A presentation at JSDayES 2017 in in Madrid, Spain by José M. Pérez
Progressive image rendering José M. Pérez · Web dev at Spotify @jmperezperez
PROGRESSIVE IMAGE RENDERING @jmperezperez About me
PROGRESSIVE IMAGE RENDERING @jmperezperez
PROGRESSIVE IMAGE RENDERING @jmperezperez Page Load Time
PROGRESSIVE IMAGE RENDERING @jmperezperez 0.0s 0.3s 0.6s 0.9s 1.2s JSDayES Madrid Version A 2017 Speakers & Schedule 0.0s Version B 0.3s 0.6s 0.9s 1.2s JSDayES Madrid JSDayES Madrid JSDayES Madrid JSDayES Madrid 2017 2017 2017 2017 Speakers & Schedule Speakers & Schedule
PROGRESSIVE IMAGE RENDERING @jmperezperez User Perceived Performance
PROGRESSIVE IMAGE RENDERING @jmperezperez SpeedIndex = end ∫0 end = end time in milliseconds VC = % visually complete 1− VC 100
PROGRESSIVE IMAGE RENDERING @jmperezperez WebPageTest
PROGRESSIVE IMAGE RENDERING @jmperezperez
PROGRESSIVE IMAGE RENDERING @jmperezperez More kilobytes can sometimes lead to improved perceived performance
PROGRESSIVE IMAGE RENDERING @jmperezperez Avoiding this:
PROGRESSIVE IMAGE RENDERING @jmperezperez Techniques to improve perceived performance Server-side rendering Critical CSS Async JS Async fonts
PROGRESSIVE IMAGE RENDERING @jmperezperez What about images?
PROGRESSIVE IMAGE RENDERING @jmperezperez images scripts other 1712kB (66%) 426kB (16%) 464kB (18%) source: http archive 15 apr 2017
To use or not to use images
PROGRESSIVE IMAGE RENDERING @jmperezperez Minimalist | Flat Design
PROGRESSIVE IMAGE RENDERING @jmperezperez Not that long ago
PROGRESSIVE IMAGE RENDERING @jmperezperez TIP 1 Optimise your images
PROGRESSIVE IMAGE RENDERING @jmperezperez
PROGRESSIVE IMAGE RENDERING @jmperezperez right format gif | png | jpg | webp | <the_next_thing> <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 compression · lossless · perceptual
PROGRESSIVE IMAGE RENDERING @jmperezperez TIP Responsive 1 column 2 columns 3 columns 2
PROGRESSIVE IMAGE RENDERING @jmperezperez RESPONSIVE IMAGES Example <img sizes="(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw - 100px)" srcset="profile-200.jpg 200w, profile-400.jpg 400w, profile-800.jpg 800w, profile-1600.jpg 1600w" src="profile-400.jpg" alt="Pinchito"> Challenge: Keeping in sync markup and CSS
PROGRESSIVE IMAGE RENDERING @jmperezperez TIP 3 Lazy-load images
PROGRESSIVE IMAGE RENDERING @jmperezperez <img> above the fold & Lazy below the fold
PROGRESSIVE IMAGE RENDERING @jmperezperez Intersection Observer
PROGRESSIVE IMAGE RENDERING @jmperezperez INTERSECTION OBSERVER Example // 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 Encapsulating in React 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 What to show while the image is loading
PROGRESSIVE IMAGE RENDERING @jmperezperez PLACEHOLDERS Options Nothing Placeholder Solid colour Progressive image loading or "Blur-up"
PROGRESSIVE IMAGE RENDERING @jmperezperez Examples of solid color
PROGRESSIVE IMAGE RENDERING @jmperezperez
PROGRESSIVE IMAGE RENDERING @jmperezperez
PROGRESSIVE IMAGE RENDERING @jmperezperez
PROGRESSIVE IMAGE RENDERING @jmperezperez
PROGRESSIVE IMAGE RENDERING @jmperezperez
PROGRESSIVE IMAGE RENDERING @jmperezperez Examples of Progressive Image Loading
PROGRESSIVE IMAGE RENDERING @jmperezperez Medium
PROGRESSIVE IMAGE RENDERING @jmperezperez Medium
PROGRESSIVE IMAGE RENDERING @jmperezperez Quartz (qz.com)
PROGRESSIVE IMAGE RENDERING @jmperezperez Quartz (qz.com)
PROGRESSIVE IMAGE RENDERING Quora @jmperezperez
PROGRESSIVE IMAGE RENDERING @jmperezperez How it is done
PROGRESSIVE IMAGE RENDERING @jmperezperez Markup - Eg Medium <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 JPEGs Baseline Progressive Source: https://blog.codinghorror.com/progressive-image-rendering/
PROGRESSIVE IMAGE RENDERING @jmperezperez With the Progressive JPEG method [...] cognitive fluency “ is inhibited and the brain has to work slightly harder to make sense of what is being displayed. — From Progressive image rendering: Good or evil?
PROGRESSIVE IMAGE RENDERING @jmperezperez Facebook Inlining thumbnail image in payload Source: https://code.facebook.com/posts/991252547593574/the-technology-behind-preview-photos/
PROGRESSIVE IMAGE RENDERING @jmperezperez Facebook “ Unfortunately, the standard JPEG header is hundreds of bytes in size. In fact, the JPEG header alone is several times bigger than our entire 200-byte budget. However, excluding the JPEG header, the encoded data payload itself was approaching our 200 bytes.
PROGRESSIVE IMAGE RENDERING @jmperezperez Facebook Header (Quantization Table and Huffman Table) Compressed Data Client (mobile app) GraphQL
PROGRESSIVE IMAGE RENDERING @jmperezperez Thumbnails
PROGRESSIVE IMAGE RENDERING @jmperezperez Getting creative with SVGs
PROGRESSIVE IMAGE RENDERING @jmperezperez SVG Source: https://www.polygon.com/a/ps4-review
PROGRESSIVE IMAGE RENDERING @jmperezperez SVG Source: https://www.polygon.com/a/xbox-one-review
PROGRESSIVE IMAGE RENDERING @jmperezperez Drawing with SVG ">//codepen.io/jmperez/embed/rxxRRg/?height=525&themeid=0&default-tab=js,result&embed-version=2"> Source: https://codepen.io/jmperez/pen/rxxRRg
PROGRESSIVE IMAGE RENDERING @jmperezperez Drawing bitmap images Canny Edge Detector
https://jmperezperez.com/renderconf17/extslides/contour2/index.html Source: https://jmperezperez.com/contour/
PROGRESSIVE IMAGE RENDERING @jmperezperez https://jmperezperez.com/contour/ Source: https://jmperezperez.com/contour/
PROGRESSIVE IMAGE RENDERING @jmperezperez How to draw bitmaps 1. Find edges with canny edge detector 2. Create lines 3. Use JS and SVG to animate <svg> <polyline <polyline <polyline ... <polyline </svg> points="51,1 61,1 61,2 56,4 56,3"/> points="52,1 50,2 51,3 50,4 50,9 46,10 46,8 48,8 48,9"/> points="61,4 61,5 58,6"/> points="62,58 61,59 61,60 50,62 50,61 51,61"/>
PROGRESSIVE IMAGE RENDERING @jmperezperez Should we do this? Just because you can it doesn't mean you should
PROGRESSIVE IMAGE RENDERING @jmperezperez Summary Reduce requests Choose the right format and optimise Embrace responsive images Try to lazy load Innovate!
PROGRESSIVE IMAGE RENDERING @jmperezperez The Web is fun fun..
spotify.com/jobs talk with me for more info
Thanks! @jmperezperez
On a regular web page, images represent the largest assets. We might have heard about responsive images to serve the most suitable image for each screen. However, how and when we load them can have a great impact too.
I will show you several techniques used by well known websites, based on placeholders, dominant colours, blurry images and lazy loading to improve user's perceived performance.
These techniques leverage several web technologies like CSS3, canvas and the recent IntersectionObserver API.
Here’s what was said about this presentation on social media.
Great talk by @jmperezperez about image loading process in a #Website | let's have fun trying different type of loading! Seen at #JsDayEs pic.twitter.com/jgNJpzFB6n
— Belen Moreno (@belenxi) May 13, 2017
@jmperezperez Taking about Progressive Imagen Rendering at @JSDayES#JSDayES pic.twitter.com/PiDtMzrxhE
— Ignacio Villanueva (@IgnaciodeNuevo) May 13, 2017
Progressive image rendering con @jmperezperez, tema con altas espectativas #JsDayEs pic.twitter.com/5UJjimtd53
— Jonas Talavera (@jonas_tg) May 13, 2017