Een data-URI zet een bestand rechtstreeks in het document: de afbeelding reist mee in de HTML of CSS in plaats van als apart request. Jarenlang was dat een standaardoptimalisatie, en de redenering erachter is grotendeels verlopen.
Wat het kost
Base64 codeert drie bytes als vier tekens, dus de gecodeerde vorm is ongeveer 33% groter dan het bestand. Dat hoort bij de codering zelf en is geen implementatiedetail: ze gebruikt 64 afdrukbare tekens om willekeurige bytes weer te geven, en 64 is 2⁶, dus in elk teken dat acht bits had kunnen dragen gaan er zes. Het voorvoegsel data:image/png;base64, komt daar met een paar dozijn tekens bij, wat niets is bij een foto en iets bij een icoon van 200 bytes.
Het loont om precies te zijn over die 33%, want hij wordt vaak overdreven. In het bestand op schijf, in het geparste document en in het geheugen is hij helemaal echt. Over het netwerk grotendeels niet. Tekstcompressie eet hem op: neem 12 KB aan al gecomprimeerde beeldgegevens, wat een JPEG of WebP is, dan is de Base64-vorm 16.000 tekens, maar na gzip komt hij terug op 12.070 bytes tegen 12.023 voor het gegzipte origineel. Dat is een overdrachtsboete van minder dan een halve procent, geen derde. Compressie vindt geen patronen in de beeldgegevens, maar wel makkelijk in het alfabet van 64 tekens dat eroverheen ligt.
Het groottegeargument is dus zwakker dan het meestal klinkt. Het cacheargument niet.
Een los afbeeldingsbestand wordt één keer gedownload, onder zijn eigen URL gecachet, en hergebruikt op elke pagina die ernaar verwijst en bij elk volgend bezoek. Een ingesloten afbeelding is deel van het document. Hij wordt opnieuw gedownload met elke pagina die hem draagt, elke keer opnieuw gedecodeerd, en kan nooit los van de tekst eromheen gecachet worden, dus één woord op de pagina aanpassen maakt ook de afbeelding ongeldig.
Voor een logo op één pagina is dat niets. Voor een logo op elke pagina van een site is het strikt slechter dan een los bestand, en het verschil groeit met het aantal pagina’s, niet met de grootte van de afbeelding.
Wat je naast de cache inlevert
De minder zichtbare prijs is dat een ingesloten afbeelding voor de rest van het platform geen afbeelding meer is.
| Je verliest | Omdat |
|---|---|
loading="lazy" |
hij al met het document binnenkwam |
srcset en <picture> |
elke variant nog een volledige ingesloten kopie zou zijn |
| Verkleinen en formaatkeuze door een CDN | er geen URL meer is om te onderscheppen |
| Een eigen cacheduur | hij verloopt als het document verloopt |
| Een bruikbare foutmelding | een kapotte URI gewoon niet verschijnt |
Er zit ook een haakje aan de content security policy. Een strikte policy met img-src 'self' blokkeert data-URI’s meteen, en ze toestaan betekent data: aan de directive toevoegen. Dat is een kleine maar echte verruiming: data: in img-src geldt over het algemeen als acceptabel, data: in script-src beslist niet, en uit gewoonte versoepel je de twee makkelijk tegelijk.
Waar hij staat telt ook meer dan men denkt. CSS blokkeert het renderen: een stylesheet wordt volledig gedownload en geparst voordat de browser ook maar iets tekent. Een halve megabyte Base64 in een stylesheet vertraagt de eerste weergave van de hele pagina, inclusief alle delen die niets met de afbeelding te maken hebben.
Waarom het voordeel kromp
Onder HTTP/1.1 openden browsers zo’n zes verbindingen per host en stonden requests achter elkaar in de rij. Eén request weghalen hielp echt, en technieken als spritesheets en insluiten bestonden daarom.
HTTP/2 en HTTP/3 multiplexen veel requests over één verbinding, dus een tweede bestand kost nu weinig en de rekensom die insluiten rechtvaardigde gaat grotendeels niet meer op. Uit dezelfde tijd kwam HTTP/2 Server Push, bedoeld om de laatste rondgang weg te nemen, en Chrome haalde de ondersteuning in 2022 weg omdat het lastiger goed te krijgen was dan het opleverde. Het patroon is steeds hetzelfde: het request is niet meer het dure deel.
Wanneer het nog steeds de goede keuze is
| Situatie | Waarom |
|---|---|
| Klein icoon in een CSS-bestand | scheelt een request voor een paar honderd bytes |
| HTML-mail | externe afbeeldingen worden standaard geblokkeerd |
| Eén zelfstandig bestand | geen bestanden om mee te sturen |
| Kritieke placeholder | verschijnt voordat er iets anders laadt |
De praktijk is uitgekomen op een zachte band in plaats van een lijn: een paar kilobyte is zo weinig dat het request besparen wint, tien of meer is zoveel dat het dat niet doet, en het midden hangt af van hoe vaak de pagina wordt geserveerd en of dezelfde afbeelding er meer dan eens op staat. Herhaling beslist vaker dan grootte. Eén illustratie van 20 KB op een landingspagina waar niemand terugkomt is prima; een icoon van 2 KB ingesloten in elke pagina van een documentatiesite niet, en geen grens in kilobytes vertelt je dat.
De uitzondering voor SVG
Sla Base64 over bij SVG. Een SVG is tekst, dus hem in CSS met procentcodering opnemen geeft een kleiner resultaat dan Base64 van hetzelfde bestand: procentcodering vergroot alleen de tekens die echt ge-escapet moeten worden, terwijl Base64 alles een derde groter maakt. Een icoon van 299 bytes van deze site is 400 tekens als Base64 en 329 met de minimale escaping die CSS vraagt.
Hij is achteraf ook leesbaar in de stylesheet, wat soms uitmaakt, en een vulkleur aanpassen is een bewerking in plaats van een hercodering.
Vragen die mensen stellen
Comprimeert coderen de afbeelding opnieuw? Dat zou niet moeten. De originele bytes coderen geeft een afbeelding die byte voor byte gelijk is; via een canvas gaan zou hem opnieuw coderen.
Kan ik data-URI’s in een img-tag gebruiken? Ja, en in CSS url(), en in een SVG-element image.
Werken ze in mail? Meestal niet; Gmail en Outlook halen ze weg of weigeren ze. Dat is het enige geval waarin het antwoord een bijlage is.
Is er een groottegrens? Browsers accepteren meerdere megabytes, maar een data-URI van die omvang maakt het bestand eromheen met de hand onleesbaar en traag te verwerken.
En als het eindproduct één bestand moet zijn? Sluit dan alles in, en het argument verdwijnt. Een offline rapport, een sjabloon, een pagina die als bijlage gaat: er is niets om apart te cachen, dus de enige prijs die overblijft is de derde die compressie grotendeels wegneemt.
De tool afbeelding naar Base64 codeert de originele bytes en geeft je de vorm voor CSS of HTML, Base64 coderen en Base64 decoderen doen tekst, alle drie voorlopig in het Engels, en afbeelding comprimeren is de stap die het waard is vóór al het andere, want een derde van een kleiner bestand is een kleinere derde.