Post on 13-Apr-2017
Beyond Breakpoints
@renettarenula Aysha Anggraini Rakuten Tech Conf ‘16
Improving performance for responsive sites
1. Optimize Web Fonts
2. Reduce Render-Blocking Scripts
3. Optimize Images
Optimize Web Fonts
@font-face {
font-family: 'Open Sans';
src: url('open-sans.woff2') format("woff2"),
url('open-sans.woff') format("woff");
}
CSS
Does not guarantee load of fonts
body {
font-family: 'Open Sans', sans-serif;
}
CSS
Will only load when font is specifically declared under a rule
Problem
Construct DOM
Construct CSSOM
DownloadFonts!
Web fonts are lazy loaded!
Problem
Image Credit: Bram Stein @ Smashing Magazine’s Real Life Responsive Web Design (Web Fonts Performance)
Results in FOUT or FOIT
Problem
Different browsers handles this differently
FOUT & FOIT
Present Solution
Define fallback & web fonts in
CSS
Basic Font Loading Strategy
Leverage browser cache
Load fonts dynamically &
use it
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
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;
}
}
Present Solution
Define fallback & web fonts in
CSS
Basic Font Loading Strategy
Leverage browser cache
Load fonts dynamically &
use it
Font Face Observerby Bram Stein
https://github.com/bramstein/fontfaceobserver
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});
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
Present Solution
Define fallback & web fonts in
CSS
Basic Font Loading Strategy
Leverage browser cache
Load fonts dynamically &
use it
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!
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
Problem
Image Credit: Bram Stein @ Smashing Magazine’s Real Life Responsive Web Design (Web Fonts Performance)
Future Solution
Give ability to define custom loading logic
Preload
Future Solution
FOUT and FOIT can be reduced!Image Credit: https://www.bramstein.com/writing/preload-hints-for-web-fonts.html
Future Solution
<link rel="preload" href="assets/opensans.woff2" as="font" type="font/woff2" crossorigin>
HTML
Important in order to set
priority
Future Solution
Source: http://caniuse.com/#search=preload
Future Solution
Determines how a font-face is displayed when it is downloading & once it is downloaded
Font-Display
Future Solution
@font-face {
font-family: 'Open Sans';
font-display: 'auto';
src: local('Open Sans Light'), local('OpenSans-Light'),
url('open-sans-v13-latin-300.woff2') format('woff2');
}
CSS
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
Font Display Specby Tab Atkins
https://tabatkins.github.io/specs/css-font-display/#font-display-desc
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
Comprehensive Guide to Font Loading Strategy
by Zach Leatherman
https://www.zachleat.com/web/comprehensive-webfonts/
Web Font Loading Patternsby Bram Stein
https://www.bramstein.com/writing/web-font-loading-patterns.html
Reduce Render-Blocking Scripts
Problem
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
“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
Problem
HTML ParserScript Download
Parser Paused
Script Execute
HTML Parser
Script
Source: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html
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 ParserScript Download
Parser Paused
Script Execute
HTML Parser
Script
Problem
CSSJS
Render-blocking scripts
Fonts
Present Solution
HTML
<script src="script.js" async></script>
<script src="script.js" defer></script>
Present Solution
HTML ParserScript Download
Parser Paused
Script Execute
HTML Parser
Async
Defer
HTML ParserScript Download
Script Execute
Source: http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html
Present Solution
Async — Scripts with no dependencies
Execution order implementation is
buggy in IE < 10
Removing dependencies completely or inline themOnly applies to small JS code
Defer — Scripts with dependencies; Execution order matters
Problem
CSSJS
Render-blocking scripts
Fonts
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>
Criticalby Addy Osmani
https://github.com/addyosmani/critical
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
Limitations of HTTP/1.x
No compression of response headers
No effective resource prioritization
Multiple connections instead of one
HTTP/2Awesome extension to HTTP/1.x
Future Solution
“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/
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)
Source: https://hpbn.co/http2/#request-and-response-multiplexing
Future Solution
Future Solution
Server PushAllows push of resources to client without client
requesting for it
“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
Server Push
Source: https://hpbn.co/http2/#server-push
Cached by client
Can be reused across other pages
Can be multiplexed along side other request
Can be prioritized by the server
High Performance Browser Networkingby Ilya Grigorik
https://hpbn.co/
Optimize Images
“It’s the problem of efficiently loading appropriately sized content images that fit the page’s design” - Yoav Weiss
Problem
Problem
CSS
img {
max-width: 100%;
}
Will cause bloat since image resolution must be large
Variable Width Images
Present Solution
Art DirectionFixed Width
Images
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
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
Variable Width Images
Present Solution
Art DirectionFixed Width
Images
Present Solution
Variable width Images
Dimensions vary based on viewport
Examples: Header images or
thumbnails
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 width100vw = 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?
<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
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
Variable Width Images
Present Solution
Art DirectionFixed Width
Images
Present Solution
Art Direction
Customize image for specific breakpoints
Image varies in quality, crop area, proportions, etc.
Image Credit: Yoav Weiss @ Smashing Magazine’s Real Life Responsive Web Design (Responsive Images)
Present Solution
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 obeyedOrder matters
img {
max-width: 100%;
}
>
<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">
Too much syntax
Future Solution
Missing link between server & client for layout information
Client Hints
Browsers Server
DPRViewport-Width
Width
Perfect fit image!
Future 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.jpg" alt="Example">
<img src="image.jpg"
sizes="(min-width: 840px) 50vw,
(min-width: 450px) 75vw,
100vw"
alt="Example">
Make markup simpler!
Future Solution
No longer need srcset since image resizing will
be done server side
Future Solution
<meta http-equiv="Accept-CH" content="DPR, Viewport-Width, Width">
Enable Client Hints
<img src="sunset.png" alt="Beautiful Sunset" sizes="50vw"/>
Future Solution
Automating resource selection with Client Hints
by Ilya Grigorik
https://developers.google.com/web/updates/2015/09/automating-resource-selection-with-client-hints
The Anatomy of Responsive Imagesby Jake Archibald
https://jakearchibald.com/2015/anatomy-of-responsive-images/
Responsive Imagesby Yoav Weiss
Smashing Magazine Book 5: Real-Life Responsive Web Design
Thank You!
renaysha.me codepen.io/rrenula @renettarenula