🖇️

Osadzanie obrazów jako Base64 w HTML/CSS: zalety i wady

Data URI pozwalają wstawić obraz bezpośrednio do HTML-a i CSS-a. Czasem to genialna optymalizacja, czasem katastrofa. Pokazuję, jak odróżnić jedno od drugiego.

· 6min czytania

W web developmencie istnieje technika, w której zamiast linkować do pliku obrazu przez <img src="logo.png">, wkleja się bajty obrazu bezpośrednio w HTML lub CSS jako ciąg Base64:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..." />

Nazywa się to data URI. Potrafi przyspieszyć ładowanie strony albo je spowolnić, zmniejszyć rozmiar strony albo go powiększyć - i przy złym użyciu wpakuje cię w zaskakująco dużo kłopotów. Przyjrzyjmy się, kiedy to sensowna optymalizacja, a kiedy błąd.

Czym jest data URI

Data URI to URL, który zawiera same dane, a nie wskaźnik do danych gdzieś indziej. Format:

data:<mime-type>;base64,<base64-encoded-data>

Dla obrazu PNG:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...

Dla SVG:

data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...

Dla SVG można też pominąć Base64 i użyć URL-encoded tekstu:

data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'>...</svg>

Przeglądarka parsuje URI, dekoduje dane i renderuje obraz tak, jakby był wczytany z pliku.

Po co w ogóle to robić

Typowy argument: oszczędzasz żądanie HTTP.

Bez data URI przeglądarka wysyła osobne żądanie o image.png - jeden HTTP request, jeden round-trip, potem pobieranie. Z data URI obraz jest już w HTML-u, renderuje się natychmiast po sparsowaniu dokumentu.

W czasach przed HTTP/2 każde żądanie miało zauważalny narzut. Na stronie z pięćdziesięcioma małymi ikonkami to się sumowało. Wklejanie małych obrazów jako data URI mogło mierzalnie przyspieszyć renderowanie.

Dlaczego to częściej zły pomysł niż dobry

Data URI pompują rozmiar pliku, w którym siedzą

Base64 dodaje 33% narzutu do surowego rozmiaru pliku. Ikonka 1 KB dorzuca ~1,3 KB do HTML-a. Dla jednej ikonki nic. Dla pięćdziesięciu dokładasz 65 KB do payloadu HTML - który trzeba pobrać i sparsować, zanim cokolwiek się wyrenderuje.

Nie możesz ich cache’ować osobno

Plik logo.png pobrany raz jest cache’owany przez przeglądarkę i wykorzystywany na każdej stronie. Logo zakodowane w Base64 jest częścią każdej strony HTML, na której się pojawia. Pierwsza wizyta: ten sam czas. Każda kolejna strona: marnotrawstwo transferu.

Blokują równoległe pobieranie

Przeglądarki pobierają wiele zasobów równolegle. Data URI są częścią samego HTML - konkurują z pierwszym pobraniem dokumentu, a nie pobierają się obok niego. HTML 500 KB przez wklejone obrazy? Strona dłużej stoi pusta.

HTTP/2 i HTTP/3 w dużej mierze eliminują pierwotną korzyść

Główny argument za data URI - “unikamy dodatkowych żądań HTTP” - był silny w HTTP/1.1, gdzie każde żądanie miało realny koszt. HTTP/2 multipleksuje wiele żądań przez jedno połączenie praktycznie bez narzutu. Na nowoczesnych serwerach dwadzieścia osobnych żądań o obrazy nie jest istotnie wolniejsze od jednego. Narzut siedzi w danych, nie w samym żądaniu.

Kiedy data URI ma sens

Mimo wad są konkretne przypadki, gdzie to działa.

Bardzo małe, często używane ikonki - ikona CSS 100 bajtów (ptaszek, strzałka) używana wielokrotnie na jednej stronie to dobry kandydat. Narzut jest mały, renderuje się natychmiast, a oszczędność round-tripa jest warta więcej niż dodatkowa waga HTML-a.

Obrazy tła w CSS używane na każdej stronie - pliki CSS cache’ują się długoterminowo. Data URI wewnątrz CSS cache’uje się razem z CSS, więc argument o braku cache’owania traci na sile. Dla małych obrazów tła (gradienty niemożliwe do zrobienia samym CSS, nakładki teksturowe) data URI w CSS bywa czystszy niż osobne pliki.

HTML w emailach - wiele klientów pocztowych domyślnie blokuje zewnętrzne obrazy. Osadzenie ich jako data URI sprawia, że renderują się niezależnie od blokady. Ale uwaga - niektóre klienty (Gmail, Outlook) blokują też data URI, więc zawsze testuj.

