Responsive afbeeldingen met srcset en sizes

Met de nieuwe attributen srcset en sizes kun je meerdere formaten van dezelfde afbeelding specificeren in de <img> tag. De browser kiest vervolgens voor elke situatie het beste formaat. Superhandig en het zorgt ook voor een betere laadtijd van je website.

Deze nieuwe attributen zijn al een tijdje beschikbaar. Het lukte me echter nooit de werking goed te begrijpen. Maar, het is een zeer waardevolle vernieuwing. Daarom de moeite waard mij erin te verdiepen.

Het resultaat is deze pagina over de werking van srcset en sizes. Om het praktisch te maken, heb ik een alledaags voorbeeld uitgewerkt: de pagina met sidebar. Deze layout kom je op veel websites tegen, van webshops tot blogs.

Waarom srcset en sizes gebruiken?

Er komt wel vaker nieuwe syntax uit. Dus waarom zou je je willen verdiepen in srcset en sizes? Ik zie twee voordelen:

  1. betere weergave van afbeeldingen,
  2. betere laadtijd van je website

Met srcset en sizes is het mogelijk meerdere formaten te maken van dezelfde afbeelding. De browser kiest vervolgens zelf het beste formaat. Daarbij houdt het niet alleen rekening met de breedte van het scherm (viewport width), maar ook met de pixel dichtheid. Of je website nou bekeken wordt op een klein scherm met lage resolutie of een groot scherm met hoge resolutie, de browser kiest de best passende afbeelding.

Met srcset en sizes voorkom je dat onnodig grote afbeeldingen geladen worden. Dit maakt je website sneller en dat vinden de meeste gebruikers erg prettig. Te langzame websites kan je bezoekers en omzet kostenZie ook mijn artikel over waarom een snelle laadtijd zo belangrijk is..

Het mooie van srcset en sizes is bovendien dat de fallback uitstekend is. Deze attributen zijn een uitbreiding van de standaard <img> tag. Browsers die de nieuwe attributen niet ondersteuning zullen de 'gewone' afbeelding gebruiken (daarover later meer). Voldoende reden dus om verder kennis te maken met srcset en sizes.

De werking van srcset en sizes

Een voorbeeld van een <img> tag met de nieuwe attributen:

<img alt="image alt text" src="medium.jpg" srcset="small.jpg 240w, medium.jpg 300w, large.jpg 720w" sizes=“(min-width: 960px) 720px, 100vw">

Of, om het iets beter leesbaar te maken:

<img 
   alt="image alt text" 
   src="medium.jpg" 
   srcset="
      small.jpg 240w, 
      medium.jpg 300w, 
      large.jpg 720w
   " 
   sizes="
      (min-width: 960px) 720px, 
      100vw
   "
>

Laten we elk onderdeel langslopen.

alt="image alt text"

Ook bij responsive afbeeldingen gebruik je natuurlijk gewoon een alt tekst.

src="medium.jpg"

De vertrouwde manier waarmee je de locatie van je afbeelding opgeeft. Bij het gebruik van srcset en sizes is dit de fallback. Browsers die deze attributen niet ondersteunen, zullen de afbeelding bij src gebruiken.

srcset="small.jpg 240w, medium.jpg 300w, large.jpg 720w"

Dit is waar de magie begint. Bij scrset geef je een lijst van afbeeldingen op in verschillende formaten. In dit geval zijn het er drie. Achter elke afbeelding staat de breedte in pixels (w van width). Bijvoorbeeld, small.jpg 240w betekent dat deze afbeelding 240px breed is.

Alternatieve schrijfwijze

Voor de media queries in sizes kan het handig zijn deze net iets anders op te schrijven.

   sizes="
      (max-width: 960px) 300px,
      720px
   "

Deze notatie is wat makkelijker te lezen. Wat er staat is:

  • bij een viewport van maximaal 960px breed, toon de afbeelding van 300px breed
  • bij een viewport groter dan 960px, toon de afbeelding van 720px
