Files
unicorn-utterances/content/blog/angular-npm-font-usage/index.md
2020-11-15 16:25:18 -08:00

5.6 KiB

title, description, published, authors, tags, attached, license
title description published authors tags attached license
Package Font Files on NPM for Angular Usage 2020-11-15T22:12:03.284Z
crutchcorn
angular
javascript
npm
cc-by-4

While working on my company's shared component system, I got a request from our design team. They wanted to keep our branding consistent with internal documents and other assets. As such, they requested we use a font called "Stirling Foundry".

While we're prepping our shared component system for an open-source release to the public, we quickly acknowledged that we couldn't possibly ship this font with the package we intend for public publishing due to it's licensing and cost.

However, we have mutliple teams that rely on our shared component system and we don't want to have to copy+paste the relevant @font-face definition or font files. What was our solution? Ship a second npm package (in our internal npm registry) that contained all of our private assets - including font files.

Let's walk through how we did that.

Setup Assets Package

As we're wanting to ship our packages seperately, we opted for two Git repositories for the component system and private assets. In a new repository, I have the following for the package.json:

{
  "name": "ecp-private-assets",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "release": "standard-version"
  },
  "devDependencies": {
    "@commitlint/cli": "^11.0.0",
    "@commitlint/config-angular": "^11.0.0",
    "husky": "^4.3.0",
    "standard-version": "^9.0.0"
  },
  "husky": {
    "hooks": {
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  },
  "commitlint": {
    "extends": [
      "@commitlint/config-angular"
    ]
  }
}

While this package is not going to maintain code, I still believe it important to maintain a semver for the package. If a path of the package changes, the semver will communicate that with your package's consumers alongside the changeling. As such, this package.json utilizes Conventional Commit and commitlint to auto-generate changelogs and maintain history version.

Add Font Files

The "Foundry Stirling" font that I'm shipping is a combination of 7 .otf files. I start by creating a fonts directory. Inside that directory, I place the .otf files in the fonts directory.

Once done, your project repo should look something like this:

.
├── CHANGELOG.md
├── README.md
├── fonts
│   ├── foundry_sterling_bold.otf
│   ├── foundry_sterling_book.otf
│   ├── foundry_sterling_book_italic.otf
│   ├── foundry_sterling_demi.otf
│   ├── foundry_sterling_extra_bold.otf
│   ├── foundry_sterling_light.otf
│   └── foundry_sterling_medium.otf
├── index.js
├── package-lock.json
└── package.json

@font-face CSS Definition

Now that we have the fonts in their place, we need to create a common foundry_stirling.css file to access those fonts from CSS.

Because we're planning on using Angular CLI, we'll want to set the src property to be prefixed with /assets/, since that's where Angular sends it's assets.

/* foundry_stirling.css */

@font-face {
    font-family: 'Foundry Sterling';
    font-style: normal;
    /* Light */
    font-weight: 300;
    src: local('Foundry Sterling Light'), local('FoundrySterling-light'), url("/assets/foundry_sterling_light.otf") format('opentype')
}

/* ... */

@font-face {
    font-family: 'Foundry Sterling';
    font-style: normal;
    /* Extra-Bold */
    font-weight: 800;
    src: local('Foundry Sterling Extra Bold'), local('FoundrySterling-extra-bold'), url("/assets/foundry_sterling_extra_bold.otf") format('opentype')
}

While we're using CSS here, if you wanted to set the src to a different location for non-Angular projects, you could use a SCSS @mixin to define the @font-face declarations with a customizable $base_path.

@mixin foundry_sterling($base_path) {
@font-face {
 font-family: 'Foundry Sterling';
 font-style: normal;
 /* Extra-Bold */
 font-weight: 800;
 src: url("#{$base_path}/foundry_sterling_extra_bold.otf") format('opentype')
}

// ... Other @font-face declarations
}

Then, when consuming the package in your client-side app, you'll want to use something like this:

@include foundry_sterling("/assets")

Font Name Value Mapping

Because our font had multiple files to declare the different CSS values weights, we had to declare the @font-face for each of the font files. This is the mapping we used:

Value Common weight name Related File
100 Thin / Hairline N/A
200 Extra-Light / Ultra-Light N/A
300 Light foundry_sterling_light.otf
400 Normal / Regular foundry_sterling_book.otf
500 Medium foundry_sterling_medium.otf
600 Semi-Bold / Demi-Bold foundry_sterling_demi.otf
700 Bold foundry_sterling_bold.otf
800 Extra-Bold / Ultra-Bold foundry_sterling_extra_bold.otf
900 Black / Heavy N/A

Consume Assets Package in Angular CLI