Aplikacje offline-first - jeśli twoja aplikacja musi działać bez sieci, data URI gwarantują, że spakowane obrazy zawsze się wyświetlą. Realne zastosowanie przy PWA i aplikacjach instalowanych.

Obrazy generowane runtime’owo - rysujesz na <canvas> i musisz wyświetlić lub pobrać wynik. Naturalnym wyjściem jest Base64 data URL, bez zapisywania do pliku.

Artefakty do druku i samodzielne pliki - HTML przeznaczony do druku, wysyłki mailem lub zapisania jako jeden plik korzysta z data URI, bo nie ma wtedy osobnych plików do zarządzania.

Kiedy data URI to zły pomysł

Duże obrazy - cokolwiek powyżej ~10 KB prawie zawsze powinno być osobnym plikiem. Narzut HTML-a za wysoki, korzyść z cache’u za ważna.

Obrazy, które się zmieniają - avatar, zdjęcie nagłówka, zdjęcie produktu. To powinny być pliki, cache’owane i podmieniane. Data URI zamknie obraz w HTML-u.

Obrazy istotne dla SEO - wyszukiwarki obsługują data URI, ale priorytetowo traktują osobne pliki dla wyszukiwania obrazów. Jeśli obraz ma rankować w Google Images, zrób z niego plik z dobrym alt-tekstem.

Obrazy używane wielokrotnie - ta sama ikonka w dwunastu miejscach z data URI płaci koszt kodowania dwanaście razy. Plik jest cache’owany raz i ponownie wykorzystywany.

Zasada kciuka

Dla większości nowoczesnych stron na HTTP/2 lub HTTP/3:

Rozmiar zasobuUżywany razUżywany wielokrotnie
< 1 KBData URI OKData URI OK
1-5 KBData URI OKOsobny plik
5-10 KBNa stykuOsobny plik
> 10 KBOsobny plikOsobny plik

W razie wątpliwości - zmierz. Chrome Lighthouse i WebPageTest pokazują realny wpływ.

Praktyczny workflow

Zdecydowałeś, że dany obraz nadaje się na data URI:

  1. Najpierw zoptymalizuj obraz. Przepuść go przez kompresor - 10 KB PNG skompresowane do 3 KB to znacznie lepszy kandydat. Kompresor obrazów.
  2. Zamień na Base64. Wrzuć plik do narzędzia Base64. Ciąg Base64 dostaniesz od razu.
  3. Zbuduj data URI. Doklej data:image/png;base64, (albo pasujący MIME type) na początek ciągu.
  4. Wklej w HTML lub CSS. HTML: <img src="data:...">. CSS: background: url(data:...).
  5. Przetestuj w wielu przeglądarkach i klientach poczty.

Uwaga o SVG

SVG to przypadek specjalny. Obrazy SVG są tekstowe, więc można je osadzać jako surowy tekst, nie Base64. Surowy SVG jest zwykle mniejszy - Base64 zawsze dodaje 33%, a surowy SVG potrzebuje tylko lekkiego escape’owania znaków specjalnych.

/* SVG zakodowany w Base64 (większy) */
background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3...');

/* URL-encoded tekst SVG (mniejszy, często o 40%+) */
background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg">...');

Dla SVG preferuj URL-encoded tekst zamiast Base64.

SEO i dostępność

Kilka rzeczy warto wiedzieć:

  • alt działa normalnie na <img> z data URI - używaj go.
  • Prawy klik → zapisz obraz działa, ale zapisana nazwa pliku będzie generyczna.
  • Indeksowanie przez wyszukiwarki radzi sobie z data URI, ale priorytetowo traktuje osobne pliki.
  • Content Security Policy (CSP) może wymagać jawnego zezwolenia na data: URI.

Jeśli chcesz teraz zamienić obraz na Base64 - żeby poeksperymentować z data URI, wkleić w szablon maila albo w chat - nasz enkoder Base64 to obsłuży. Wrzuć plik, skopiuj ciąg, zbuduj data URI. Wszystko lokalnie, więc firmowe logo albo prywatne materiały zostają na twoim urządzeniu.

Data URI to narzędzie precyzyjne. Użyte do właściwego zasobu we właściwym miejscu - oszczędzają żądanie i mogą przyspieszyć stronę. Używane bezkrytycznie pompują HTML i marnują transfer. Trzydzieści sekund na decyzję zwraca się z nawiązką.