1 of 18

Loading Custom Fonts

⚡JS Lightning Talk: Coding for Design Systems

Jen Chan

🔗 jenchan.biz

📦 Demo 📦 Storybook Demo

Missed my talk? More info in the slide notes ;)

2 of 18

3 of 18

4 of 18

But what if:

  • Font isn’t free?
  • Font can’t be found online?
  • Font can’t be found on a public CDN/API?
  • Your designer throws you an .eot font file ?
  • There’s a flash of unstyled font on load?
  • The original font shows up first and shifts the layout?

…???

5 of 18

Styled Components

Storybook

React

@font-face

6 of 18

Web Font File Formats

TLDR: Stick to .otf, .ttf and .woff/.woff2

Conversion Tools: Cloud Convert , FontForge, Transfonter

7 of 18

Keep it organized 🛢️

8 of 18

😩😩😩

9 of 18

Make the compiler happy

// typings/fonts.d.ts

declare module '*.woff2';

declare module '*.woff';

declare module '*.ttf';

declare module '*.otf';

// tsconfig.json

{

"compilerOptions": {

...

"include": [

"typings",

"*.d.ts"

]

}

10 of 18

// src/tokens/fonts.ts

import { ProximaNovaRegularOtf,ProximaNovaRegularTtf,ProximaNovaRegularWoff, ProximaNovaRegularWoff2 } from "../fonts";

const mainFont = "Proxima Nova";

const fallbackFontStack = "Helvetica Neue, Arial, sans-serif";

export const fontFamily = {

regular: `${mainFont}`,

bold: `${mainFont} Bold`,

};

export const fonts = {

heading: `${fontFamily.bold}, ${fallbackFontStack}`,

body: `${fontFamily.regular}, ${fallbackFontStack}`,

};

11 of 18

// tokens/fonts.ts

export const globalFonts = `

@font-face {

font-family: 'Proxima Nova';

src: url(${ProximaNovaRegularWoff2}) format('woff2'),

url(${ProximaNovaRegularWoff}) format('woff'),

url(${ProximaNovaRegularOtf}) format('opentype'),

url(${ProximaNovaRegularTtf}) format('ttf');

font-weight: 400;

font-style: normal;

font-display: optional;

fallback: ${fallbackFontStack};

}`;

Prevent layout shifts and Flash of Unstyled Text

12 of 18

What about in Storybook?

13 of 18

// .storybook/preview-head.html

<link

rel="preload"

href="./static/media/ProximaNova-Regular.woff2"

as="font"

type="font/woff2"

crossorigin

/>

...

<style type="text/css">

@font-face {

font-family: "Proxima Nova";

font-style: normal;

font-weight: 400;

src: /* Modern Browsers */ url("./static/media/ProximaNova-Regular.woff2") format("woff2"),

url("./static/media/ProximaNova-Regular.woff") format("woff"),

url("./static/media/ProximaNova-Regular.otf") format("opentype"),

/* Safari, Android, iOS */ url("./static/media/ProximaNova-Regular.ttf")

format("truetype");

font-display: optional;

}}

</style>

14 of 18

import { createGlobalStyle } from "styled-components";

import { globalFonts } from "./fonts";

const GlobalStyle = createGlobalStyle`${globalFonts}`;

function App() {

return (

<>

<GlobalStyle />

<div className="App">

<section>

<Heading as="h1">Browser default size with H1 tag</Heading>

<Heading as="h2">Browser default size H2 tag</Heading>

<Heading as="h3">Browser default size H3 tag</Heading>

</section>

</div>

</>);}

Inject the Global Styles

15 of 18

Quarter of a second on Chrome with .otf!

16 of 18

167 ms with .woff2 on Chrome

17 of 18

Throttled 3G: 5 seconds on Chrome with woff2

18 of 18