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

CSS and the First Meaningful Paint - All day Hey!, April 2017

CSS and the First Meaningful Paint - All day Hey!, April 2017

To render a webpage browsers needs to go through the complex dance of networking, parsing and painting before any content can be displayed to your user. Over the years, we've developed mechanisms and hacks to aid the browser at each stage of this process, but these have always come at some cost or trade-off.

How can we utilize modern web platform features to load our CSS as fast as possible? Should we still be inlining our critical content into the document or instead, how can HTTP/2 server push and Service Workers help us?

In this talk we will take a journey exploring the current, past, and future best-practices for loading CSS in the browser and how we can achieve a first meaningful paint within 1000ms. Ultimately creating a faster, more resilient experience for our users.

Patrick Hamann

April 24, 2017
Tweet

More Decks by Patrick Hamann

Other Decks in Technology

Transcript

  1. Name of Presentation
    CSS and the:
    First meaningful paint
    All Day Hey, April 2017

    Patrick Hamann
    @patrickhamann

    View Slide

  2. View Slide

  3. Name of Presentation
    Why?

    View Slide

  4. CSS and the first meaningful paint @patrickhamann
    How fast is your website?

    View Slide

  5. CSS and the first meaningful paint @patrickhamann
    What is the golden
    performance metric?

    View Slide

  6. CSS and the first meaningful paint @patrickhamann
    Does it even exist…
    Should it even exist?

    View Slide

  7. CSS and the first meaningful paint @patrickhamann
    How can we measure the
    perception and experience of
    our real users?

    View Slide

  8. CSS and the first meaningful paint
    • First byte

    • Document complete

    • Load event

    • Requests

    • Start render

    • SpeedIndex

    • First meaningful paint

    • Interactivity

    • Custom…

    Old New

    View Slide

  9. CSS and the first meaningful paint @patrickhamann
    WTF is TTFMP ?

    View Slide

  10. CSS and the first meaningful paint @patrickhamann
    First Meaningful Paint is the time when a
    page’s primary content appeared on the
    screen.

    View Slide

  11. CSS and the first meaningful paint @patrickhamann
    First Meaningful Paint is the first paint after
    which the biggest above-the-fold layout
    change has happened, and web fonts have
    loaded.

    View Slide

  12. CSS and the first meaningful paint @patrickhamann
    A bold statement

    View Slide

  13. https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI

    View Slide

  14. # of layout objects
    Timeline

    View Slide

  15. CSS and the first meaningful paint @patrickhamann
    A bold statement

    View Slide

  16. CSS and the first meaningful paint @patrickhamann
    A bold statement

    View Slide

  17. https://developers.google.com/web/tools/lighthouse/

    View Slide

  18. Name of Presentation
    Optimising for TTFMP
    A case-study: FT.com

    View Slide

  19. View Slide

  20. https://www.webpagetest.org/
    Test on real devices
    Real network conditions

    View Slide

  21. CSS and the first meaningful paint @patrickhamann
    • Where are your users based?
    • What is your device landscape?
    • In what context are they using your site?
    • What is their network profile?
    • What did they come for?
    What is your average user profile?

    View Slide

  22. CSS and the first meaningful paint @patrickhamann
    The average load time for mobile sites is 19
    seconds over 3G connections
    The need for mobile speed, Google DoubleClick

    View Slide

  23. CSS and the first meaningful paint @patrickhamann
    53% of mobile site visits are abandoned if
    pages takes longer than 3 seconds to load.
    The need for mobile speed, Google DoubleClick

    View Slide

  24. View Slide

  25. CSS and the first meaningful paint @patrickhamann
    Forming a TTFMP baseline:
    3G EM 3G Cable
    3 secs 2 secs 1 secs
    Time to First Meaningful Paint:
    3G EM 3G Cable
    ? ? ?
    Insert your custom profiles here:

    View Slide

  26. CSS and the first meaningful paint @patrickhamann
    Case-study profile:
    BW down BW up Latency RTT
    3G EM 400 kbs 400 kbs 400 ms
    3G 1.6 Mbs 768 kbs 150 ms
    Cable 5m Mbs 1Mbs 28 ms
    • Moto G (low-mid Android)
    • 9 runs
    • Chrome beta

    View Slide

  27. Name of Presentation
    Baseline

    View Slide

  28. CSS and the first meaningful paint @patrickhamann
    1
    2
    3
    4
    5 FT.com
    6
    7
    8
    9 Other head elements...
    10
    11
    12
    13
    14 Content ...
    15
    16
    17

    View Slide

  29. CSS and the first meaningful paint @patrickhamann

    View Slide

  30. Name of Presentation
    Baseline results
    TTFMP (ms)
    0
    1000
    2000
    3000
    4000
    5000
    6000
    7000
    8000
    9000
    10000
    Baseline
    3G EM 3G Cable
    TTFMP % impovement
    3G EM 3259 63
    3G 1462 63
    Cable 1327 46

    View Slide

  31. Name of Presentation
    Inline critical CSS

    View Slide

  32. CSS and the first meaningful paint @patrickhamann
    Request page
    Network
    Renderer
    GET html
    Build DOM
    response
    Build CSSOM Render page
    GET css
    GET js
    response
    response
    idle idle
    Render blocking
    Run JS
    Async

    View Slide

  33. CSS and the first meaningful paint @patrickhamann
    Request page
    Network
    Renderer
    GET html
    Build DOM
    response
    Build CSSOM Render page
    GET css
    GET js
    response
    response
    idle idle
    Render blocking
    Run JS
    Async

    View Slide

  34. CSS and the first meaningful paint @patrickhamann
    Request page
    Network
    Renderer
    GET html
    Build DOM
    response
    Build CSSOM Render page
    GET css
    GET js
    response
    response
    idle idle
    Render blocking
    Run JS
    Async
    GET css response

    View Slide

  35. CSS and the first meaningful paint @patrickhamann
    Request page
    Network
    Renderer
    GET html
    Build DOM
    response
    Build CSSOM Render page
    GET css response
    idle
    Async
    Render

    View Slide

  36. View Slide

  37. ! !

    View Slide

  38. ç
    https://github.com/filamentgroup/loadCSS
    1
    2
    3
    4
    5 FT.com
    6
    7 <br/>8 html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}a{background-color:tran<br/>9<br/>10 Critical styles ...<br/>11
    12
    13
    14
    15 <br/>16 /*! loadCSS. [c]2017 Filament Group, Inc. MIT License */<br/>17 (function(){ ... }());<br/>18
    19
    20 Other head elements...
    21
    22
    23
    24

    View Slide

  39. TCP slow-start https://hpbn.co/building-blocks-of-tcp/

    View Slide

  40. Before

    View Slide

  41. After

    View Slide

  42. After

    View Slide

  43. Name of Presentation
    Inline critical CSS results
    TTFMP (ms)
    0
    1000
    2000
    3000
    4000
    5000
    6000
    7000
    8000
    9000
    10000
    Baseline Inline
    3G EM 3G Cable
    % Improvement
    0
    10
    20
    30
    40
    50
    60
    70
    80
    90
    100
    TTFMP % impovement
    3G EM 3259 63
    3G 1462 63
    Cable 1327 46

    View Slide

  44. CSS and the first meaningful paint
    • No blocking resources

    • No SPOF on CSS

    • Less requests over wire

    • Instant painting

    • Causes reflow

    • Not cachable

    • Hard to maintain

    • Hard to automate
    Pros Cons

    View Slide

  45. Name of Presentation
    Preload

    View Slide

  46. CSS and the first meaningful paint @patrickhamann
    What are your
    critical resources?

    View Slide

  47. Logo?
    Fonts?
    Hero image?

    View Slide

  48. Lighthouse https://developers.google.com/web/tools/lighthouse/

    View Slide

  49. Lighthouse https://developers.google.com/web/tools/lighthouse/

    View Slide

  50. Before

    View Slide

  51. Before

    View Slide

  52. CSS and the first meaningful paint @patrickhamann
    Network JavaScript Render tree Layout Paint
    HTML DOM
    CSS CSSOM
    Network JavaScript Render tree Layout Paint
    HTML DOM
    CSS CSSOM

    View Slide

  53. CSS and the first meaningful paint @patrickhamann
    Network JavaScript Render tree Layout Paint
    HTML
    CSS CSSOM
    Network JavaScript Render tree Layout Paint
    HTML DOM
    CSS CSSOM

    View Slide

  54. CSS and the first meaningful paint @patrickhamann
    Network JavaScript Render tree Layout Paint
    HTML
    CSS CSSOM
    Network JavaScript Render tree Layout Paint
    HTML DOM
    CSS CSSOM

    View Slide

  55. CSS and the first meaningful paint @patrickhamann
    Network JavaScript Render tree Layout Paint
    CSS CSSOM
    Network JavaScript Render tree Layout Paint
    HTML DOM
    CSS CSSOM

    View Slide

  56. CSS and the first meaningful paint @patrickhamann
    JavaScript Render tree Layout Paint
    CSSOM
    Network JavaScript Render tree Layout Paint
    HTML DOM
    CSS CSSOM

    View Slide

  57. CSS and the first meaningful paint @patrickhamann
    Render tree Layout Paint
    Network JavaScript Render tree Layout Paint
    HTML DOM
    CSS CSSOM

    View Slide

  58. https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model

    View Slide

  59. CSS and the first meaningful paint @patrickhamann
    The preload scanner

    View Slide

  60. Preload, W3C working draft https://www.w3.org/TR/preload/

    View Slide

  61. CSS and the first meaningful paint @patrickhamann
    Provides a declarative fetch primitive that
    initiates an early fetch and separates fetching
    from resource execution.

    View Slide

  62. CSS and the first meaningful paint @patrickhamann
    1
    2
    3
    4
    5 <br/>6 var res = document.createElement("link");<br/>7 res.rel = "preload";<br/>8 res.as = "style";<br/>9 res.href = "styles/other.css";<br/>10 document.head.appendChild(res);<br/>11
    1 Link: rel=“preload”; as=“style” nopush
    Preload with markup:
    Preload with HTTP header:

    View Slide

  63. CSS and the first meaningful paint @patrickhamann
    < GET /index.html


    < HTTP/1.1 200 OK
    < Cache-Control: private, max-age=60, must-revalidate
    < Expires: Thu, 20 Apr 2017 21:39:52 GMT
    < Last-Modified: Thu, 20 Apr 2017 13:11:33 GMT
    < ETag: "966eca3815d88d8848933d33c68ab2bd"
    < Content-Type: text/html
    < Content-Encoding: gzip
    < Content-Length: 43177
    < Date: Thu, 20 Apr 2017 21:39:52 GMT
    < Connection: keep-alive
    < Link: ; as=style; rel=preload; nopush, 

    ; rel=preload as=font crossorigin nopush,
    ; rel=preload as=font crossorigin nopush,
    ; as=image; rel=preload; nopush

    View Slide

  64. Before

    View Slide

  65. Before

    View Slide

  66. After

    View Slide

  67. Preload browser support, April 2017, http://caniuse.com/#feat=link-rel-preload

    View Slide

  68. Name of Presentation
    Preload results
    TTFMP (ms)
    0
    1000
    2000
    3000
    4000
    5000
    6000
    7000
    8000
    9000
    10000
    Baseline Inline Preload
    3G EM 3G Cable
    % Improvement
    0
    10
    20
    30
    40
    50
    60
    70
    80
    90
    100
    TTFMP % impovement
    3G EM 3176 64
    3G 1778 55
    Cable 1042 57

    View Slide

  69. CSS and the first meaningful paint
    • Indicate hidden resources

    • Dictate priority and order

    • Separates fetch from exec

    • Easy to create contention

    • Requires server logic

    Pros Cons

    View Slide

  70. Name of Presentation
    Server push

    View Slide

  71. CSS and the first meaningful paint @patrickhamann
    HTTP/2

    View Slide

  72. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server

    View Slide

  73. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    GET /index.html

    View Slide

  74. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    GET /index.html
    200 OK /index.html

    View Slide

  75. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    GET /index.html
    GET /main.css
    200 OK /index.html

    View Slide

  76. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server

    View Slide

  77. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    GET /index.html

    View Slide

  78. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    PUSH_PROMISE /main.css
    GET /index.html

    View Slide

  79. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    PUSH_PROMISE /main.css
    200 OK /index.html
    GET /index.html

    View Slide

  80. CSS and the first meaningful paint @patrickhamann
    1
    2
    3
    4
    5 FT.com
    6
    7
    8
    9 ...
    10
    1 Link: ; rel=“preload”; as=“style”
    Indicate push of critical styles with Link preload header:
    Convert inline styles into normal link rel=“stylesheet” declaration and async the main styles

    View Slide

  81. Before
    index.html main.css
    Start render TTFMP
    Idle Idle

    View Slide

  82. TTFMP
    Start render
    After
    critical.css
    TTFMP
    index.html main.css
    Idle
    Start render
    Idle

    View Slide

  83. CSS and the first meaningful paint @patrickhamann
    /hero.jpg

    Stream ID: 4

    Weight: 16
    /data.json

    Stream ID: 7

    Weight: 16
    /app.js

    Stream ID: 3

    Weight: 64
    /icon.svg

    Stream ID: 9

    Weight: 16
    /main.css

    Stream ID: 2

    Weight: 110
    /index.html

    Stream ID: 1

    Weight: 128

    View Slide

  84. CSS and the first meaningful paint @patrickhamann
    Is indicating push via the
    HTML response too late?

    View Slide

  85. After

    View Slide

  86. After

    View Slide

  87. HTTP/2 browser support, April 2017, http://caniuse.com/#feat=http2

    View Slide

  88. Name of Presentation
    Push results
    TTFMP (ms)
    0
    1000
    2000
    3000
    4000
    5000
    6000
    7000
    8000
    9000
    10000
    Baseline Inline Preload Push
    1256
    1042
    1327
    2477
    2826
    1778
    1462
    3983
    5035
    3176
    3259
    8849
    3G EM 3G Cable
    % Improvement
    0
    10
    20
    30
    40
    50
    60
    70
    80
    90
    100
    TTFMP % impovement
    3G EM 5035 43
    3G 2826 29
    Cable 1256 49

    View Slide

  89. CSS and the first meaningful paint
    • Easy to configure
    • Creates contention

    • Requires server logic

    • Hard to debug

    • Not cache aware
    Pros Cons

    View Slide

  90. Name of Presentation
    Asynchronous Push

    View Slide

  91. TTFMP
    Start render
    After
    critical.css
    TTFMP
    index.html main.css
    Idle
    Start render
    Idle

    View Slide

  92. TTFMP
    Start render
    After
    critical.css
    TTFMP
    index.html main.css
    Idle
    Start render
    Idle

    View Slide

  93. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    HTTP/2 connection

    View Slide

  94. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    HTTP/2 connection
    GET /index.html

    View Slide

  95. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    PUSH_PROMISE /main.css $
    HTTP/2 connection
    GET /index.html

    View Slide

  96. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    PUSH_PROMISE /main.css
    200 OK /index.html
    HTTP/2 connection
    GET /index.html

    View Slide

  97. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    "
    App

    View Slide

  98. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    GET /index.html "
    GET /index.html
    App

    View Slide

  99. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    PUSH_PROMISE /main.css -
    GET /index.html "
    GET /index.html
    App

    View Slide

  100. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    PUSH_PROMISE /main.css -
    $
    GET /index.html "
    GET /index.html
    App

    View Slide

  101. CSS and the first meaningful paint @patrickhamann
    "
    #
    Client Server
    PUSH_PROMISE /main.css -
    $
    200 OK /index.html
    GET /index.html "
    GET /index.html
    200 OK /index.html
    App

    View Slide

  102. CSS and the first meaningful paint @patrickhamann
    1 const http2 = require('http2');
    2
    3 function handler(request, response) {
    4 if (request.url === "/index.html") {
    5 const push = response.push('/critical.css');
    6 push.writeHead(200);
    7 fs.createReadStream('/critical.css').pipe(push);
    8 }
    9
    10 // Generate index response:
    11 // - Fetch data from DB
    12 // - Render template
    13 // etc ...
    14
    15 response.end(data);
    16 }
    17
    18 const server = http2.createServer(opts, handler);
    19 server.listen(80);

    View Slide

  103. Before

    View Slide

  104. After

    View Slide

  105. Name of Presentation
    Push async results
    TTFMP (ms)
    0
    1000
    2000
    3000
    4000
    5000
    6000
    7000
    8000
    9000
    10000
    Baseline Inline Preload Push Push async
    3G EM 3G Cable
    % Improvement
    0
    10
    20
    30
    40
    50
    60
    70
    80
    90
    100
    TTFMP % impovement
    3G EM 3062 65
    3G 1613 59
    Cable 1021 58

    View Slide

  106. CSS and the first meaningful paint
    • Uses idle time

    • Ensures delivery before
    preload

    • Limited avaliablity

    • Custom server logic

    • Hard to debug
    Pros Cons

    View Slide

  107. CSS and the first meaningful paint @patrickhamann
    What about the
    repeat view?

    View Slide

  108. Name of Presentation
    Results

    View Slide

  109. View Slide

  110. View Slide

  111. View Slide

  112. View Slide

  113. Name of Presentation
    The future

    View Slide

  114. Cache digests for HTTP/2, K. Oku https://tools.ietf.org/html/draft-ietf-httpbis-cache-digest-01

    View Slide

  115. https://www.ietf.org/proceedings/95/slides/slides-95-httpbis-5.pdf

    View Slide

  116. Early hints status code for HTTP, K. Oku https://tools.ietf.org/html/draft-ietf-httpbis-early-hints-01

    View Slide

  117. https://www.ietf.org/proceedings/97/slides/slides-97-httpbis-sessb-early-hints-00.pdf

    View Slide

  118. Name of Presentation
    Conclusion

    View Slide

  119. CSS and the first meaningful paint @patrickhamann
    Resource loading is hard.

    View Slide

  120. CSS and the first meaningful paint @patrickhamann
    Bandwidth is often 

    under-utilised

    View Slide

  121. CSS and the first meaningful paint @patrickhamann
    Identify your critical resources
    and request chains.

    View Slide

  122. CSS and the first meaningful paint @patrickhamann
    Use preload to indicate critical
    resources, such as fonts to the
    browser.

    View Slide

  123. CSS and the first meaningful paint @patrickhamann
    Push critical CSS,
    but only on first view and only
    within idle time.

    View Slide

  124. CSS and the first meaningful paint @patrickhamann
    Always be testing.

    View Slide

  125. Name of Presentation
    Thanks!
    Patrick Hamann
    [email protected]
    @patrickhamann

    View Slide