Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Handling images on the web

Handling images on the web

Handling images on the web seems simple – add an <img> tag, set its src and you're done. But then there's also SVGs that can be embedded directly in the DOM. Or you could inline any image with Base64. There's also images in CSS, images that are part of your app and images uploaded by users, various techniques for (pre-) loading images to maximize efficiency and much more. This talk gives an overview over everything to know and consider when using imagery on the web and some recommendations for common scenarios.

3179e6bb62dc91d29bb906ffef4fa2d4?s=128

Marco Otte-Witte

March 25, 2021
Tweet

Transcript

  1. Handling images on the web Marco Otte-Witte 
 Managing Director,

    simplabs 
 @marcoow
  2. 2 https://en.wikipedia.org/wiki/Les_Horribles_Cernettes#/media/File:Les_Horribles_Cernettes_in_1992.jpg

  3. <img src="/images/my-image.jpg " >

  4. <picture > <source srcset="my-image-608.webp" type="image/webp" media="(max-width: 608px)" > <source srcset="my-image-1208.webp"

    type="image/webp" media="(min-width: 608px)" > <img src="/images/my-image.jpg" loading="lazy" decoding="async" style="background-size: cover; background-image: url('data:image/base64;…')" > </picture>
  5. <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="my-image" > <path d="…"></path

    > {{#if this.isActive}} <path d="…"></path > {{/if}} </svg > <style > .my-image path { fill: #818ca2 ; } </style>
  6. https://unsplash.com/photos/1tpLdmxki-c

  7. Images as essential UI Icons, status indicators, etc. are essential

    parts of an application’s UI. Images as data Images loaded as part of dynamic data from an API are only discovered at runtime. Static images Photos, illustrations, etc. make apps look nicer or support other data but are not required to enable functionality. https://https://guides.emberjs.com/release/getting-started/anatomy-of-an-ember-app/ https://unsplash.com/photos/_zKxPsGOGKg https://www.linkedin.com
  8. Images as essential UI Icons, status indicators, etc. are essential

    parts of an application’s UI. https://unsplash.com/photos/_zKxPsGOGKg
  9. Many but small Adapt to application state Must be present

    immediately https://www.linkedin.com/feed/
  10. <button class="contacts"></button> .contacts { height: 3.2rem ; width: 3.2rem ;

    background-image : url('/images/contacts.png'); } https://www.linkedin.com/feed/ .contacts.pending { background-image : url('/images/contacts-pending-1.png'); }
  11. <button class="contacts"></button > .contacts { height: 3.2rem ; width: 3.2rem

    ; background-image : url('data:image/png;…'); } https://www.linkedin.com/feed/ .contacts.pending { background-image : url('data:image/png;…'); }
  12. <link href="/fontawesome.css" rel="stylesheet" > <button class="contacts" > <i class="fa fa-users"></i

    > </button>
 
 .fa { display: inline-block ; font: FontAwesome ; } .fa-users:before { content: "\f0c0" ; } https://fontawesome.com/icons/font-awesome-logo-full <link href="/fontawesome.css" rel="stylesheet" > <button class="contacts" > <i class="fa fa-users-1"></i > </button>
 
 .fa { display: inline-block ; font: FontAwesome ; } .fa-users-1:before { content: "\f01e" ; }
  13. <button class="expand" > <svg xmlns="http://www.w3.org/2000/svg" > … </svg > </button>

    https://en.wikipedia.org/wiki/Scalable_Vector_Graphics#/media/File:SVG_logo_h.svg <button class="expand" > <svg xmlns="http://www.w3.org/2000/svg" > … {{#if this.pending}} <text class="pending" > {{this.pending}} </text > {{/if}} </svg > </button>
  14. None
  15. ember-template-lint https://github.com/ember-template-lint/ember-template-lint https://github.com/ember-template-lint

  16. ember-asset-sizes-action https://github.com/simplabs/ember-asset-size-action https://github.com/ember-learn/ember-website/pull/783

  17. Image URLs in CSS Base64 in CSS Icon Fonts SVG

    in DOM Immediate rendering ❌ ✅ ❌ ✅ extra weight added – CSS – Templates/JS can adapt to application state ❌ ❌ ❌ ✅ Images as essential UI
  18. Static Images Photos, illustrations, etc. make apps look nicer or

    support other data but are not required to enable functionality. https://www.linkedin.com
  19. Few but big No adaption to application state Non-essential http://linkedin.com

  20. http://linkedin.com <img src="/landing.jpg " > <img src="/landing.jpg" loading="lazy " >

    <img src="/landing.jpg " loading="lazy" sizes="(max-width: 608px) 100vw, 1280px " srcset="/landing-608.jpg 608w , /landing-1280.jpg 1280w " > <img src="/landing.jpg" loading="lazy" sizes="(max-width: 608px) 100vw, 1280px" srcset="/landing-608.jpg 608w , /landing-1280.jpg 1280w" decoding="async" > <img src="/landing.jpg" loading="lazy" sizes="(max-width: 608px) 100vw, 1280px" srcset="/landing-608.jpg 608w , /landing-1280.png 1280w" decoding="async" style="background-size: cover ; background-image: url('data:image/base64;…')" > <img src="/landing.jpg" loading="lazy" sizes="(max-width: 608px) 100vw, 1280px" srcset="/landing-608.jpg 608w, /landing-1280.png 1280w" decoding="async" style="background-size: cover; background-image: url('data:image/base64;…')" width="1280" height="400" >
  21. PNG Portable Networks Graphics https://tools.ietf.org/html/rfc2083 JPEG Joint Photographic Experts Group

    https://jpeg.org/jpeg/ https://en.wikipedia.org/wiki/Portable_Network_Graphics#/media/File:PNG_transparency_demonstration_1.png https://en.wikipedia.org/wiki/JPEG#/media/File:Felis_silvestris_silvestris_small_gradual_decrease_of_quality.png
  22. WebP https://developers.google.com/speed/webp https://en.wikipedia.org/wiki/WebP#/media/File:WebPLogo.svg

  23. https://caniuse.com/webp

  24. <picture > <source srcset="landing.webp" type="image/webp" > <img src="landing.jpg"> </picture> <picture

    > <source srcset="landing-608.webp" type="image/webp" media="(max-width: 608px)" > <source srcset="landing-1208.webp" type="image/webp" media="(min-width: 608px)" > <img src="landing.jpg"> </picture>
  25. PNG, 201KB WebP, 25KB

  26. http://linkedin.com <picture > <source srcset="landing-608.webp" type="image/webp" media="(max-width: 608px)" > <source

    srcset="landing-1208.webp" type="image/webp" media="(min-width: 608px)" > <img src="/landing.jpg" loading="lazy" decoding="async" style="background-size: cover; background-image: url('data:image/base64;…')" width="1280" height="400" > </picture>
  27. Images as data 27 Web apps (as opposed to web

    sites) use images a data that is dynamic and will change with changing application state https://www.linkedin.com/feed/
  28. https://www.linkedin.com/feed/ Similar to static images otherwise Discovered at runtime

  29. GET /posts HTTP1.1 { "data": [ { "id": "1" ,

    "type": "posts" , "attributes": { "title": "Interface Inventory Workshop" , "text": "Join our remote workshop…" , "picture": "/images/v4545rfre2.jpg" } } , … ] } https://www.linkedin.com/feed/ <article > <h4>{{@post.title}}</h4 > <p>{{@post.text}}</p > <img src={{@post.picture}} > </article>
  30. GET /posts HTTP1.1 { "data": [ { "id": "1" ,

    "type": "posts" , "attributes": { "title": "Interface Inventory Workshop" , "text": "Join our remote workshop…" , "picture": { "url": { "small": "/images/v4545rfre2.webp" , "large": "/images/v4545rfr45g.webp" , "fallback": "/images/v4545rfr45g.jpg" } "placeholder": "data:image/base64;…" , "dimensions": { "width": 200 , "height": 100 } } } } , … ] } https://www.linkedin.com/feed/ <article > <h4>{{@post.title}}</h4 > <p>{{@post.text}}</p > <picture > <source srcset={{@post.picture.url.small}} type="image/webp" media="(max-width: 608px)" > <source srcset={{@post.picture.url.large}} type="image/webp" media="(min-width: 608px)" > <img src={{@post.picture.url.fallback}} style="background-image: url({{@post.picture.placeholder}})" width={{@post.picture.dimensions.width}} height={{@post.picture.dimensions.height}} loading="lazy" decoding="async" > </picture > </article>
  31. async model() { let posts = await this.store.findAll("post") ; await

    Promise.all(posts.map(p) = > preloadImage(p.picture)) ; return posts ; } function preloadImage(src) { return new Promise(function(resolve, reject) { var image = new Image() ; image.onload = resolve ; image.onerror = resolve ; image.src = path ; }) ; } https://www.linkedin.com/feed/
  32. https://www.linkedin.com/feed/ Provide additional data for images rather than just a

    URL via the API (consider preloading images in the Ember routing layer)
  33. https://www.shutterstock.com/de/image-photo/man-think-how-solve-mathematical-problem-766012597

  34. https://img.zeit.de/kultur/kunst/2018-10/sothebys-auktion-street-art-schredder/wide__1300x731

  35. Thanks! Marco Otte-Witte 
 Managing Director, simplabs 
 @marcoow