sizes="(min-width: 960px) 540px, 100vw"

Met sizes bepaal je wanneer welke afbeelding getoond moet worden. Dit gebeurt door een combinatie van een media query en de specificatie voor de breedte van de afbeeldingVoor de breedte van de afbeelding bij sizes kun je verschillende waarden gebruiken. Zie het overzicht van beschikbare waarden op w3.org.. sizes vond ik trouwens het meest lastige om te begrijpen.

Bovenstaande code voor sizes zegt het volgende:

  • Is de minimale breedte van de viewport gelijk met of groter dan 960px, toon dan de afbeelding met een breedte van 540px.
  • Is de breedte van de viewport kleiner dan 960px, toon dan de afbeelding zo breed als de viewport (100vw = 100% van de ‘viewport width’).

Nu kun je opmerken dat er bij srcset geen afbeeldingen staan met een breedte van 540px. Dat is geen probleem. De browser zal de best passende afbeelding selecteren. Daarbij rond de browser af naar boven. Bij een breedte van 540px zal de browser large.jpg gebruiken (met een breedte van 720px).

HD schermen en de pixel-device-ratio

Het mooie van srcset en sizes, is dat het ook rekening houdt met de pixel dichtheid van het beeldscherm. Schermen met een zgn. HD scherm hebben een grotere pixeldichtheid. Daarmee kunnen afbeeldingen scherper weergegeven worden.

Browsers rekenen met de zgn. pixel-device-ratio. Een pixel-device-ratio van 1 wil zeggen dat 1 echte pixel overeenkomt met 1 CSS pixel. Een pixel-device-ratio van 2 wil zeggen dat 2 echte pixels overeenkomt met 1 CSS pixel.

Voorbeeld: een iPad Air 2 heeft een schermresolutie van 2048 bij 1536 pixels (bron: apple.com). De pixel-device-ratio is 2, waarmee een browser het scherm behandelt als 1024 bij 768 pixels. Het scherm is echter wel twee keer zo scherp, dus je wilt er ook grotere afbeeldingen op weergeven. En voilá, daarvoor hebben we srcset en sizes!

Voorbeeld: pagina met sidebar

Dan nu een voorbeeld uit de praktijk: de pagina met een sidebar. Voor dit voorbeeld gebruik ik drie situaties: weergave op mobiel, tablet en desktopDe media queries in dit voorbeeld zijn gebaseerd op de genoemde devices. Dat heb ik gedaan om het voorbeeld wat makkelijker te maken. In de praktijk kun je het beste je media queries baseren op je website layout.. Verder geldt het volgende:

  • de breedte van de content (met afbeelding) is 67%, de sidebar is 33% breed
  • de sidebar wordt op mobiel onderaan de pagina weergegeven,
  • mobiel en tablet hebben een pixel-device-ratio van 2
Voorbeeld: pagina met sidebar.
Voorbeeld: pagina met sidebar.

Mobiel

Voor de weergave op mobiel krijgen we het volgende resultaat:

  • viewport width is 320px,
  • pixel-device-ratio is 2,
  • het aantal echte pixels is daarom 320px x 2 = 640px,
  • de sidebar wordt onderaan de pagina getoond, de afbeelding wordt dus op volledige breedte van het scherm weergegeven,
  • we hebben dus een afbeelding nodig van 640px breed,
  • en sizes stellen we in op 100vw,

Daarmee ziet onze voorlopige HTML voor <img> er zo uit:

srcset="small.jpg 640w"
sizes="100vw"

Tablet

