Slide 1

Slide 1 text

Handling images on the web Marco Otte-Witte 
 Managing Director, simplabs 
 @marcoow

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

Slide 4

Slide 4 text

Slide 5

Slide 5 text

.my-image path { fill: #818ca2 ; }

Slide 6

Slide 6 text

https://unsplash.com/photos/1tpLdmxki-c

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

Images as essential UI Icons, status indicators, etc. are essential parts of an application’s UI. https://unsplash.com/photos/_zKxPsGOGKg

Slide 9

Slide 9 text

Many but small Adapt to application state Must be present immediately https://www.linkedin.com/feed/

Slide 10

Slide 10 text

.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'); }

Slide 11

Slide 11 text

.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;…'); }

Slide 12

Slide 12 text


 
 .fa { display: inline-block ; font: FontAwesome ; } .fa-users:before { content: "\f0c0" ; } https://fontawesome.com/icons/font-awesome-logo-full 
 
 .fa { display: inline-block ; font: FontAwesome ; } .fa-users-1:before { content: "\f01e" ; }

Slide 13

Slide 13 text

https://en.wikipedia.org/wiki/Scalable_Vector_Graphics#/media/File:SVG_logo_h.svg

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

ember-template-lint https://github.com/ember-template-lint/ember-template-lint https://github.com/ember-template-lint

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Static Images Photos, illustrations, etc. make apps look nicer or support other data but are not required to enable functionality. https://www.linkedin.com

Slide 19

Slide 19 text

Few but big No adaption to application state Non-essential http://linkedin.com

Slide 20

Slide 20 text

http://linkedin.com

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

WebP https://developers.google.com/speed/webp https://en.wikipedia.org/wiki/WebP#/media/File:WebPLogo.svg

Slide 23

Slide 23 text

https://caniuse.com/webp

Slide 24

Slide 24 text

Slide 25

Slide 25 text

PNG, 201KB WebP, 25KB

Slide 26

Slide 26 text

http://linkedin.com

Slide 27

Slide 27 text

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/

Slide 28

Slide 28 text

https://www.linkedin.com/feed/ Similar to static images otherwise Discovered at runtime

Slide 29

Slide 29 text

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/

{{@post.title}}

{{@post.text}}

Slide 30

Slide 30 text

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/

{{@post.title}}

{{@post.text}}

Slide 31

Slide 31 text

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/

Slide 32

Slide 32 text

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)

Slide 33

Slide 33 text

https://www.shutterstock.com/de/image-photo/man-think-how-solve-mathematical-problem-766012597

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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