The Performance and Usability of Font Loading (Velocity Santa Clara 2015)

The Performance and Usability of Font Loading (Velocity Santa Clara 2015)

A deep dive into @font-face for Velocity 2015 in Santa Clara.

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

E1899004c71c7043343196103e210be3?s=128

zachleat

May 28, 2015
Tweet

Transcript

  1. The Performance and Usability of Font Loading Zach Leatherman @zachleat

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

  3. None
  4. THE DEFAULT BROWSER BEHAVIOR FOR FONT-LOADING IS HARMFUL TO BOTH

    THE PERCEIVED PERFORMANCE AND INTEGRITY OF CONTENT ON THE WEB.
  5. 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
  6. @zachleat zachleat.com

  7. None
  8. 47% http://httparchive.org/trends.php?s=Top1000 of the top 1000

  9. http://httparchive.org/trends.php?s=Top1000 AVERAGE PAYLOAD 97KB

  10. 0 350 700 1050 1400 CSS javaScript Images WebFonts TRANSFER

    SIZE
  11. REMOVE AN IMAGE! JAVASCRIPT SIZE? WORRIED ABOUT

  12. NOT ALL REQUESTS ARE CREATED EQUAL

  13. PERCEIVED PERFORMANCE

  14. IMG

  15. IMG

  16. None
  17. CSS

  18. None
  19. JavaScript

  20. None
  21. WEB FONT

  22. A G EN D A TRIGGER A FONT DOWNLOAD BEHAVIOR

    WHILE DOWNLOADING 1.   2.  
  23. @font-­‐face  {    font-­‐family:  The  Font  that  Could;    src:

     url('icanfont.woff2')            format('woff2'),          url('icanfont.woff')            format('woff'),          url('icanfont.otf')            format('opentype');   }
  24. WOFF2 WOFF OTF SVG

  25. WOFF2 WOFF OTF SVG

  26. WOFF2 WOFF OTF SVG T

  27. 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
  28. <!doctype  html>   <style>   @font-­‐face  {    font-­‐family:  My

     Web  Font;    src:  url('icanfont.woff2')  format('woff2'),        url('icanfont.woff')  format('woff'),        url('icanfont.otf')  format('opentype');   }   </style>  
  29. None
  30. None
  31. dAY since last pluralization ERROR 1

  32. dAY 0 since last pluralization ERROR

  33. IF NOT USED, NOT DOWNLOADED

  34. <p  style="font-­‐family:  My  Web  Font"></p> 9+

  35. <p  style="font-­‐family:  My  Web  Font">      Needs  Content.  

    </p>
  36. 8 36–42 23–28 6.1–8 2.3, 4.1 7–8 DOWNLOADS WITH EMPTY

    ATTACHED ELEMENT DOWNLOADS EVERY TIME DOWNLOADS WITH NON-EMPTY ATTACHED ELEMENT 28–37 9–11
  37. 8 36–42 23–28 6.1–8 2.3, 4.1 7–8 DOWNLOADS WITH EMPTY

    ATTACHED ELEMENT DOWNLOADS EVERY TIME DOWNLOADS WITH NON-EMPTY ATTACHED ELEMENT 28–37 9–11
  38. RESTRICT TO SPECIFIC CHARACTERS

  39. unicode- range

  40. BASIC LATIN CODE POINTS Arial Chunk Five x26 & &

    x41 A A x42 B B x43 C C x2B + + x3F ? ?
  41. @font-­‐face  {     font-­‐family:  Ampersand;     src:  url('sands.woff2')

     format('woff2'),                url('sands.woff')  format('woff'),                url('sands.ttf')  format('truetype');      unicode-­‐range:  U+26;   } unicode- range
  42. <div  style="font-­‐family:   Ampersand">Needs  Content.</div>

  43. <div  style="font-­‐family:   Ampersand">Needs  Content.</div>

  44. <div  style="font-­‐family:   Ampersand">Needs  an  &</div>

  45. Needs an _ FALLBACK Web Font

  46. unicode- range 36 9, 10, 11 23 8 4.1 8

    ALWAYS DOWNLOADS SMART DOWNLOAD NOT SUPPORTED
  47. unicode- range 36 9, 10, 11 23 8 4.1 8

    ALWAYS DOWNLOADS SMART DOWNLOAD NOT SUPPORTED
  48. USED IN DOCUMENT CONTENT FONT-WEIGHT FONT-STYLE Images courtesy of http://www.w3.org/TR/css3-fonts/

  49. USED IN DOCUMENT CONTENT FONT-WEIGHT FONT-STYLE ✔ Images courtesy of

    http://www.w3.org/TR/css3-fonts/
  50. <!doctype  html>   <style>   @font-­‐face  {    font-­‐family:  My

     Web  Font;    src:  url('icanfont.woff2')  format('woff2'),        url('icanfont.woff')  format('woff'),        url('icanfont.otf')  format('opentype');      font-­‐weight:  400;      font-­‐style:  normal;   }   </style>  
  51. <style>   p  {      font-­‐family:  My  Web  Font;

         font-­‐weight:  400;      font-­‐style:  normal;   }   </style>   <p>Roman  Text</p>
  52. @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;   }
  53. @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;   } ✔
  54. 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
  55. @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;   }
  56. 100  200  300  400  500  600  700  800  900 FONT-WEIGHT

    <p> ‐ ‑ ‐ Lighter  weights Bolder  weights
  57. 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;   }
  58. 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;   }
  59. @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;   }
  60. 100  200  300  400  500  600  700  800  900 FONT-WEIGHT

    <p> ‐ ‑ ‐ Normal/Roman  @font-­‐face Bold  @font-­‐face Faux  Bold
  61. 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;   }
  62. 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
  63. DISABLE FAUX FONTS WITH FONT-SYNTHESIS

  64. None
  65. None
  66. http://stateofwebtype.com/ STATE OF WEB TYPE

  67. <style>   @font-­‐face  {      font-­‐weight:  400;    

     font-­‐style:  normal;   }   </style>   <p>      Roman  Text      <strong>Bold  Text</strong>      <b>Bold  Text</b>      <em>Italic  Text</em>      <i>Italic  Text</i>   </p>
  68. BE FRUGAL BE

  69. BE FRUGAL BUT NOT TOO

  70. instagram.com 6 @font-face BLOCKS

  71. None
  72. None
  73. None
  74. None
  75. None
  76. None
  77. <i>

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

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

  80. i,  cite,  em,  var,   address,  dfn,   strong,  b,

     h1,  h2,   h3,  h4,  h5,  h6,  th
  81. USED IN DOCUMENT CONTENT FONT-WEIGHT FONT-STYLE Images courtesy of http://www.w3.org/TR/css3-fonts/

  82. USED IN DOCUMENT CONTENT FONT-WEIGHT FONT-STYLE ✔ Images courtesy of

    http://www.w3.org/TR/css3-fonts/ ✔ ✔
  83. A G EN D A TRIGGER A FONT DOWNLOAD BEHAVIOR

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

    WHILE DOWNLOADING 1.   2.  
  85. FONT FINISHES LOADING A B FONT STARTS LOADING @FONT-FACE IS

    PARSED
  86. FONT FINISHES LOADING A B FONT STARTS LOADING @FONT-FACE IS

    PARSED
  87. LOCAL FONT { @FONT-FACE { A

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

  89. Flash of Invisible Text F O I T

  90. FOIT

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

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

  93. 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 “
  94. None
  95. None
  96. None
  97. https://twitter.com/zoompf/status/578901383253995520

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

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

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

  101. LOCAL FONT { @FONT-FACE { A

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

  103. Flash of UNSTYLED Text F O U T

  104. FOUT

  105. IS 3 SECONDS A GOOD TIMEOUT?

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

  107. NOT JUST A PERFORMANCE PROBLEM

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

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

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

  111. http://httparchive.org/trends.php?s=Top1000 of the top 1000

  112. 47% http://httparchive.org/trends.php?s=Top1000 of the top 1000

  113. None
  114. None
  115. LOCAL FONT { @FONT-FACE {

  116. LOCAL FONT { @FONT-FACE {

  117. FOUT FOIT REVIEW

  118. FOIT

  119. ABCDEFGH FOIT @FONT-FACE LOAD

  120. FOIT to FOUT, 3 seconds

  121. 3 S ABCDEFGH FOIT to FOUT, 3 seconds

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

  123. FOUT, 0 seconds ABCDEFGH

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

  125. “But FOUT is ugly.”

  126. PNG BASELINE JPEG Progressive JPEG

  127. PNG BASELINE JPEG Progressive JPEG

  128. WebPageTest.org

  129. SOLUTION CONTINUUM

  130. FOUT DO NOTHING EMBRACE BROWSER DEFAULTS 0 SECOND TIMEOUT FOUT

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

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

    FOIT N SECOND TIMEOUT FOIT InFINITE TIMEOUT N  >  0
  133. DO NOTHING EMBRACE BROWSER DEFAULTS FOIT InFINITE TIMEOUT FONT REQUESTs

    ARE A SINGLE POINT OF FAILURE
  134. STOP BUTTON HAS NO EFFECT

  135. ANTI- PATTERNS

  136. CSS ONLOAD

  137. <style>   h1  {  font-­‐family:  serif;  }   .loaded  h1

     {  font-­‐family:  My  Web  Font;  }   </style>   <link  href="fonts.css"   onload="document.body.className+='   loaded';"  rel="stylesheet">  
  138. @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;   }
  139. None
  140. BLOCKING FONTS.CSS Blocking FONT REQUESTS

  141. BLOCKING FONTS.CSS Blocking FONT REQUESTS A Fonts   start  

    loading
  142. BLOCKING FONTS.CSS Blocking FONT REQUESTS onload A Fonts   start

      loading
  143. BLOCKING FONTS.CSS Blocking FONT REQUESTS onload Fonts   finish  

    loading B A Fonts   start   loading
  144. ASYNC- CSS

  145. <style>   h1  {  font-­‐family:  serif;  }   .loaded  h1

     {  font-­‐family:  My  Web  Font;  }   </style>   <link  href="fonts.css"  media="none"   onload="document.body.className+='   loaded';  this.media='all'"   rel="stylesheet">  
  146. BLOCKING FONTS.CSS

  147. ASYNC FONTS.CSS

  148. ASYNC FONTS.CSS Blocking FONT REQUESTS

  149. ASYNC FONTS.CSS Blocking FONT REQUESTS A Fonts   start  

    loading
  150. ASYNC FONTS.CSS Blocking FONT REQUESTS onload A Fonts   start

      loading
  151. ASYNC FONTS.CSS Blocking FONT REQUESTS onload Fonts   finish  

    loading B A Fonts   start   loading
  152. filamentgroup / loadcss https://github.com/filamentgroup/loadCSS

  153. @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;   }
  154. None
  155. ASYNC FONTS.CSS Font  Data  URIs   finish   loading B

    A Font  Data  URIs   start   loading REPAINT
  156. None
  157. None
  158. None
  159. ONE 50KB CSS REQUEST NO FONT REQUESTS

  160. @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;   }
  161. FOUT 0 SECOND TIMEOUT FOUT FOIT N SECOND TIMEOUT N

     >  0 EMBRACE MORE FOUT
  162. font-rendering CSS PROPERTY https://github.com/KenjiBaheux/css-font-rendering from Kenji Baheux, Ilya Grigorik, David

    Kuettel, Tab Atkins
  163. CSS Font Loading http://dev.w3.org/csswg/css-font-loading/

  164. FONTFACEONLOAD github.com/zachleat/fontfaceonload USES THE CSS FONT LOADING API WHEN AVAILABLE.

    FONTFACEOBSERVER github.com/bramstein/fontfaceobserver/ INCLUDES A NICE PROMISES POLYFILL
  165. 0 SECOND TIMEOUT FOUT

  166. var  doc  =  document,          docEl  =

     doc.documentElement;   doc.fonts.load("1em  Raleway")    .then(function()  {          //  The  font  has  loaded.      docEl.className  +=  "  raleway-­‐loaded";    }); ‑
  167. body  {      font-­‐family:  sans-­‐serif;   }   .raleway-­‐loaded

     body  {      font-­‐family:  Raleway,  sans-­‐serif;   } ‑
  168. None
  169. FONT REQUEST

  170. FONT REQUEST A Font   starts   loading

  171. FONT REQUEST Font   finishes   loading B A Font

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

    Font   starts   loading
  173. FOUT RALEWAY font-­‐rendering:  block  0s;

  174. FOUT @FONT-FACE LOAD font-­‐rendering:  block  0s;

  175. FOUT FOIT N SECOND TIMEOUT N  >  0

  176. 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";   });   ‑
  177. .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;   } ‑
  178. FOIT to FOUT, 1 second font-­‐rendering:  block  1s   swap

     infinite;
  179. 1 S FOIT to FOUT, 1 second font-­‐rendering:  block  1s

      swap  infinite; RALEWAY
  180. 1 S FOIT to FOUT, 1 second @FONT-FACE LOAD font-­‐rendering:

     block  1s   swap  infinite;
  181. https://twitter.com/jmuspratt/status/561239961924403200

  182. ONE REPAINT TO RULE THEM ALL

  183. 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
  184. None
  185. FONT REQUESTS

  186. FONT REQUESTS A Fonts   start   loading

  187. FONT REQUESTS Fonts   finish   loading B A Fonts

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

    Fonts   start   loading
  189. TWO REPAINTS TO RULE THEM ALL

  190. None
  191. MOST  JARRING   REPAINT  FOR  ROMAN ROMAN

  192. MOST  JARRING   REPAINT  FOR  ROMAN BOLD ITALIC BOLD  ITALIC

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

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

    FAUX   VERSIONS FINAL  REPAINT ROMAN
  195. ARIAL ARIAL BOLD

  196. EXO EXO FAUX BOLD

  197. EXO EXO BOLD

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

  199. MINIMIZE THE FALLBACK to WEBFONT REFLOW

  200. font-­‐family FALLBACK STYLE

  201. fontfamily.io

  202. font-­‐family   FALLBACK STYLE

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

  204. 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/
  205. THERE ARE A LOT OF TOOLS AT OUR DISPOSAL TO

    EASE THE TRANSITION FROM FALLBACK TO WEBFONT
  206. None
  207. THE DEFAULT BROWSER BEHAVIOR FOR FONT-LOADING IS HARMFUL TO BOTH

    THE PERCEIVED PERFORMANCE AND INTEGRITY OF CONTENT ON THE WEB.
  208. 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
  209. USE A FONT LOADING STRATEGY.

  210. DON’t ACCEPT THE DEFAULTS.

  211. @zachleat zachleat.com