Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Performance and Usability of Font Loading (Velocity NYC 2015)

zachleat
October 13, 2015

The Performance and Usability of Font Loading (Velocity NYC 2015)

A deep dive into @font-face for Velocity 2015 in New York City.

http://velocityconf.com/devops-web-performance-ny-2015/public/schedule/detail/46234

zachleat

October 13, 2015
Tweet

More Decks by zachleat

Other Decks in Programming

Transcript

  1. The Performance and
    Usability of Web Fonts
    Zach Leatherman
    @zachleat

    View Slide

  2. @zachleat
    zachleat.com

    View Slide

  3. View Slide

  4. N C

    T
    @

    View Slide

  5. N T
    O
    F C
    A
    F E
    @ -

    View Slide

  6. THE DEFAULT
    BROWSER BEHAVIOR
    FOR FONT-LOADING
    IS HARMFUL TO BOTH
    THE PERCEIVED PERFORMANCE
    AND INTEGRITY OF
    CONTENT ON THE WEB.
    FONT-LOADING
    INTEGRITY
    PERCEIVED PERFORMANCE

    View Slide

  7. 56%
    http://httparchive.org/trends.php
    OF WEB SITES

    View Slide

  8. http://httparchive.org/trends.php
    AVERAGE PAYLOAD
    105KB

    View Slide

  9. 0
    350
    700
    1050
    1400
    CSS javaScript Images WebFonts
    TRANSFER
    SIZE

    View Slide

  10. REMOVE AN IMAGE!
    JAVASCRIPT SIZE?
    WORRIED ABOUT

    View Slide

  11. NOT ALL
    REQUESTS
    ARE CREATED
    EQUAL

    View Slide

  12. PERCEIVED
    PERFORMANCE

    View Slide

  13. IMG

    View Slide

  14. CSS

    View Slide

  15. JavaScript

    View Slide

  16. WEB FONT

    View Slide

  17. A
    G
    EN
    D
    A
    TRIGGER A FONT DOWNLOAD
    BEHAVIOR WHILE DOWNLOADING
    1.  
    2.  

    View Slide

  18. @font-­‐face  {  
     font-­‐family:  The  Font  that  Could;  
     src:  url('icanfont.woff2')  
             format('woff2'),  
           url('icanfont.woff')  
             format('woff'),  
           url('icanfont.otf')  
             format('opentype');  
    }

    View Slide

  19. WOFF2
    WOFF
    OTF
    SVG
    T 2.3–4.3

    View Slide

  20. WOFF2
    WOFF

    View Slide

  21. IS
    30%
    SMALLER
    THAN WOFF
    On average across all of Google Fonts:
    https://groups.google.com/a/chromium.org/forum/#!topic/chromium-dev/j27Ou4RtvQI/discussion
    WOFF2

    View Slide

  22.  
     <br/>@font-­‐face  {  <br/>  font-­‐family:  My  Web  Font;  <br/>  src:  url('icanfont.woff2')  format('woff2'),  <br/>      url('icanfont.woff')  format('woff');  <br/>}  <br/>  

    View Slide

  23. View Slide

  24. dAY
    since last
    pluralization ERROR
    1

    View Slide

  25. dAY
    0
    since last
    pluralization ERROR

    View Slide

  26. IF NOT USED,
    NOT DOWNLOADED

    View Slide


  27. 9+

    View Slide

  28.  
       Needs  Content.  

    View Slide

  29. 8
    36+
    23+
    6.1+
    2.3+
    7+
    DOWNLOADS WITH
    EMPTY
    ATTACHED ELEMENT
    DOWNLOADS
    EVERY TIME
    DOWNLOADS WITH
    NON-EMPTY
    ATTACHED ELEMENT
    28+
    9+ &

    View Slide

  30. RESTRICT TO
    SPECIFIC
    CHARACTERS

    View Slide

  31. unicode-
    range

    View Slide

  32. BASIC
    LATIN
    CODE
    POINTS Arial Chunk Five
    x26 & &
    x41 A A
    x42 B B
    x43 C C
    x2B + +
    x3F ? ?

    View Slide

  33. @font-­‐face  {  
      font-­‐family:  Ampersand;  
      src:  url('sands.woff2')  format('woff2'),  
                 url('sands.woff')  format('woff');  
       unicode-­‐range:  U+26;  
    }
    unicode-
    range

    View Slide

  34. Ampersand">Needs  Content.

    View Slide

  35. Ampersand">Needs  an  &

    View Slide

  36. Needs an _
    FALLBACK
    Web Font

    View Slide

  37. unicode-
    range
    36
    9+
    23
    8+
    2.1+
    8+
    ALWAYS DOWNLOADS SMART DOWNLOAD
    NOT SUPPORTED
    &

    View Slide

  38. Matching Font-Family
    USED IN DOCUMENT CONTENT
    FONT-WEIGHT
    FONT-STYLE

    Images courtesy of http://www.w3.org/TR/css3-fonts/

    View Slide

  39.  
     <br/>@font-­‐face  {  <br/>  font-­‐family:  My  Web  Font;  <br/>  src:  url('icanfont.woff2')  format('woff2'),  <br/>      url('icanfont.woff')  format('woff');  <br/>    font-­‐weight:  400;  <br/>    font-­‐style:  normal;  <br/>}  <br/>  

    View Slide

  40.  <br/>p  {  <br/>    font-­‐family:  My  Web  Font;  <br/>    font-­‐weight:  400;  <br/>    font-­‐style:  normal;  <br/>}  <br/>  
    Roman  Text

    View Slide

  41. @font-­‐face  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  400;  
       font-­‐style:  normal;  
    }
    p  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  400;  
       font-­‐style:  normal;  
    }

    View Slide

  42. @font-­‐face  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  400;  
       font-­‐style:  normal;  
    }
    p  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  400;  
       font-­‐style:  normal;  
    }

    View Slide

  43. 100  200  300  400  500  600  700  800  900
    FONT-WEIGHT
    DEFAULT  CSS  
    font-­‐weight:  normal;
    DEFAULT  CSS  
    font-­‐weight:  bold;

    ‑ ‑

    Lighter  weights Bolder  weights

    View Slide

  44. @font-­‐face  {  font-­‐weight:  500;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  400;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  300;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  200;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  100;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  600;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  700;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  800;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  900;  font-­‐style:  normal;  }  
    /*  REPEAT  THE  SAME,  WITH  font-­‐style:  italic;  */
    p  {  
       font-­‐weight:  500;  
       font-­‐style:  normal;  
    }

    View Slide

  45. 100  200  300  400  500  600  700  800  900
    FONT-WEIGHT




    Lighter  weights Bolder  weights

    View Slide

  46. MisMatch weight
    600 Available, 100 assigned, FORCED BOLD
    p  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  100;  
       font-­‐style:  normal;  
    }
    @font-­‐face  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  600;  
       font-­‐style:  normal;  
    }

    View Slide

  47. MISMATCH STYLE
    ITALIC AVAILABLE, NORMAL ASSIGNED, FORCED ITALIC
    p  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  400;  
       font-­‐style:  normal;  
    }
    @font-­‐face  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  400;  
       font-­‐style:  italic;  
    }

    View Slide

  48. @font-­‐face  {  font-­‐weight:  600;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  700;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  800;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  900;  font-­‐style:  normal;  }  
    /*  FAUX  BOLD  */  
    @font-­‐face  {  font-­‐weight:  500;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  400;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  300;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  200;  font-­‐style:  normal;  }  
    @font-­‐face  {  font-­‐weight:  100;  font-­‐style:  normal;  }  
    /*  END  FAUX  BOLD  */  
    /*  REPEAT  THE  SAME,  WITH  font-­‐style:  italic;  */
    p  {  
       font-­‐weight:  600;  
       font-­‐style:  normal;  
    }

    View Slide

  49. 100  200  300  400  500  600  700  800  900
    FONT-WEIGHT




    Normal/Roman  @font-­‐face Bold  @font-­‐face
    Faux  Bold

    View Slide

  50. MisMatch weight
    500 Available, 600 assigned, FAUX BOLD
    p  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  600;  
       font-­‐style:  normal;  
    }
    @font-­‐face  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  500;  
       font-­‐style:  normal;  
    }

    View Slide

  51. MISMATCH STYLE
    p  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  400;  
       font-­‐style:  italic;  
    }
    @font-­‐face  {  
       font-­‐family:  My  Web  Font;  
       font-­‐weight:  400;  
       font-­‐style:  normal;  
    }
    NORMAL AVAILABLE, ITALIC ASSIGNED, FAUX ITALIC

    View Slide

  52. DISABLE FAUX FONTS WITH
    FONT-SYNTHESIS

    View Slide

  53. View Slide

  54. http://stateofwebtype.com/
    STATE OF
    WEB TYPE

    View Slide

  55.  <br/>@font-­‐face  {  <br/>    font-­‐weight:  400;  <br/>    font-­‐style:  normal;  <br/>}  <br/>  
     
       Roman  Text  
       Bold  Text  
       Bold  Text  
       Italic  Text  
       Italic  Text  

    View Slide

  56. BE FRUGAL
    BE

    View Slide

  57. BE FRUGAL
    BUT NOT TOO

    View Slide

  58. instagram.com
    6 @font-face BLOCKS

    View Slide

  59. View Slide

  60. View Slide

  61. View Slide

  62. View Slide

  63. View Slide


  64. View Slide

  65. .page-­‐home  .content  .home-­‐login  i  {  
       font-­‐style:  normal;  
    }

    View Slide

  66. SAVES 13.4KB
    FOR EACH EMPTY-CACHE PAGELOAD
    TO INSTAGRAM.COM

    View Slide

  67. i,  cite,  em,  var,  
    address,  dfn,  
    strong,  b,  h1,  h2,  
    h3,  h4,  h5,  h6,  th

    View Slide

  68. Matching Font-Family
    USED IN DOCUMENT CONTENT
    FONT-WEIGHT
    FONT-STYLE

    Images courtesy of http://www.w3.org/TR/css3-fonts/



    View Slide

  69. A
    G
    EN
    D
    A
    TRIGGER A FONT DOWNLOAD
    BEHAVIOR WHILE DOWNLOADING
    1.  
    2.  

    View Slide

  70. FONT FINISHES LOADING
    A
    B
    FONT IS USED, STARTS LOADING
    @FONT-FACE IS PARSED

    View Slide

  71. FONT FINISHES LOADING
    A
    B
    FONT IS USED, STARTS LOADING
    @FONT-FACE IS PARSED

    View Slide

  72. LOCAL FONT
    {
    @FONT-FACE
    { A B

    View Slide

  73. Flash of Invisible Text
    F O I T

    View Slide

  74. FOIT

    View Slide

  75. http://www.webpagetest.org/video/compare.php?tests=141205_VE_STK-r:1-c:0

    View Slide

  76. http://www.webpagetest.org/video/compare.php?tests=141205_VE_STK-r:1-c:0

    View Slide

  77. People will visit a Web site less often
    if it is slower than a close competitor
    by more than 250 milliseconds.”
    http://www.nytimes.com/2012/03/01/technology/impatient-web-users-flee-slow-loading-sites.html

    View Slide

  78. View Slide

  79. View Slide

  80. View Slide

  81. https://twitter.com/zoompf/status/578901383253995520

    View Slide

  82. http://www.webpagetest.org/video/compare.php?tests=141209_AY_Z79-r:1-c:0

    View Slide

  83. http://www.webpagetest.org/video/compare.php?tests=141209_AY_Z79-r:1-c:0

    View Slide

  84. http://www.webpagetest.org/video/compare.php?tests=141209_AY_Z79-r:1-c:0

    View Slide

  85. LOCAL FONT
    {
    @FONT-FACE
    { A 3s B

    View Slide

  86. Flash of UNSTYLED Text
    F O U T

    View Slide

  87. FOUT

    View Slide

  88. IS 3 SECONDS
    A GOOD TIMEOUT?

    View Slide

  89. https://twitter.com/zoompf/status/578901383253995520

    View Slide

  90. NOT JUST A
    PERFORMANCE
    PROBLEM

    View Slide

  91. https://twitter.com/jmuspratt/status/561239961924403200

    View Slide

  92. https://twitter.com/jmuspratt/status/561239961924403200

    View Slide

  93. https://twitter.com/jmuspratt/status/561239961924403200

    View Slide

  94. View Slide

  95. View Slide

  96. LOCAL FONT
    {
    @FONT-FACE
    {

    View Slide

  97. FOUT
    FOIT
    REVIEW

    View Slide

  98. FOIT

    View Slide

  99. ABCDEFGH
    FOIT
    @FONT-FACE LOAD

    View Slide

  100. FOIT to FOUT, 3 seconds

    View Slide

  101. 3 S
    ABCDEFGH
    FOIT to FOUT, 3 seconds

    View Slide

  102. 3 S
    ABCDEFGH
    FOIT to FOUT, 3 seconds
    @FONT-FACE LOAD

    View Slide

  103. FOUT, 0 seconds
    ABCDEFGH

    View Slide

  104. ABCDEFGH
    FOUT, 0 seconds
    @FONT-FACE LOAD

    View Slide

  105. “But FOUT is ugly.”

    View Slide

  106. PNG
    BASELINE
    JPEG
    Progressive
    JPEG

    View Slide

  107. WebPageTest.org

    View Slide

  108. SOLUTION
    CONTINUUM

    View Slide

  109. FOUT
    DO
    NOTHING
    EMBRACE
    BROWSER
    DEFAULTS
    0 SECOND
    TIMEOUT
    FOUT
    FOIT
    N SECOND
    TIMEOUT
    FOIT
    InFINITE
    TIMEOUT
    N  >  0

    View Slide

  110. DO
    NOTHING
    EMBRACE
    BROWSER
    DEFAULTS
    FOIT
    InFINITE
    TIMEOUT
    FONT REQUESTs ARE A
    SINGLE
    POINT OF
    FAILURE

    View Slide

  111. STOP BUTTON HAS
    NO EFFECT

    View Slide

  112. ANTI-
    PATTERNS

    View Slide

  113. CSS
    ONLOAD

    View Slide

  114.  <br/>h1  {  font-­‐family:  serif;  }  <br/>.loaded  h1  {  font-­‐family:  My  Web  Font;  }  <br/>  
    onload="document.body.className+='  
    loaded';"  rel="stylesheet">  

    View Slide

  115. @font-­‐face  {  
       font-­‐family:  My  Web  Font;  
       src:  url('icanfont.woff')  format('woff');  
    }  
    @font-­‐face  {  
       font-­‐family:  My  Web  Font;  
       src:  url('icanfontbold.woff')  format('woff');  
       font-­‐weight:  700;  
    }

    View Slide

  116. BLOCKING
    FONTS.CSS
    Blocking
    FONT REQUESTS

    View Slide

  117. BLOCKING
    FONTS.CSS
    Blocking
    FONT REQUESTS
    A Fonts  
    start  
    loading

    View Slide

  118. BLOCKING
    FONTS.CSS
    Blocking
    FONT REQUESTS
    onload
    Fonts  
    finish  
    loading
    B
    A Fonts  
    start  
    loading

    View Slide

  119. ASYNC-
    CSS

    View Slide

  120.  <br/>h1  {  font-­‐family:  serif;  }  <br/>.loaded  h1  {  font-­‐family:  My  Web  Font;  }  <br/>  
    onload="document.body.className+='  
    loaded';  this.media='all'"  
    rel="stylesheet">  

    View Slide

  121. BLOCKING
    FONTS.CSS

    View Slide

  122. ASYNC
    FONTS.CSS

    View Slide

  123. ASYNC
    FONTS.CSS
    Blocking
    FONT REQUESTS
    onload
    Fonts  
    finish  
    loading
    B
    A Fonts  
    start  
    loading

    View Slide

  124. filamentgroup / loadcss
    https://github.com/filamentgroup/loadCSS

    View Slide

  125. ASYNC-
    CSS
    with
    DATA
    URIS

    View Slide

  126. @font-­‐face  {  
       font-­‐family:  My  Web  Font;  
       src:  url('data:application/x-­‐font-­‐
    woff;charset=utf-­‐8;base64,...')  format('woff');  
    }  
    @font-­‐face  {  
       font-­‐family:  My  Web  Font;  
       src:  url('data:application/x-­‐font-­‐
    woff;charset=utf-­‐8;base64,...')  format('woff');  
       font-­‐weight:  700;  
    }

    View Slide

  127. ASYNC
    FONTS.CSS
    Font  Data  URIs  
    finish  
    loading
    B
    A Font  Data  URIs  
    start  
    loading
    REPAINT

    View Slide

  128. View Slide

  129. View Slide

  130. INLINE DATA URIS WITH
    MAIN CSS

    View Slide

  131. View Slide

  132. ONE 50KB CSS REQUEST
    NO FONT REQUESTS

    View Slide

  133. @font-­‐face  {  
       font-­‐family:  Roboto;  
       src:  url('data:application/x-­‐font-­‐
    woff;charset=utf-­‐8;base64,...')  format('woff');  
    }  
    @font-­‐face  {  
       font-­‐family:  Roboto;  
       src:  url('data:application/x-­‐font-­‐
    woff;charset=utf-­‐8;base64,...')  format('woff');  
       font-­‐weight:  700;  
    }

    View Slide

  134. FOUT
    0 SECOND
    TIMEOUT
    FOUT
    FOIT
    N SECOND
    TIMEOUT
    N  >  0
    EMBRACE MORE
    FOUT

    View Slide

  135. font-DISPLAY CSS DESCRIPTOR
    https://tabatkins.github.io/specs/css-font-display/
    from Kenji Baheux, Tab Atkins

    View Slide

  136. CSS Font Loading
    http://dev.w3.org/csswg/css-font-loading/

    View Slide

  137. FONTFACEONLOAD
    github.com/zachleat/fontfaceonload
    USES THE CSS FONT LOADING API WHEN AVAILABLE.
    FONTFACEOBSERVER
    github.com/bramstein/fontfaceobserver/
    INCLUDES A NICE PROMISES POLYFILL

    View Slide

  138. 0 SECOND
    TIMEOUT
    FOUT

    View Slide

  139. var  doc  =  document,  
           docEl  =  doc.documentElement;  
    doc.fonts.load("1em  Raleway")  
     .then(function()  {  
           //  The  font  has  loaded.  
       docEl.className  +=  "  raleway-­‐loaded";  
     });

    View Slide

  140. body  {  
       font-­‐family:  sans-­‐serif;  
    }  
    .raleway-­‐loaded  body  {  
       font-­‐family:  Raleway,  sans-­‐serif;  
    }

    View Slide

  141. FONT REQUEST
    REPAINT
    Font  
    finishes  
    loading
    B
    A Font  
    starts  
    loading

    View Slide

  142. FOUT
    RALEWAY
    font-­‐display:  swap;

    View Slide

  143. FOUT
    @FONT-FACE LOAD
    font-­‐display:  swap;

    View Slide

  144. FOUT
    FOIT
    N SECOND
    TIMEOUT
    N  >  0

    View Slide

  145. var  docEl  =  document.documentElement;  
    docEl.className  +=  "  raleway-­‐loading";  
    window.setTimeout(function()  {  
       docEl.className  +=  "  raleway-­‐fallback";  
    },  1000);  
    document.fonts.load("1em  Raleway").then(function()  {  
       docEl.className  +=  "  raleway-­‐loaded";  
    });  

    View Slide

  146. .raleway-­‐loading  body  {  
       color:  transparent;  
    }  
    .raleway-­‐fallback  body,  
    .raleway-­‐loaded  body  {  
       color:  inherit;  
    }  
    .raleway-­‐fallback  body  {  
       font-­‐family:  serif;  
    }  
    .raleway-­‐loaded  body  {  
       font-­‐family:  Raleway,  serif;  
    }

    View Slide

  147. FOIT to FOUT, 1 second

    View Slide

  148. 1 S
    FOIT to FOUT, 1 second
    RALEWAY

    View Slide

  149. 1 S
    FOIT to FOUT, 1 second
    @FONT-FACE LOAD

    View Slide

  150. https://twitter.com/jmuspratt/status/561239961924403200

    View Slide

  151. ONE REPAINT
    TO RULE THEM ALL

    View Slide

  152. Promise.all([  
       document.fonts.load("400  1em  Raleway"),  
       document.fonts.load("700  1em  Raleway")  
    ]).then(function  ()  {  
       docEl.className  +=  "  raleway-­‐loaded";  
    });

    document.fonts.load("1em  Raleway").then(function()  {  
       docEl.className  +=  "  raleway-­‐loaded";  
    });
    BECOMES

    View Slide

  153. FONT REQUESTS

    View Slide

  154. FONT REQUESTS
    REPAINT
    Fonts  
    finish  
    loading
    B
    A Fonts  
    start  
    loading

    View Slide

  155. TWO REPAINTS
    TO RULE THEM ALL

    View Slide

  156. MOST  JARRING  
    REPAINT  FOR  ROMAN
    ROMAN

    View Slide

  157. MOST  JARRING  
    REPAINT  FOR  ROMAN
    BOLD
    ITALIC
    BOLD  ITALIC
    ROMAN

    View Slide

  158. MOST  JARRING  
    REPAINT  FOR  ROMAN
    BOLD
    ITALIC
    BOLD  ITALIC
    FAUX  
    VERSIONS
    ROMAN

    View Slide

  159. MOST  JARRING  
    REPAINT  FOR  ROMAN
    BOLD
    ITALIC
    BOLD  ITALIC
    FAUX  
    VERSIONS
    FINAL  REPAINT
    ROMAN

    View Slide

  160. ARIAL ARIAL BOLD

    View Slide

  161. EXO EXO FAUX BOLD

    View Slide

  162. EXO EXO BOLD

    View Slide

  163. FLASH OF FAUX TEXT
    zachleat.com/web/foft/

    View Slide

  164. FALLBACKS ARE
    IMPORTANT

    View Slide

  165. View Slide

  166. View Slide

  167. fontfamily.io

    View Slide

  168. MINIMIZE THE
    FALLBACK
    to
    WEBFONT
    REFLOW

    View Slide

  169. font-­‐family  
    FALLBACK STYLE
    font-­‐size  
    font-­‐size-­‐adjust  
    line-­‐height

    View Slide

  170. Web Font Tune-up Time:
    A Fun Font Fallback Event
    http://blog.fonts.com/2011/08/web-font-tune-up-
    time-a-fun-font-fallback-event/

    View Slide

  171. View Slide

  172. View Slide

  173. THERE ARE A LOT OF TOOLS
    AT OUR DISPOSAL
    TO EASE THE TRANSITION
    FROM FALLBACK
    TO WEBFONT

    View Slide

  174. THE DEFAULT
    BROWSER BEHAVIOR
    FOR FONT-LOADING
    IS HARMFUL TO BOTH
    THE PERCEIVED PERFORMANCE
    AND INTEGRITY OF
    CONTENT ON THE WEB.
    FONT-LOADING
    INTEGRITY
    PERCEIVED PERFORMANCE

    View Slide

  175. USE A
    FONT LOADING
    STRATEGY.

    View Slide

  176. DON’t ACCEPT
    THE DEFAULTS.

    View Slide

  177. @zachleat
    zachleat.com

    View Slide