Op een tablet krijgen we het volgende resultaat:

  • viewport width is 768px,
  • pixel-device-ratio is 2,
  • het aantal echte pixels is: 768px x 2 = 1536px,
  • de sidebar wordt naast de pagina getoond,
  • de breedte van het artikel is 67%,
  • daarmee wordt de breedte van de afbeelding: 67% van 1536px = 1030px,
  • sizes stellen we als volgt in: (min-width: 1536px) 1030pxVoor het gemak stel ik de media query van sizes gelijk aan de grootte van de afbeelding. In de praktijk kies je wellicht een ander query die rekening houdt met de gehele website en niet alleen deze afbeelding., dat betekent zoveel als: is de viewport 1536px of groter, toon dan de afbeelding met een breedte van 1030px

Daarmee komt onze HTML er als volgt uit te zien:

srcset="
   small.jpg 640w, 
   large.jpg 1030w
"
sizes="
   (min-width: 1536px) 1030px, 
   100vw
"

Desktop

De laatste situatie waarvoor we de juiste afbeelding willen laden is desktop. Ik heb gekozen voor een beeldscherm met een resolutie van 1366 x 768 px. Dat is volgens de statistieken van w3schools.com een veel voorkomende resolutie op dit moment.

Dit levert het volgende resultaat:

  • de viewport width is 1366px,
  • de pixel-device-ratio is 1,
  • aantal echte pixels is 1366px x 1 = 1366px,
  • de sidebar wordt naast de pagina getoond,
  • de breedte van het artikel is nog steeds 67%,
  • de breedte van de afbeelding is dus: 67% van 1366px = 916px,
  • en sizes wordt: (min-width: 1366px) 916px,

De HTML wordt daarmee als volgt:

srcset="
   small.jpg 640w,
   medium.jpg 916w,
   large.jpg 1030w"
sizes="
   (min-width: 1366px) 916px,
   (min-width: 1536px) 1030px, 
   100vw
"

Om de HTML voor <img> te voltooien voegen we nog de attributen alt en src toe. De complete code voor de <img> tag wordt daarmee:

<img
   alt"alt text image"
   src="medium.jpg"
   srcset="
      small.jpg 640w,
      medium.jpg 916w,
      large.jpg 1030w"
   sizes="
      (min-width: 1366px) 916px,
      (min-width: 1536px) 1030px, 
      100vw
   "
>

Opmerkingen

Het lijkt zo dat het verschil tussen medium.jpg en large.jpg niet heel groot is. Waarom niet voor beide situaties dezelfde afbeelding gebruiken, bijvoorbeeld large.jpg?

Maar het verschil is groter dan je denkt. Er van uitgaande dat de afbeeldingen een verhouding hebben van 3:2 (lengte:breedte), dan is large.jpg 21% groter dan medium.jpgDe berekening is als volgt. Oppervlakte medium.jpg is 916px x 614px = 562.424px. Oppervlakte large.jpg is 710.700px. Daarmee is de oppervlakte van large.jpg 21% groter.. Het is dus zeker de moeite waard beide afbeeldingen te gebruiken.

Browserondersteuning

De browserondersteuning voor srcset en sizes is goed. Voor Nederland geldt een dekking van 85%. Geen ondersteuning wordt geboden door Internet Explorer, Opera mini en oudere versies van Android. Maar nogmaals, de fallback is perfect. Wordt srcset en sizes niet ondersteund, dan zal een browser de src attribuut gebruiken.

Browserondersteuning van srcset en sizes volgens caniuse.com (26 okt. 2016).
Browserondersteuning van srcset en sizes volgens caniuse.com (26 okt. 2016).

bron: Can I use Srcset attribute op caniuse.com

Conclusie

srcset en sizes kun je direct toepassen om je website te verbeteren. De browser kiest zelf de beste afbeelding uit. De nieuwe attributen srcset en sizes zorgen voor een betere weergave van je afbeeldingen en het levert een snellere laadtijd op. Omdat je een 100% fallback hebt, sluit je niemand uit bij het gebruik van srcset en sizes.

Bronnen

Voor het schrijven van deze pagian heb ik gebruik gemaakt van o.a. de volgende bronnen:

Andere versies

Van dit artikel bestaat ook een Engelse versie.