Progressive Image Rendering

A presentation at CSSConf AU 2016 in December 2016 in Melbourne VIC, Australia by José M. Pérez

Slide 1

Slide 1

Progressive image rendering CSSConf AU 2016 José M. Pérez · Web dev at Spotify @jmperezperez

Slide 2

Slide 2

Images on the web

Slide 3

Slide 3

To use or not to use images

Slide 4

Slide 4

Slide 5

Slide 5

Slide 6

Slide 6

Slide 7

Slide 7

Wrong way of hiding images (1/2) <img src="example.png"> <!-- it'll be requested --> @media (max-width: 480px) { img { display: none; } }

Slide 8

Slide 8

Wrong way of hiding images (2/2) <body> <section class="section-1"> <p>This is the current section</p> <img src="example-1.png"> </section> <section class="section-2 hidden"> <p>This section might or might not be shown later</p> <img src="example-2.png"> <!-- it'll be requested --> </div> </body> .hidden { display: none; }

Slide 9

Slide 9

Optimise your images really

Slide 10

Slide 10

Picture element and srcset 2 columns 1 column 3 columns

Slide 11

Slide 11

1st issue: Keeping in sync markup and CSS <img sizes="(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw - 100px)" srcset="swing-200.jpg 200w, swing-400.jpg 400w, swing-800.jpg 800w, swing-1600.jpg 1600w" src="swing-400.jpg" alt="Kettlebell Swing">

Slide 12

Slide 12

2nd issue: Lazy loading

Slide 13

Slide 13

Combine regular images and lazy-loaded ones

Slide 14

Slide 14

How to lazy load: Basic approach For all images, check whether they are in the viewport (or close enough). If they are, request it. Repeat this onScroll and onResize

Slide 15

Slide 15

How to lazy load: IntersectionObserver Don't bind to the scroll event. Subscribe to an event triggered when the image enters the rendered area Supported in Chrome, Opera. In development in Firefox and Edge. Very easy to use as another strategy in your lazy loading library.

Slide 16

Slide 16

IntersectionObserver

Slide 17

Slide 17

What to show while the image is loading

Slide 18

Slide 18

Alternatives

Slide 19

Slide 19

Examples of solid color

Slide 20

Slide 20

Slide 21

Slide 21

Slide 22

Slide 22

style="border:0"

Slide 23

Slide 23

Examples of Progressive Image Loading

Slide 24

Slide 24

Medium

Slide 25

Slide 25

How it's done

Use <div> to render the image Request small thumbnail Draw thumbnail to <canvas/> and apply blur effect Request large image Render large image and hide <canvas/>

Slide 26

Slide 26

Markup Overview <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>

Slide 27

Slide 27

How do users perceive it? Jason @lang Follow Did @Medium recently add a new image loading fadein? I noticed it this morning on mobile and just now again on web. Looks nice. 6:05 AM - 1 Mar 2016 DobaKung @zartre Follow @Medium's articles (although full of high-res images) load up very fast - 1:38 PM - 28 Mar 2015

Slide 28

Slide 28

or maybe not? Harris Rodis @harrisrodis Follow I don't know about you but I don't like a bit those blurry (still loading...) images on Medium. Very distracting. 3:40 AM - 30 Dec 2015 James Young @welcomebrand Follow That blurry image preloading thing on Medium - is it just me or does it make all images load extremely slowly now? 8:53 PM - 5 Feb 2016

Slide 29

Slide 29

Source: wpexplorer.com/optimize-images-wordpress-guide

Slide 30

Slide 30

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?

Slide 31

Slide 31

Reliable? Damien Erambert @Eramdam Follow I'm seeing this more and more on Medium posts. Maybe the whole "blur the pictures" stuff isn't a good idea… 5:44 AM - 9 Jan 2016 Sara Soueidan @SaraSoueidan Follow This @Medium page is fully loaded on my slow connection. Very pretty with those stupid image effects, isn’t it? 12:07 AM - 29 Nov 2015 3 18

Slide 32

Slide 32

Facebook - Inlining thumbnail image in payload Source: The technology behind preview photos

Slide 33

Slide 33

Facebook - Inlining thumbnail image in payload 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.

Slide 34

Slide 34

Facebook - Inlining thumbnail image in payload Header (mainly Quantization Table and Huffman Table) Compressed Data Client (mobile app) GraphQL

Slide 35

Slide 35

Generating tiny thumbnails JPG 464 B 532 B 428 B 409 B 456 B 692 B WebP 112 B 154 B 106 B 96 B 116 B 202 B

Slide 36

Slide 36

Generating tiny thumbnails JPG 464 B 532 B 428 B 409 B 456 B 692 B WebP 112 B 154 B 106 B 96 B 116 B 202 B

Slide 37

Slide 37

Getting creative with SVGs

Slide 38

Slide 38

Source: polygon.com/a/ps4-review

Slide 39

Slide 39

How it works HTML CSS JS Result window.onload = function() { var path = document.querySelector('path'); var length = path.getTotalLength(); // Clear any previous transition path.style.transition = path.style.WebkitTransition = 'none'; // Set up the starting positions path.style.strokeDasharray = length + ' ' + length; path.style.strokeDashoffset = length; // Trigger a layout so styles are calculated & the browser // picks up the starting position before animating path.getBoundingClientRect(); // Define our transition path.style.transition = path.style.WebkitTransition = 'stroke-dashoffset 7s ease-in-out'; // Go! path.style.strokeDashoffset = '0'; }; More info: jakearchibald.com/2013/animated-line-drawing-svg EDIT ON

Slide 40

Slide 40

Drawing bitmap images Canny Edge Detector

Slide 41

Slide 41

Drawing bitmap images Source: jmperezperez.com/contour

Slide 42

Slide 42

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"/>

Slide 43

Slide 43

Should we do this? Just because you can it doesn't mean you should

Slide 44

Slide 44

The Web is fun.

Slide 45

Slide 45

Thanks! @jmperezperez