Wydajność obrazu

Obrazy są często najwięcej i najpowszechniejszymi zasobami w internecie. W efekcie optymalizacja obrazów może znacznie zwiększyć skuteczność Twojej witryny. W większości przypadków optymalizacja obrazów oznacza skrócenie czasu działania sieci przez wysyłanie mniejszej liczby bajtów, ale można też zoptymalizować liczbę bajtów wysyłanych do użytkownika, wyświetlając obrazy w rozmiarze odpowiednim do urządzenia użytkownika.

Obrazy można dodawać do strony za pomocą elementów <img> lub <picture> albo właściwości background-image CSS.

Rozmiar obrazu

Pierwszą optymalizacja, jaką można przeprowadzić, aby zacząć korzystać z zasobów graficznych, to wyświetlenie obrazu w odpowiednim rozmiarze. W tym przypadku termin size odnosi się do wymiarów obrazu. Nie uwzględniając żadnych innych zmiennych, optymalny rozmiar obrazu wyświetlany w kontenerze o wymiarach 500 x 500 pikseli powinien wynosić 500 x 500 pikseli. Na przykład obraz kwadratowy o powierzchni 1000 pikseli będzie 2 razy większy od potrzebnego.

Jednak na wybór odpowiedniego rozmiaru obrazu wpływa wiele zmiennych, przez co wybór właściwego rozmiaru w każdym przypadku jest dość skomplikowany. W 2010 roku, po wprowadzeniu iPhone'a 4, rozdzielczość ekranu (640 x 960) była dwukrotnie większa niż w iPhonie 3 (320 x 480). Jednak fizyczny rozmiar ekranu iPhone'a 4 pozostaje mniej więcej taki sam jak iPhone 3.

Wyświetlanie wszystkiego w wyższej rozdzielczości znacznie zmniejszyłoby tekst i obrazy – dokładnie o połowę poprzedniego rozmiaru. Jeden piksel stał się 2 pikselami urządzenia. Jest to tzw. współczynnik pikseli urządzeń (DPR). iPhone 4 i wiele późniejszych modeli iPhone'ów uzyskiwało 2DPR.

Wróćmy do poprzedniego przykładu. Jeśli urządzenie ma wartość DPR równą 2, a obraz jest wyświetlany w kontenerze o wymiarach 500 x 500 pikseli, optymalnym rozmiarem jest teraz kwadratowy obraz o wymiarach 1000 pikseli (nazywany rozmiarem wewnętrznym). Podobnie, jeśli wartość DPR urządzenia wynosi 3, optymalnym rozmiarem będzie kwadratowy obraz o wymiarach 1500 pikseli.

srcset

Element <img> obsługuje atrybut srcset, który umożliwia określenie listy możliwych źródeł obrazów, z których może korzystać przeglądarka. Każde podane źródło obrazu musi zawierać adres URL obrazu i deskryptor szerokości lub gęstości pikseli.

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>

Poprzedni fragment kodu HTML korzysta z deskryptora gęstości pikseli, aby wskazać przeglądarce, że ma ona użyć wartości image-500.png na urządzeniach z DPR 1, image-1000.jpg na urządzeniach o wartości DPR 2 i image-1500.jpg na urządzeniach o tej wartości 3.

Choć może się wydawać, że wszystko jest w porządku, DPR ekranu nie jest jedynym kwestią podczas wybierania optymalnego obrazu dla danej strony. Układ strony to kolejny element, który należy wziąć pod uwagę.

sizes

Poprzednie rozwiązanie działa tylko wtedy, gdy wyświetlasz obraz w tym samym rozmiarze w pikselach CSS we wszystkich widocznych obszarach. W wielu przypadkach układ strony i rozmiar kontenera zmieniają się w zależności od urządzenia użytkownika.

Atrybut sizes umożliwia określenie zestawu rozmiarów źródeł, przy czym każdy rozmiar źródłowy składa się z warunku multimediów i wartości. Atrybut sizes określa zamierzony rozmiar wyświetlanego obrazu w pikselach CSS. W połączeniu z deskryptorami szerokości srcset przeglądarka może wybrać źródło obrazu najlepiej dostosowane do urządzenia użytkownika.

