第1页
High Performance Images
Beautiful shouldn’t mean Slow
@guypod
第2页
Average Web Page Weight (Sep ’15)
@guypod
Not 37%
Images 63%
Source: HTTP Archive
第3页
Images On Average Page
696 KB
891 KB
1,128 KB
1,383 KB
~2x!!!
50 Reqs
Sep '12
@guypod
56 Reqs
55 Reqs
Jun '13
Jun '14
Requests
Source: HTTP Archive
KB
54 Reqs
Sep '15
第4页
Images Impact Performance
19000 14250
-30%
@guypod
With Images No Images
Load Time, 3G Speed
第5页
What Can you do?
@guypod
第6页
Image Compression
@guypod
第7页
Image Loading
@guypod
第8页
@guypod
Operationalizing Image Optimization
第9页
Image Compression
@guypod
第10页
Average Resource Size
CSS
9 KB
JS 16 KB
JPEG
@guypod
37 KB
10 20 30 40
第11页
RWD Sites Use Big Images
RWD
Not RWD
30 31.6 KB
20 10
@guypod
20.8 KB
JPEG Size
10 KB
7.1 KB
PNG Size
第12页
Tip #1:
Pick The Right Format
@guypod
第13页
Image Formats On The Web
GIF 23%
Other 2%
JPEG 45%
PNG 30%
@guypod
第14页
GIF
• 28 Years Old (1987) • 256 Colors • Supports “Simple”
Transparency • Supports Animation • Patented (now expired)
@guypod
第15页
PNG
• 19 Years Old (1996) • 8-32 bit color palettes • Alpha Transparency • Not patented
@guypod
第16页
GIF -> PNG = 21% Savings
PNG File Size
GIF File Size
@guypod Source: Styoan Stefanov, “Give PNG A Chance” (2009)
第17页
JPEG
• 23 years old (1992) • RGB Colors (24 bit) • No Transparency Support • A Lossy Format
@guypod
第18页
Lossy Compression
JPEG
≠Bitmap
Bitmap
Lossless Compression
PNG
=Bitmap
Bitmap
@guypod
第19页
JPEG
• 23 years old (1992) • RGB Colors (24 bit) • No Transparency Support • A Lossy Format
@guypod
第20页
PNG -> JPG = MUCH Smaller
PNG, 574 KB
JPG, 110 KB
@guypod
第21页
JPEG: No Transparency
@guypod
PNG
JPEG
第22页
WebP
3.3 2.475
1.65
3.27 bpp
-26%
2.42 bpp
15 11.25
7.5
14.4 KB
-31%
9.9 KB
0.825
3.75
PNG
WebP
Bytes Per Pixel
JPEG (q75) WebP
File Size (KB)
@guypod
Source: Google Studies
第23页
WebP Browser Support
@guypod
第24页
BPG
• Less than 1 year old
• Lossless & Lossy
• Based on Video encoder HEVC
• H.265, successor of H.264
• Beat WebP & J2K in Mozilla Study
Fabrice Bellard
• Free (LGPL)
(Creator of ffmpeg)
@guypod
第25页
FLIF
• 0 years old • Lossless • Progressive • Responsive Friendly • No browser support • Free (GPL)
@guypod
Source: FLIF Creators Jon Sneyers & Harshad RJ
第26页
PNG vs Others
@guypod
Source: Cloudinary
第27页
New Format Bakeoff
@guypod
Source: Cloudinary
第28页
FLIF - 3rd Party Stats
@guypod
Source: Cloudinary
第29页
New Image Formats
WebP
JPEG XR
JPEG 2000
Support
Chrome, Opera, Android 4.x
IE 10+
Savings (over JPEG)
40-50%
~25%
Mime Type
image/webp
image/vnd.ms-photo
Soon: image/jxr
Identification
Accept: image/ webp
Detect IE 10+
Safari on iOS, OS X
15-20%
image/jp2
Detect Safari 5+
@guypod
第30页
Using Custom Formats
Client Side
<script src="picturefill.js"></script> <picture> <source type="image/webp"
srcset="book.webp"> <source type="image/vnd.msphoto"
srcset="book.jxr"> <img src="book.jpg" alt="a book"> </picture>
@guypod
第31页
Using Custom Formats
Server Side, Single URL
GET /book.jpg
GET /book.jpg
CDN/Cache
Origin
@guypod
第32页
Using Custom Formats
Server Side, Single URL
GET /book.jpg
GET /book.jpg
GET /book.jpg Accept: image/webp
GET /book.webp
CDN/Cache
Origin
@guypod
第33页
Using Custom Formats
Server Side, Single URL
GET /book.jpg
GET /book.jpg
GET /book.jpg Accept: image/webp
GET /book.webp
GET /book.jpg User-Agent: MSIE 10 * Spartan Accept: image/jxr*
@guypod
GET /book.jxr CDN/Cache
Origin
第34页
Tip #1: Pick The Right Format
@guypod
第35页
Tip #2: Control Quality
@guypod
第36页
JPEG Quality
Low Quality
@guypod
High Quality
第37页
Quality: 75 Size: 37 KB
Quality: 25 Size: 16 KB
@guypod
Quality: 90 Size: 66 KB
Quality: 40 Size: 21 KB
第38页
Quality: 90 Size: 66 KB
Quality: 75 Size: 37 KB
Quality: 40 Size: 21 KB
Quality: 25 Size: 16 KB
@guypod
第39页
Quality Scale Is Per Format
0.25
JPEG JPEG XR WebP
0.19
Similarity
0.13
0.06
@guypod
0.00 0
25 50 75
Quality
Source: Nick Doyle Performance Calendar
第40页
Detecting Excessive Quality
WebPageTest
• Some stats about image quality on the web?
@guypod
第41页
Detecting Excessive Quality
PageSpeed Insights
• Some stats about image quality on the web?
@guypod
第42页
Tip #2: Control Quality
@guypod
第43页
SIZE Doesn’t matter It’s all about
TECHNIQUE
@guypod
第44页
Image Loading
@guypod
第45页
Tip #3: Size Images To Device
@guypod
第46页
Download & Shrink
@guypod
102 KB 1876×520 (975,520 pixels)
第47页
Download & Shrink
1876px
520px
.hp07img {width: 100%}
@guypod
866px
240px
第48页
Download & Shrink
1876px
975,520 pixels
520px
79% wasted pixels (~770K)
866px 207,840 pixels
240px
@guypod
第49页
Download & Shrink
1876px
110,744 Bytes
520px
79% wasted pixels 68% wasted bytes
(~75KB)
@guypod
866px 35,345 Bytes
240px
第50页
Download & Shrink
1876px
975,520 * 4(RGBA) = 3.9M Memory Bytes
520px
79% wasted pixels 68% wasted bytes 79% wasted memory
(3MB)
@guypod
866px 831K Mem Bytes
240px
第51页
@guypod
IMAGES
On an Average Page
第52页
“...25% of new Android phones have only 512MB of RAM.”
– Jen Fitzpatrick, Google Maps
@guypod
第53页
Download & Shrink
Processing Times
@guypod
Source: Tim Kadlec, “Mobile Image Processing”
第54页
Implementing Responsive Images
<img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36em) 33.3vw, 100vw" alt="A rad wolf">
@guypod
第55页
Implementing Responsive Images
<img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36em) 33.3vw, 100vw" alt="A rad wolf">
Hint, Hint…
@guypod
第56页
Implementing Responsive Images
<img src="small.jpg" srcset="large.jpg 1024w, medium.jpg 640w, small.jpg 320w" sizes="(min-width: 36em) 33.3vw, 100vw" alt="A rad wolf">
Hint, Hint…
@guypod
第57页
Implementing Responsive Images
<picture> <source media="(min-width: 40em)"
srcset="big.jpg 1x, big-hd.jpg 2x"> <source srcset="small.jpg 1x, small-hd.jpg 2x"> <img src="fallback.jpg" alt=""> </picture>
@guypod
第58页
Implementing Responsive Images
<picture> <source media="(min-width: 40em)"
srcset="big.jpg 1x, big-hd.jpg 2x"> <source srcset="small.jpg 1x, small-hd.jpg 2x"> <img src="fallback.jpg" alt=""> </picture>
Use Picturefill
@guypod
第59页
Which Breakpoints To Use?
What Are your Users Using?
@guypod
第60页
Which Breakpoints To Use?
How Big & Complex Are Your Images?
• Your Analytics
Width Height File Size 1 320 213 25K 2 453 302 44K 3 579 386 65K 4 687 458 85K 5 786 524 104K 6 885 590 124K 7 975 650 142K 8 990 660 151K
@guypod
Source: Jason Grigsby, “Sensible Jumps In Responsive Image File Sizes”
第61页
Which Breakpoints To Use?
How Big & Complex Are Your Images?
• Your Analytics
point # Width Height File Size 1 320 213 9.0K 2 731 487 29K 3 990 660 40K
@guypod
Source: Jason Grigsby, “Sensible Jumps In Responsive Image File Sizes”
第62页
FLIF Progressive “Breakpoints”
@guypod
第63页
FLIF Progressive “Breakpoints”
1969x1307 pixels 299,643 bytes
@guypod
第64页
FLIF Progressive “Breakpoints”
1969x1307 pixels All 299,643 bytes
653x985 pixels (1:2) First 80,389 bytes
@guypod
第65页
FLIF Progressive “Breakpoints”
1969x1307 pixels All 299,643 bytes
653x985 pixels (1:2) First 80,389 bytes
492x326 pixels (1:4) First 37,014 bytes @guypod
第66页
Tip #3: Size Images To Device
@guypod
第67页
Tip #4: Prioritize Critical Images
@guypod
第68页
Below The Fold
@guypod
Etsy 82%
Velocity 91%
Guardian 92%
第69页
On A Typical Page & Desktop Screen…
Page Content
Image Requests
Not Visible 62%
Visible 38%
Visible 20%
Not Visible 80%
@guypod
第70页
Download & Hide
@guypod
第71页
Download & Hide
@guypod
img {display: none}
第72页
Download & Hide
Image Requests Image Weight
@guypod
79 2,258 KB
78 2,251 KB
第73页
Lazy Load Images
<img src="book.jpg" alt="A Book">
<img src="1px.gif" data-src="book.jpg" alt="A Book" onload="loadImage(this)">
@guypod
第74页
Lazy Load Images
<script> function loadImage(img) {
var dataSrc = imgs[i].getAttribute("data-src"); if (dataSrc && isAboveTheFold(img)) { img.onload = null; img.src = dataSrc;
}} </script> <img src="1px.gif" data-src="book.jpg"
alt="A Book" onload="loadImage(this)">
@guypod
第75页
Lazy Load Images
<script> function loadImage(img) {
var dataSrc = imgs[i].getAttribute("data-src"); if (dataSrc && isAboveTheFold(img)) { img.onload = null; img.src = dataSrc;
}} // Repeat check on viewport changes (scroll, resize...) </script> <img src="1px.gif" data-src="book.jpg" alt="A Book" onload="loadImage(this)">
@guypod
第76页
Defer Load Images
<script> function loadImage(img, force) {
var dataSrc = imgs[i].getAttribute("data-src"); if (dataSrc && (force || isAboveTheFold(img)) ) { img.onload = null; img.src = dataSrc;
} else if (deferOthers) { window.addEventListener("load", function() { loadImage(img,true)});
}} </script>
@guypod
第77页
The Infamous
PRELOADER
@guypod
第78页
HTML Parser
<html> <head> <script src="main.js"></script> <link src="styles.css" type="text/css"> </head> <body> <img src="book.jpg"/> <img src="bag.jpg"/> </body> </html>
@guypod
第79页
HTML Parser
<html>
<head>
<script src="main.js"></script>
<link src="styles.css" type="text/css">
</head>
<body> <img src="book.jpg"/>
main.js
<img src="bag.jpg"/>
styles.css
</body>
book.jpg
</html>
bag.jpg
@guypod
第80页
HTML Parser & Pre-parser
<html>
<head>
<script src="main.js"></script>
<link src="styles.css" type="text/css">
</head>
<body> <img src="book.jpg"/>
main.js
<img src="bag.jpg"/>
styles.css
</body>
book.jpg
</html>
bag.jpg
@guypod
第81页
HTML Parser & Pre-parser
<html>
<head>
<script src="main.js"></script>
<link src="styles.css" type="text/css">
</head>
<body> <img src="book.jpg"/>
main.js
<img src="bag.jpg"/>
styles.css
</body>
book.jpg
</html>
bag.jpg
@guypod
第82页
HTML Parser & Pre-parser
<html>
<head>
<script src="main.js"></script>
<link src="styles.css" type="text/css">
</head>
<body> <img src="book.jpg"/>
main.js
<img src="bag.jpg"/>
styles.css
</body>
book.jpg
</html>
bag.jpg
@guypod
第83页
Who Initiates Image Downloads?
CSS 20%
HTML Parser 37%
Pre-parser 43%
@guSyopuorcde: Ilya Grigorik, HTTP Archive
第84页
HTML Parser & Pre-parser
…
<img src="1px.gif" data-src=“book.jpg" onload="loadImage(this)"/>
<img src="bag.jpg" data-src="bag.jpg" onload="loadImage(this)"/>
… main.js
styles.css
book.jpg
@guypod
bag.jpg
第85页
HTTP/1.1
HTTP/2
@guypod
第86页
Pre-Parser Boost
@guypod
Excess Images
第87页
Protip #1: LQIP
Low Quality Image Placeholders
<img src=“LowQ.jpg” data-src=“HighQ.jpg” onload=“loadImage(this)”>
@guypod
第88页
Protip #1: LQIP
Low Quality Image Placeholders
<img src=“LowQ.jpg” data-src=“HighQ.jpg” onload=“loadImage(this)”>
LowQ.jpg Quality: 25 Size: 16 KB
@guypod
第89页
Protip #1: LQIP
Low Quality Image Placeholders
<img src=“LowQ.jpg” data-src=“HighQ.jpg” onload=“loadImage(this)”>
LowQ.jpg Quality: 25 Size: 16 KB
@guypod
HighQ.jpg Quality: 90
Size: 66 KB
第90页
Protip #2: Selective Lazy Load
<img class="responsive-img" sizes="(min-width: 980px) 460px, (min-width: 740px) 340px, 100%" srcset="/w-460/<id>/500.jpg 460w, /w-340/<id>/500.jpg 340w,
/w-445/<id>/500.jpg 445w, /w-605/<id>/620.jpg 605w" src="/w-300/<id>/500.jpg">
@guypod
第91页
Protip #2: Selective Lazy Load
<img class="js-lazy-loaded-image responsive-img" data-srcset="/w-220/<id>/1000.jpg 220w,
/w-160/<id>/1000.jpg 160w, /w-127/<id>/1000.jpg 127w"
data-sizes="(min-width: 980px) 220px,
(min-width: 740px) 160px, 127px" src="data:image/gif;base64,R0lGODlhAQABAAAAACH
5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">
@guypod
第92页
Protip #2: Selective Lazy Load
<img class="js-lazy-loaded-image responsive-img" data-srcset="/w-220/<id>/1000.jpg 220w,
/w-160/<id>/1000.jpg 160w, /w-127/<id>/1000.jpg 127w"
data-sizes="(min-width: 980px) 220px,
(min-width: 740px) 160px, 127px" src="data:image/gif;base64,R0lGODlhAQABAAAAACH
5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">
@guypod
JS Disabled
第93页
Tip #4: Prioritize Critical
Images
@guypod
第94页
@guypod
Operationalizing Image Optimization
第95页
Tip #5: Encode Well
• Quality Curve is NOT a Standard • “Save For Web” is NOT just quality • Decoding Is Standard, Encoding Is Not • Notable Deltas: Chroma Subsampling, Per-Region
Quality, Lossy PNG, SSIM-Based Quality… • If you use one tool: ImageOptim (benchmark)
@guypod
第96页
Tip #6: Use Image Management Service
5 breakpoints * 2 Pixel Ratios * 3 Views * 5 thumbnails * 100,000 Products/Articles…
And tomorrow?
@guypod
第97页
Tip #6: Use Image Management Service
5 breakpoints * 2 Pixel Ratios * 3 Views * 5 thumbnails * 100,000 Products/Articles…
And tomorrow?
Transcoder
/q75/w120/book.jpg
GET /book.jpg
Origin
<Right-Sized Img>
<Big, High Res Img>
@guypod
第98页
Image Manager
@guypod
第99页
Cloudinary
@guypod
第100页
What Can You Do?
Image Compression
Image Loading
Image Operations
Choose The Right Format
Control Quality
Use Responsive Images
Prioritize Critical Content
Encode Well Transcode in Proxy
Enforce a Performance Budget
@guypod
第101页
FREE Copy at @hgttupyp:/o/dbit.ly/hpi-preview
第102页
Thank You!
Guy Podjarny @guypod
@guypod
Reminder Free HPI Link:
http://bit.ly/hpi-preview