Performance is important but often overlooked when it comes to building responsive sites. We often spend time discussing layouts, breakpoints, and designs that fits well for both desktops and mobile but we do not invest more time in thinking about performance. We learned this the hard way when we revamped Viki's main web page to a responsive site a few months ago. In the process of improving Viki's performance, we discovered practical techniques and useful tools in helping us enhance our user experience and monitor our performance. In this talk, we are going to share the present and the future of performance optimizations for responsive sites.
https://tech.rakuten.co.jp/
12. Define fallback & web fonts in CSS
@font-face {
font-family: 'Open Sans';
src: url('open-sans.woff2') format("woff2"),
url('open-sans.woff') format("woff");
}
CSS
13. Define fallback & web fonts in CSS
Detect specific
font loa
body {
font-family: sans-serif;
}
CSS
.fonts-loaded {
body {
font-family: 'Open Sans', sans-serif;
}
}
16. Detect specific font load (Basic Font Load)
Detect
specific font
loafont.load().then(function () {
// Font successfully loads; use webfont class
window.document.documentElement.className += " fonts-loaded";
});
JS
// Font Face Observer is written by Bram Stein:
// https://github.com/bramstein/fontfaceobserver
var font = new FontFaceObserver("Open Sans", {weight: 400});
17. Toggle class in order to use web fonts
Detect specific
font loa
body {
font-family: sans-serif;
}
.fonts-loaded {
body {
font-family: 'Open Sans', sans-serif;
}
}
CSS
<html class="fonts-loaded">
<body>
<!-- Open sans fonts with class added w JS -->
<p>Your content here</p>
</body>
</html>
HTML
20. Leverage browser cache
Detect
specific font
loa
<!--#if expr="$HTTP_COOKIE=/fonts-loaded=true/" -->
<html class="fonts-loaded">
<!--#else -->
<html>
<!--#endif -->
HTML
Set a cookie!
21. Leverage Browser Cache
Detect
specific font
loa
// do not do anything if class is set
if (w.document.documentElement.className.indexOf("fonts-loaded") > -1) {
return;
}
var font = new FontFaceObserver("Open Sans", {weight: 400});
font.load().then(function () {
window.document.documentElement.className += " fonts-loaded";
// Set cookie to optimize for repeat views
document.cookie = "fonts_loaded=true; domain=" + viki.com + "; path=/";
});
JS
22. Problem
Image Credit: Bram Stein @ Smashing Magazine’s Real Life Responsive Web Design (Web Fonts Performance)
29. Future Solution
@font-face {
font-display: auto | block | swap | fallback | optional;
} Determine by user
agent
Invisible text & swap
once fonts is loaded
(FOIT)
Show fallback & swap
once fonts is loaded
(FOUT)
Same as swap but
will show fallback
when font fails to
load
Font is used if it is
already downloaded;
else fallback is used
Source: https://tabatkins.github.io/specs/css-font-display/#font-display-desc
30. Font Display Spec
by Tab Atkins
https://tabatkins.github.io/specs/css-font-display/#font-display-desc
31. Future Solution
Detect specific
font loa
@font-face {
font-family: 'Open Sans';
font-display: 'fallback';
src: local('Open Sans'), local('OpenSans-Light'),
url('open-sans.woff2') format('woff2');
}
CSS
<link rel="preload" href="open-sans.woff2" as="font" type="font/woff2">
HTML
Can be combined to make font loading efficient
32. Comprehensive Guide to Font
Loading Strategy
by Zach Leatherman
https://www.zachleat.com/web/comprehensive-webfonts/
33. Web Font Loading Patterns
by Bram Stein
https://www.bramstein.com/writing/web-font-loading-patterns.html
36. “DOM construction cannot proceed until
JavaScript is executed, and JavaScript
execution cannot proceed until CSSOM is
available.” - Ilya Grigorik
Source: https://hpbn.co/primer-on-web-performance/#hypertext-web-pages-and-web-applications
38. Document
Object Model
(DOM)
CSS Object
Model
(CSSOM)
Render Tree Layout Paint
CSS is render
blocking!
Contains both
content & style
information
Browser calculates
the size & position
of elements
Browser picks up
layout results and
paint pixels to the
screen
Time spent on each process should be minimize!
HTML Parser
Script Download
Parser Paused
Script Execute
HTML Parser
Script
41. Present Solution
HTML Parser
Script Download
Parser Paused
Script Execute
HTML Parser
Async
Defer
HTML Parser
Script Download
Script Execute
Source: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html
42. Present Solution
Async — Scripts with no dependencies
Execution order
implementation is
buggy in IE < 10
Removing dependencies completely or inline them
Only applies to
small JS code
Defer — Scripts with dependencies; Execution order matters
45. HTML
<noscript>
<link rel="stylesheet" href="path/to/all.css">
</noscript>
</head>
Present Solution
Library to defer the load of CSS:
https://github.com/filamentgroup/loadCSS
Inline CSS for first time page load
Include full CSS path in noscript tag
for people without JS
<head>
<script>
function loadCSS( href ) { ... }
loadCSS( "path/to/all.css" );
</script>
<style>
.carousel { width: 100%; } .card { background-color: #fff; } ...
</style>
47. Size of inline scripts & CSS < 14KB
“...server can send up to 10 TCP packets on a new connection (~14KB) in first
roundtrip, and then it must wait for the client to acknowledge this data before it
can grow its congestion window and proceed to deliver more data.”
“Due to this TCP behavior, it is important to optimize your content to minimize the
number of roundtrips required to deliver the necessary data to perform the first
render of the page. Ideally, the ATF (above the fold) content should fit under
14KB — this allows the browser to paint the page after just one roundtrip…”
Source: https://developers.google.com/speed/docs/insights/mobile#delivering-the-sub-one-second-rendering-experience
48. Limitations of HTTP/1.x
No compression of response headers
No effective resource prioritization
Multiple connections instead of one
50. “HTTP/2 modifies how the data is formatted
(framed) and transported between the client
and server, both of whom manage the entire
process, and hides all the complexity from
our applications within the new framing
layer.” - Ilya Grigorik
Source: https://hpbn.co/http2/
51. HTTP/1.x
No compression of response
headers
No effective resource
prioritization
Multiple connections instead
of one
HTTP/2
Compress response headers
Allow prioritization of request
One connection for multiple
concurrent exchange
(multiplexing)
54. “By manually inlining the resource into the
document, we are, in effect, pushing that
resource to the client, without waiting for
the client to request it.” - Ilya Grigorik
Source: https://hpbn.co/http2/#server-push
61. Present Solution
Fixed Width
Images
Dimensions remain the same in other viewport
Higher quality image in retina displays; normal
quality is lower-end devices.
Examples: Logo or
small profile
pictures
62. Present Solution
<img src="logo_500px.jpg" srcset="logo_700px.jpg 1.5x,
logo_1000px.jpg 2x, logo_1500px.jpg 3x" width="500"
alt="logo image">
A fallback src and
also used for DPR
of 1x
X descriptors:
Pixel density of
screen
Browsers will choose the best resource that fits the screen
DPR
66. Present Solution
<img srcset="image_400.jpg 400w,
image_600.jpg 600w,
image_900.jpg 900w,
image_1200.jpg 1200w"
sizes="(min-width: 840px) 50vw,
(min-width: 450px) 75vw,
100vw"
src="image_600.jpg" alt="Some image for example’s sake">
VW is viewport width
100vw = 100% of viewport width
75vw = 75% of the viewport width
Browser will use srcset and sizes to serve
image that match the condition
So which will the browsers choose?
67. <img srcset="image_450.jpg 450w,
image_600.jpg 600w,
image_900.jpg 900w,
image_1200.jpg 1200w"
sizes="(min-width: 840px) 50vw,
(min-width: 600px) 75vw,
100vw"
src="image_600.jpg" alt="Some image for example’s sake">
Browser Viewport: 900px
900 * 0.50 =
450
Retina display with DPR of 2 will
load (450 * 2) px of image
68. Srcset — Browser hint. No guarantee which image browsers will choose
Present Solution Browser may choose
lower res image due
to connectivity
Sizes — Order matters; Browsers choose the first media condition that match in sizes
sizes="(min-width: 840px) 50vw,
(min-width: 450px) 75vw,
100vw"
sizes="(max-width: 320px) 50vw,
(max-width: 800px) 75vw,
100vw"
Min-width should be
organize from
largest to smallest
Max-width should be
organize from
smallest to largest
71. Image Credit: Yoav Weiss @ Smashing Magazine’s Real Life Responsive Web Design (Responsive Images)
Present Solution
72. Present Solution
<picture>
<source media="(min-width: 840px)" srcset="image-large.jpg">
<source media="(min-width: 600px)" srcset="image-medium.jpg">
<img src="image-small.jpg" alt="Art directions">
</picture>
Must have img tag for
fallback & must appear
after all sources
You can have as many
sources as you want &
it will be obeyed
Order matters