José M. Pérez
Solutions Engineer at Facebook
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
Version A
FrontFest
2017
Speakers & Schedule
0.0s
0.3s
0.6s
0.9s
1.2s
Version B
FrontFest
2017
Speakers & Schedule
0.0s
0.3s
0.6s
0.9s
1.2s
FrontFest
2017
Speakers & Schedule
FrontFest
2017
FrontFest
2017
PROGRESSIVE IMAGE RENDERING
@jmperezperez
Source https://www.smashingmagazine.com/2015/11/why-performance-matters-part-2-perception-management/
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
end = end time in milliseconds
VC = % visually complete
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
images
1,815kB (54%)
scripts
457kB (14%)
other
1,106kB (33%)
source: http archive 1 nov 2017
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
TIP 1
PROGRESSIVE IMAGE RENDERING
@jmperezperez
gif | png | jpg | webp | <the_next_thing>
PROGRESSIVE IMAGE RENDERING
@jmperezperez
<picture>
<source type="image/webp" srcset="2700x1209/my-image.webp 2700w,
1024x1024/my-image.webp 1024w,
600x600/my-image.webp 600w"
sizes="100vw" />
<source srcset="2700x1209/my-image.jpg 2700w,
1024x1024/my-image.jpg 1024w,
600x600/my-image.jpg 600w"
sizes="100vw" />
<img class="rsImg" src="600x600/my-image.jpg" alt="My beautiful image" />
</picture>
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
TIP 2
1 column
2 columns
3 columns
<img sizes="(max-width: 30em) 100vw,
(max-width: 50em) 50vw,
calc(33vw - 100px)"
srcset="red-square-200.jpg 200w,
red-square-400.jpg 400w,
red-square-800.jpg 800w,
red-square-1600.jpg 1600w"
src="red-square-400.jpg"
alt="Red Square">
PROGRESSIVE IMAGE RENDERING
@jmperezperez
Challenge: Keeping in sync markup and CSS
RESPONSIVE IMAGES
PROGRESSIVE IMAGE RENDERING
@jmperezperez
TIP 3
&
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
// load image when it's within 100px of the viewport
const options = {
rootMargin: '100px'
}
const callback = entries => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
// load image
}
});
};
const observer = new IntersectionObserver(callback, options);
observer.observe(document.querySelector('.lazy-img'));
PROGRESSIVE IMAGE RENDERING
@jmperezperez
INTERSECTION OBSERVER
class LazyImage extends React.Component {
constructor() {
this.observer = new IntersectionObserver(entries => {
if (entries[0].intersectionRatio > 0) {
// load!
}
});
this.element = null; /* render() will set it through a ref */
}
componentDidMount() {
this.observer.observe(this.element);
}
componentWillUnmount() {
this.observer.unobserve(this.element);
}
...
}
PROGRESSIVE IMAGE RENDERING
@jmperezperez
INTERSECTION OBSERVER
PROGRESSIVE IMAGE RENDERING
@jmperezperez
IMAGE DECODING
// Image loading with predecoding
const img = new Image();
img.src = "image.jpg";
img.decode().then(() => {
document.body.appendChild(img);
}).catch(() => {
throw new Error('Could not load/decode big image.');
});
PROGRESSIVE IMAGE RENDERING
@jmperezperez
IMAGE DECODING
Add an image to the DOM without causing a decoding delay.
Track the proposal on https://github.com/whatwg/html/issues/1920
TIP 4
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
PLACEHOLDERS
Nothing
Placeholder
Solid colour or gradient
Progressive image loading or "Blur-up"
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
<figure>
<div>
<div/> <!-- this div keeps the aspect ratio so
the placeholder doesn't collapse -->
<img/> <!-- this is a tiny image with a small
resolution (e.g. ~27x17) and low quality -->
<canvas/> <!-- takes the above image and applies a blur filter -->
<img/> <!-- the large image to be displayed -->
<noscript/> <!-- fallback for no JS -->
</div>
</figure>
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
Canny Edge Detector
PROGRESSIVE IMAGE RENDERING
@jmperezperez
<svg>
<polyline points="51,1 61,1 61,2 56,4 56,3"/>
<polyline points="52,1 50,2 51,3 50,4 50,9 46,10 46,8 48,8 48,9"/>
<polyline points="61,4 61,5 58,6"/>
...
<polyline points="62,58 61,59 61,60 50,62 50,61 51,61"/>
</svg>
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
SVG - 10 shapes
SVG - 100 shapes
Original
0.74kB
3.5kB
101kB
PROGRESSIVE IMAGE RENDERING
@jmperezperez
SVG - 10 shapes + Blur
SVG 100 shapes + Blur
(JPEG or WebP) + Blur
0.8kB
3.6kB
0.5kB (JPEG)
0.09 kB (WebP)
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
Just because you can it doesn't mean you should
PROGRESSIVE IMAGE RENDERING
@jmperezperez
PROGRESSIVE IMAGE RENDERING
@jmperezperez
talk with me for more info
@jmperezperez
Slides on https://slides.com/jmperez
By José M. Pérez
This talk addresses the culprit in page size, images. I feel that we like discussing JS and CSS and its payload, but we tend to forget about images, which represent more than half of the bytes of a page. I show ways to save bytes when using images, and creative techniques to render previews of the images in their placeholders.