<img
  alt="An image"
  width="500"
  height="500"
  src="/image-500.jpg"
  srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"
  sizes="(min-width: 768px) 500px, 100vw"
>

W poprzednim fragmencie kodu HTML atrybut srcset określa listę rozdzielonych przecinkami grafik, które może wybrać przeglądarka. Każda propozycja na liście składa się z adresu URL obrazu, po którym następuje składnia oznaczająca jego wewnętrzną szerokość. Wewnętrzny rozmiar obrazu to jego wymiary. Na przykład deskryptor 1000w wskazuje, że wewnętrzna szerokość obrazu ma 1000 pikseli.

Na podstawie tych informacji przeglądarka ocenia stan multimediów w atrybucie sizes i – w tym przypadku – otrzymuje instrukcję, że jeśli szerokość widocznego obszaru na urządzeniu przekroczy 768 pikseli, obraz będzie wyświetlany o szerokości 500 pikseli. Na mniejszych urządzeniach obraz wyświetla się 100vw lub całej szerokości widocznego obszaru.

Przeglądarka może następnie połączyć te informacje z listą źródeł obrazów srcset, aby znaleźć optymalny obraz. Jeśli na przykład użytkownik korzysta z urządzenia mobilnego z ekranem o szerokości 320 pikseli i DPR równym 3, obraz jest wyświetlany tutaj: 320 CSS pixels x 3 DPR = 960 device pixels. W tym przykładzie obraz o najbliższym rozmiarze to image-1000.jpg, który ma wewnętrzną szerokość 1000 pikseli (1000w).

Formaty plików

Przeglądarki obsługują kilka różnych formatów plików graficznych. Nowoczesne formaty obrazów, takie jak WebP i AVIF, mogą zapewniać lepszą kompresję niż PNG czy JPEG, dzięki czemu rozmiar pliku graficznego jest mniejszy, a jego pobieranie trwa krócej. Wyświetlając obrazy w nowoczesnych formatach, możesz skrócić czas wczytywania zasobów, przez co największe wyrenderowanie treści (LCP) może się zmniejszyć.

WebP to powszechnie obsługiwany format, który działa we wszystkich nowoczesnych przeglądarkach. WebP często ma lepszą kompresję niż JPEG, PNG i GIF, zapewniając zarówno kompresję stratną, jak i bezstratną. WebP obsługuje też przezroczystość kanału alfa nawet w przypadku kompresji stratnej – funkcji, której nie ma kodek JPEG.

Format AVIF to nowszy format obrazu, ale nie jest tak rozpowszechniony jak WebP, ale zapewnia przyzwoitą obsługę w różnych przeglądarkach. Format AVIF obsługuje zarówno kompresję stratną, jak i bezstratną. Testy wykazały w niektórych przypadkach ponad 50% oszczędności w porównaniu do plików JPEG. AVIF udostępnia też funkcje Wide Color Gamut (WCG) i High Dynamic Range (HDR).

Kompresja

Istnieją 2 rodzaje kompresji obrazów:

  1. Spada kompresja
  2. Bezstratna kompresja

Kompresja stratna polega na ograniczaniu dokładności obrazu przez kwantyzację. Dodatkowe informacje o kolorach mogą być odrzucane, stosując podpróbkowanie kolorów. Kompresja stratna jest najskuteczniejsza w przypadku obrazów o dużej gęstości z dużą ilością szumu i kolorów, zwykle na zdjęciach i obrazach o podobnej zawartości. Dzieje się tak, ponieważ artefakty powstające w wyniku kompresji stratnej są znacznie mniej zauważone na tak szczegółowych obrazach. Kompresja stratna może być jednak mniej skuteczna w przypadku obrazów zawierających ostre krawędzie, takie jak grafika linii, mniej ostre szczegóły lub tekst. Kompresja stratna może być stosowana do obrazów JPEG, WebP i AVIF.

Kompresja bezstratna zmniejsza rozmiar pliku, kompresując obraz bez utraty danych. Kompresja bezstratna opisuje piksel na podstawie różnicy z sąsiadującymi z nim pikselami. Kompresja bezstratna jest używana w przypadku formatów GIF, PNG, WebP i AVIF.

Obrazy możesz skompresować za pomocą usług Squoosh, ImageOptim lub usługi optymalizacji obrazów. Nie ma uniwersalnego ustawienia, które sprawdzi się we wszystkich przypadkach. Zalecamy eksperymentowanie z różnymi poziomami kompresji, aż znajdziesz kompromis między jakością obrazu a rozmiarem pliku. Niektóre zaawansowane usługi optymalizacji obrazów mogą zrobić to za Ciebie automatycznie, ale mogą nie być opłacalne dla wszystkich użytkowników.

Element <picture>

Element <picture> zapewnia większą elastyczność przy wskazywaniu kilku kandydujących obrazów:

<picture>
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image.jpg"
  >
</picture>

Gdy w elemencie <picture> używasz elementów <source>, możesz dodać obsługę obrazów w formacie AVIF i WebP, a jeśli przeglądarka nie obsługuje nowoczesnych formatów, wrócić do bardziej zgodnych starszych formatów graficznych. W ten sposób przeglądarka wybiera pierwszy pasujący element <source>. Jeśli może wyrenderować obraz w tym formacie, użyje tego obrazu. W przeciwnym razie przeglądarka przechodzi do następnego określonego elementu <source>. W poprzednim fragmencie kodu HTML format AVIF ma wyższy priorytet niż WebP i wybiera format JPEG, jeśli nie jest obsługiwany format AVIF ani WebP.

Element <picture> wymaga umieszczonego w nim elementu <img>. Atrybuty alt, width i height są zdefiniowane w <img> i używane niezależnie od tego, która wartość <source> jest wybrana.

Element <source> obsługuje też atrybuty media, srcset i sizes. Podobnie jak w przypadku poprzedniego przykładu <img>, wskazują one przeglądarce, który obraz ma być wybierany w różnych widocznych obszarach.

<picture>
  <source
    media="(min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

Atrybut media przyjmuje warunek mediów. W poprzednim przykładzie jako warunek dotyczący multimediów jest używany DPR urządzenia. Wszystkie urządzenia o wartości DPR większej lub równej 1,5 będą używać pierwszego elementu <source>. Element <source> informuje przeglądarkę, że na urządzeniach o szerokości widocznego obszaru większej niż 768 pikseli wybrany kandydujący obraz jest wyświetlany o szerokości 500 pikseli. Na mniejszych urządzeniach zajmuje to całą szerokość widocznego obszaru. Dzięki połączeniu atrybutów media i srcset masz większą kontrolę nad tym, którego obrazu użyć.

Widać to w tabeli poniżej, w której ocenianych jest kilka szerokości widocznego obszaru i różnych współczynników pikseli urządzenia:

Szerokość widocznego obszaru (w pikselach) 1 DPR 1,5 DPR 2 KD 3 DPR
320 500.jpg 500.jpg 500.jpg 1000.jpg
480 500.jpg 500.jpg 1000.jpg 1500.jpg
560 500.jpg 1000.jpg 1000.jpg 1500.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

Urządzenia z numerem DPR 1 pobierają obraz image-500.jpg. Dotyczy to także większości użytkowników komputerów, którzy widzą obraz w rozmiarze zewnętrznym wynoszącym 500 pikseli. Z drugiej strony użytkownicy urządzeń mobilnych o DPR równy 3 pobierają potencjalnie większą wartość image-1500.jpg – to samo zdjęcie co na komputerach z DPR równym 3.

<picture>
  <source
    media="(min-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <source
    media="(max-width: 560px) and (min-resolution: 1.5x)"
    srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"
    sizes="(min-width: 768px) 500px, 100vw"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

W tym przykładzie element <picture> został dostosowany tak, aby zawierał dodatkowy element <source>, który pozwala używać różnych obrazów w przypadku szerokich urządzeń o wysokiej wartości DPR:

Szerokość widocznego obszaru (w pikselach) 1 DPR 1,5 DPR 2 KD 3 DPR
320 500.jpg 500.jpg 500.jpg 1000-sm.jpg
480 500.jpg 500.jpg 1000-sm.jpg 1500-sm.jpg
560 500.jpg 1000-sm.jpg 1000-sm.jpg 1500-sm.jpg
1024 500.jpg 1000.jpg 1000.jpg 1500.jpg
1920 500.jpg 1000.jpg 1000.jpg 1500.jpg

Dzięki temu dodatkowemu zapytaniu widać, że image-1000-sm.jpg i image-1500-sm.jpg są wyświetlane na małych widocznych obszarach. Te dodatkowe informacje pozwalają jeszcze bardziej skompresować obrazy. Artefakty kompresji przy takim rozmiarze i gęstości nie są dobrze widoczne. Nie wpływają też na jakość obrazu na komputerach.

Możesz też dostosować atrybuty srcset i media, aby uniknąć wyświetlania dużych obrazów w małych widocznych obszarach:

<picture>
  <source
    media="(min-width: 560px)"
    srcset="/image-500.jpg, /image-1000.jpg 2x, /image-1500.jpg 3x"
  >
  <source
    media="(max-width: 560px)"
    srcset="/image-500.jpg 1x, /image-1000.jpg 2x"
  >
  <img
    alt="An image"
    width="500"
    height="500"
    src="/image-500.jpg"
  >
</picture>

W poprzednim fragmencie kodu HTML deskryptory szerokości zostały usunięte na rzecz deskryptorów współczynnika pikseli urządzenia. Zdjęcia wyświetlane na urządzeniach mobilnych mogą być ograniczone do /image-500.jpg lub /image-1000.jpg, nawet na urządzeniach o wartości DPR równej 3.

Jak radzić sobie ze złożonością

Podczas pracy z obrazami elastycznymi można stosować wiele różnych rozmiarów i formatów dla każdego obrazu. W poprzednim przykładzie używane są odmiany każdego rozmiaru, ale wykluczają one formaty AVIF i WebP. Ile wariantów trzeba postawić? Podobnie jak w przypadku wielu problemów inżynieryjnych, odpowiedź zwykle brzmi: „to zależy”.

Zastosowanie jak największej liczby odmian obrazu w celu uzyskania najlepszego dopasowania może być kuszące, ale każdy dodatkowy wariant obrazów jest droższy i ogranicza wykorzystanie pamięci podręcznej przeglądarki. W przypadku tylko jednego wariantu każdy użytkownik otrzymuje ten sam obraz, więc można go bardzo wydajnie buforować.

Z drugiej strony jeśli występuje wiele odmian, każdy z nich wymaga osobnego wpisu w pamięci podręcznej. Koszty serwera mogą wzrosnąć i zmniejszyć wydajność, jeśli wpis w pamięci podręcznej wariantu wygasł i będzie trzeba ponownie pobrać obraz z serwera pierwotnego.

Poza tym rozmiar dokumentu HTML zwiększa się z każdą wersją. Może się okazać, że w przypadku każdego obrazu przesyłasz kilka kilobajtów kodu HTML.

Wyświetlaj obrazy na podstawie nagłówka żądania Accept

Nagłówek żądania HTTP Accept informuje serwer, które typy treści może rozpoznawać przeglądarka użytkownika. Dzięki tym informacjom serwer może wyświetlać obraz w optymalnym formacie bez konieczności dodawania dodatkowych bajtów do odpowiedzi HTML.

if (request.headers.accept) {
  if (request.headers.accept.includes('image/avif')) {
    return reply.from('image.avif');
  } else if (request.headers.accept.includes('image/webp')) {
    return reply.from('image.webp');
  }
}

return reply.from('image.jpg');

Poprzedni fragment kodu HTML to uproszczona wersja kodu, którą możesz dodać do backendu JavaScript serwera, aby wybrać i wyświetlać obraz w optymalnym formacie. Jeśli nagłówek Accept żądania zawiera element image/avif, wyświetlany jest obraz AVIF. W przeciwnym razie, jeśli nagłówek Accept zawiera element image/webp, wyświetlany jest obraz WebP. Jeśli żaden z tych warunków nie jest spełniony, wyświetla się obraz JPEG.

Możesz modyfikować odpowiedzi na podstawie zawartości nagłówka żądania Accept na niemal każdym typie serwera WWW – na przykład przepisywać żądania obrazów na serwerach Apache na podstawie nagłówka Accept za pomocą mod_rewrite.

Działa to podobnie do sieci dystrybucji treści graficznych (CDN). Sieci CDN z obrazami to świetne rozwiązania do optymalizowania obrazów i wysyłania optymalnego formatu w zależności od urządzenia i przeglądarki użytkownika.

Najważniejsze jest znalezienie równowagi, wygenerowanie rozsądnej liczby pasujących obrazów i zmierzenie wpływu na wrażenia użytkownika. Różne obrazy przynoszą różne wyniki, a optymalizacje zastosowane do każdego z nich zależą od rozmiaru obrazu na stronie oraz od urządzeń, z których korzystają użytkownicy. Na przykład baner powitalny o pełnej szerokości może wymagać większej liczby wariantów niż miniatury na stronie z informacjami o produkcie w e-commerce.

Leniwe ładowanie

Można użyć atrybutu loading, aby nakazać przeglądarce leniwe ładowanie obrazów, gdy pojawią się one w widocznym obszarze. Wartość atrybutu lazy informuje przeglądarkę, aby nie pobierała obrazu, dopóki nie znajdzie się on w widocznym obszarze (lub w jego pobliżu). Oszczędza to przepustowość, dzięki czemu przeglądarka może priorytetowo traktować zasoby potrzebne do wyrenderowania kluczowych treści, które znajdują się już w widocznym obszarze.

decoding

Atrybut decoding informuje przeglądarkę, jak ma zdekodować obraz. Wartość async informuje przeglądarkę, że obraz można dekodować asynchronicznie, co może skrócić czas renderowania innych treści. Wartość sync informuje przeglądarkę, że obraz powinien być prezentowany w tym samym czasie co inne treści. Dzięki domyślnej wartości auto przeglądarka może zdecydować, co jest najlepsze dla użytkownika.

Wersje demonstracyjne

Sprawdź swoją wiedzę

Które formaty obrazów obsługują kompresję bezstratną?

GIF.
Dobrze!
JPEG.
Spróbuj ponownie.
PNG
Dobrze!
WebP.
Dobrze!
AVIF.
Dobrze!

Które formaty obrazów obsługują kompresję stratną?

GIF.
Spróbuj ponownie. Chociaż format GIF obsługuje tylko ograniczoną paletę 256 kolorów, przed konwersją do formatu GIF należy zastosować kodowanie stratne.
JPEG.
Dobrze!
PNG
Spróbuj ponownie.
WebP.
Dobrze!
AVIF.
Dobrze!

Co deskryptor szerokości (np. 1000w) informuje przeglądarkę o proponowanym obrazie określonym w atrybucie srcset?

Szerokość zewnętrzna obrazu, czyli wymiary obrazu w układzie po zastosowaniu stylów na stronie.
Spróbuj ponownie.
Wewnętrzna szerokość obrazu, czyli jego wymiary.
Dobrze!

Co atrybut sizes informuje przeglądarkę o elemencie <img>, do którego jest stosowany?

Logika określająca, który kandydat określony w elemencie srcset elementu <img> powinien zostać wczytany, z uwzględnieniem wymiarów bieżącego widocznego obszaru użytkownika.
Dobrze!
Wewnętrzna szerokość obrazu do wczytania z atrybutu srcset elementu <img>.
Spróbuj ponownie.

Następny temat: wyniki filmów

Obrazy są najpowszechniejszym rodzajem multimediów wykorzystywanych w internecie, ale są daleko od jedynego, o którym musisz pamiętać, jeśli chodzi o skuteczność. Filmy to kolejny często spotykany typ mediów w internecie, który ma swoje własne parametry działania. W następnym module tego kursu poznasz techniki optymalizacji filmów i ich efektywne wczytywanie.