Obrazy w wysokiej rozdzielczości dla zmiennej gęstości pikseli

Jedną z cech dzisiejszego złożonego ekosystemu urządzeń jest bardzo szeroki zakres gęstości pikseli ekranu. Niektóre urządzenia mają wyświetlacze o bardzo wysokiej rozdzielczości, podczas gdy inne są w tym aspekcie gorsze. Deweloperzy aplikacji muszą obsługiwać różne gęstości pikseli, co może być dość trudne. W przypadku internetu mobilnego problemy te są potęgowane przez kilka czynników:

  • duża różnorodność urządzeń o różnych formatach.
  • Ograniczona przepustowość sieci i żywotność baterii.

W przypadku obrazów celem deweloperów aplikacji internetowych jest wyświetlanie obrazów najwyższej jakości w jak najbardziej efektywny sposób. Z tego artykułu dowiesz się, jak to robić dzisiaj i w najbliższej przyszłości.

W miarę możliwości unikaj obrazów

Zanim otworzysz tę pułapkę na muchy, pamiętaj, że w internecie działa wiele zaawansowanych technologii, które są w dużej mierze niezależne od rozdzielczości i DPI. W szczególności tekst, SVG i duża część kodu CSS „działają” dzięki funkcji automatycznego skalowania pikseli w internecie (za pomocą devicePixelRatio).

Nie zawsze jednak można uniknąć obrazów rastrowych. Możesz np. otrzymać zasoby, które trudno byłoby odtworzyć w czystym formacie SVG/CSS, lub masz do czynienia ze zdjęciem. Możesz automatycznie przekonwertować obraz na SVG, ale wektoryzacja zdjęć ma niewielki sens, ponieważ powiększone wersje zwykle nie wyglądają dobrze.

Tło

Krótka historia gęstości wyświetlania

W początkach wyświetlacze komputerów miały gęstość pikseli 72 lub 96 dpi (punktów na cal).

Gęstość pikseli na wyświetlaczach stopniowo się zwiększa, głównie ze względu na zastosowanie w telefonach komórkowych, w których przypadku użytkownicy zwykle trzymają telefony bliżej twarzy, co sprawia, że piksele są bardziej widoczne. W 2008 roku telefony o rozdzielczości 150 dpi stały się nową normą. Trend zwiększania gęstości pikseli na ekranie się utrzymał, a dzisiejsze nowe telefony mają wyświetlacze o rozdzielczości 300 dpi (nazwanej przez Apple „Retina”).

Świętym Graalem jest oczywiście wyświetlacz, na którym piksele są całkowicie niewidoczne. W przypadku formatu telefonu obecna generacja wyświetlaczy Retina/HiDPI może być zbliżona do ideału. Jednak nowe kategorie sprzętu i urządzeń do noszenia, takie jak Project Glass, prawdopodobnie będą nadal zwiększać gęstość pikseli.

W praktyce obrazy o niskiej gęstości powinny wyglądać tak samo na nowych ekranach jak na starych, ale w porównaniu z ostrą grafiką o wysokiej gęstości, do której użytkownicy są przyzwyczajeni, obrazy o niskiej gęstości wyglądają dziwnie i pikselatowo. Poniżej znajduje się przybliżone symulowanie tego, jak obraz w rozdzielczości 1x będzie wyglądał na wyświetlaczu w rozdzielczości 2x. Zdjęcie w rozdzielczości 2 x wygląda za to całkiem nieźle.

Baboon 1x
Baboon 2x
Baboons! na ekranach o różnej gęstości pikseli.

Piksele w internecie

Gdy tworzono sieć, 99% wyświetlaczy miało rozdzielczość 96 dpi (lub udawało, że ma taką rozdzielczość), a w tym zakresie nie przewidziano zbyt wielu opcji. Ze względu na duże zróżnicowanie rozmiarów i gęstości ekranów potrzebowaliśmy standardowego sposobu na to, aby obrazy dobrze wyglądały na różnych ekranach o różnych gęstościach i wymiarach.

Specyfikacja HTML rozwiązała ten problem, definiując piksel referencyjny, którego producenci używają do określania rozmiaru piksela CSS.

Korzystając z pikselu referencyjnego, producent może określić rozmiar fizycznego piksela urządzenia w stosunku do piksela standardowego lub idealnego. Ten współczynnik nazywa się współczynnikiem pikseli urządzenia.

Obliczanie współczynnika pikseli urządzenia

Załóżmy, że telefon ma ekran o fizycznym rozmiarze piksela 180 pikseli na cal (ppi). Obliczenie współczynnika pikseli urządzenia wymaga wykonania 3 czynności:

  1. Porównaj rzeczywistą odległość, w której trzymane jest urządzenie, z odległością dla piksela referencyjnego.

    Zgodnie ze specyfikacją przy 28 calach idealna liczba pikseli na cal to 96. Ponieważ jednak jest to smartfon, użytkownicy trzymają go bliżej twarzy niż laptopa. Szacujemy, że odległość wynosi 18 cali.

  2. Aby uzyskać idealną gęstość pikseli dla danej odległości, pomnóż współczynnik odległości przez standardową gęstość pikseli (96 ppi).

    idealPixelDensity = (28/18) × 96 = 150 pikseli na cal (w przybliżeniu)

  3. Aby uzyskać współczynnik pikseli urządzenia, należy wziąć iloraz fizycznej gęstości pikseli i idealnej gęstości pikseli.

    devicePixelRatio = 180/150 = 1,2

Sposób obliczania devicePixelRatio
Diagram pokazujący jeden referencyjny kątowy piksel, aby zilustrować sposób obliczania współczynnika devicePixelRatio.

Gdy przeglądarka musi określić, jak zmienić rozmiar obrazu, aby pasował do ekranu zgodnie z idealną lub standardową rozdzielczością, odwołuje się do współczynnika pikseli urządzenia wynoszącego 1,2, co oznacza, że na każde 1 idealny piksel przypada 1,2 fizycznych pikseli. Oto formuła do przeliczania pikseli idealnych (zgodnie ze specyfikacją internetową) i fizycznych (punktów na ekranie urządzenia):

physicalPixels = window.devicePixelRatio * idealPixels

W przeszłości dostawcy urządzeń zaokrąglają devicePixelRatios(DPR). iPhone i iPad firmy Apple raportują DPR 1, a ich odpowiedniki Retina – 2. Specyfikacja usługi porównywania cen zaleca, aby

jednostka piksela odnosi się do liczby całkowitej pikseli urządzenia, która najlepiej przybliża się do piksela referencyjnego.

Jednym z powodów, dla których proporcje okrągłe mogą być lepsze, jest to, że mogą one powodować mniej artefaktów poniżej piksela.

W rzeczywistości jednak urządzenia są znacznie bardziej zróżnicowane, a DPR telefonów z Androidem wynosi często 1, 5. Tablet Nexus 7 ma DPR ~1,33, który został obliczony w sposób podobny do opisanego powyżej. W przyszłości spodziewaj się większej liczby urządzeń z rozmaitterm DPR. Z tego powodu nigdy nie zakładaj, że klienci będą mieli dokładne DPR.

Omówienie technik tworzenia obrazów HiDPI

Istnieje wiele technik umożliwiających jak najszybsze wyświetlanie obrazów o najwyższej jakości. Można je ogólnie podzielić na 2 kategorie:

  1. optymalizowanie pojedynczych obrazów,
  2. Optymalizacja wyboru między wieloma obrazami.

Pojedyncze obrazy: użyj jednego obrazu, ale zrób z nim coś sprytnego. Te metody mają tę wadę, że nieuchronnie wiążą się z zawieszeniem się, ponieważ obrazy HiDPI będą pobierane nawet na starszych urządzeniach z niższym DPI. Oto kilka metod na rozwiązanie problemu dotyczącego pojedynczego obrazu:

  • mocno skompresowany obraz HiDPI.
  • Niesamowicie fajny format obrazu
  • Progresywny format obrazu

Podejście z użyciem wielu obrazów: użyj wielu obrazów, ale wybierz sprytny sposób na to, który z nich ma się wczytać. Takie podejścia wymagają od dewelopera tworzenia wielu wersji tego samego komponentu, a następnie opracowania strategii podejmowania decyzji. Dostępne opcje to:

  • JavaScript
  • Dostarczanie po stronie serwera
  • Zapytania multimedialne w CSS
  • Wbudowane funkcje przeglądarki (image-set(), <img srcset>)

mocno skompresowany obraz HiDPI.

Obrazy stanowią już aż 60% przepustowości zużywanej na pobieranie przeciętnej witryny. Podając obrazy w wysokiej rozdzielczości wszystkim klientom, zwiększymy tę liczbę. O ile się powiększy?

Przeprowadziłem kilka testów, w których wyniku wygenerowano fragmenty obrazu w rozdzielczości 1x i 2x z jakością JPEG 90, 50 i 20. Oto skrypt powłoki, którego użyłem do ich wygenerowania (za pomocą ImageMagick):

Przykład 1. Przykład kafelków 2. Przykład kafelków 3.
Przykłady obrazów o różnych poziomach kompresji i gęstości pikseli.

Na podstawie tego małego, nienaukowego próbkowania wydaje się, że kompresowanie dużych obrazów zapewnia dobry kompromis między jakością a rozmiarem. Moim zdaniem obrazy skompresowane 2 x wyglądają lepiej niż nieskompresowane obrazy 1 x.

Oczywiście wyświetlanie na urządzeniach 2x obrazów o niskiej jakości, które są mocno skompresowane, jest gorsze niż wyświetlanie obrazów o wyższej jakości, a opisane powyżej podejście powoduje kary za jakość obrazu. Jeśli porównasz jakość: 90 obrazów z jakością: 20 obrazów, zauważysz spadek ostrości i zwiększone ziarnistość. Te artefakty mogą być niedopuszczalne w przypadkach, gdy kluczowe znaczenie ma wysoka jakość zdjęć (np. w aplikacji do przeglądania zdjęć) lub w przypadku deweloperów aplikacji, którzy nie chcą iść na kompromis.

Powyższe porównanie zostało wykonane wyłącznie na podstawie skompresowanych plików JPEG. Warto pamiętać, że między powszechnie stosowanymi formatami obrazów (JPEG, PNG, GIF) istnieje wiele kompromisów, co prowadzi nas do…

Niesamowicie fajny format obrazu

WebP to atrakcyjny format pliku graficznego, który kompresuje obrazy bardzo dobrze, zachowując przy tym ich jakość. Oczywiście nie jest jeszcze dostępny wszędzie.

Jednym ze sposobów jest sprawdzenie obsługi WebP za pomocą JavaScriptu. Wczytujesz obraz o wymiarach 1 piksela za pomocą atrybutu data-uri, czekasz na wyzwolenie zdarzeń loaded lub error, a potem sprawdzasz, czy rozmiar jest prawidłowy. Modernizr zawiera skrypt wykrywania funkcji, który jest dostępny za pomocą Modernizr.webp.

Lepszym sposobem jest jednak użycie bezpośrednio w CSS funkcji image(). Jeśli masz obraz WebP i JPEG jako alternatywę, możesz napisać:

#pic {
  background: image("foo.webp", "foo.jpg");
}

Takie podejście ma kilka wad. Po pierwsze, image() nie jest wcale szeroko stosowany. Po drugie, choć kompresja WebP pokonuje JPEG, to nadal jest to stosunkowo niewielkie ulepszenie – o około 30% mniejsze niż w przypadku galerii WebP. Dlatego WebP samo w sobie nie wystarczy, aby rozwiązać problem z wysokim DPI.

Progresywne formaty obrazów

Formaty obrazów progresywnych, takie jak JPEG 2000, JPEG progresywny, PNG progresywny i GIF, mają (co jest nieco dyskusyjne) tę zaletę, że obraz pojawia się na ekranie przed jego pełnym załadowaniem. Mogą one generować pewien nadmiar rozmiaru, chociaż istnieją sprzeczne dowody na ten temat. Jeff Atwood stwierdził, że tryb progresywny „zwiększa rozmiar obrazów PNG o około 20%, a obrazów JPEG i GIF o około 10%”. Jednak Stojan Stefanov stwierdził, że w przypadku dużych plików tryb progresywny jest wydajniejszy (w większości przypadków).

Na pierwszy rzut oka obrazy progresywne wydają się bardzo obiecujące w kontekście wyświetlania obrazów o najwyższej jakości w jak najkrótszym czasie. Oznacza to, że przeglądarka może przerwać pobieranie i dekodowanie obrazu, gdy tylko stwierdzi, że dodatkowe dane nie poprawią jakości obrazu (czyli wszystkie ulepszenia jakości są poniżej piksela).

Połączenia są łatwe do zakończenia, ale ich ponowne uruchomienie jest często kosztowne. W przypadku witryny z dużą liczbą obrazów najskuteczniejszym podejściem jest utrzymywanie jednego połączenia HTTP, aby używać go tak długo, jak to możliwe. Jeśli połączenie zostanie przerwane przedwcześnie, ponieważ obraz został pobrany w wystarczającym stopniu, przeglądarka musi utworzyć nowe połączenie, co może być bardzo wolne w środowiskach o niskiej latencji.

Jednym ze sposobów obejścia tego problemu jest użycie żądania zakresu HTTP, które pozwala przeglądarkom określić zakres bajtów do pobrania. Inteligentna przeglądarka może wysłać żądanie HEAD, aby pobrać nagłówek, przetworzyć go, zdecydować, ile miejsca na obraz jest faktycznie potrzebne, a następnie pobrać obraz. Niestety zakres HTTP jest słabo obsługiwany na serwerach WWW, co powoduje, że to podejście jest niepraktyczne.

Oczywistym ograniczeniem tego podejścia jest to, że nie można wybrać obrazu do załadowania, tylko różne poziomy wierności tego samego obrazu. W rezultacie nie dotyczy to przypadku użycia „kierowanie artysty”.

Używanie JavaScriptu do określania, który obraz ma być wczytany

Pierwszym i najbardziej oczywistym sposobem na określenie, który obraz ma być wczytany, jest użycie JavaScriptu po stronie klienta. Dzięki temu dowiesz się wszystkiego o swoim kliencie użytkownika i możesz podjąć właściwe działania. Możesz określić współczynnik pikseli urządzenia za pomocą funkcji window.devicePixelRatio, uzyskać szerokość i wysokość ekranu, a nawet przeprowadzić skanowanie sieci za pomocą navigator.connection lub wysyłając fałszywe żądanie, tak jak to robi biblioteka foresight.js. Gdy już zbierzesz wszystkie te informacje, możesz zdecydować, który obraz ma się wczytać.

Istnieje około miliona bibliotek JavaScript, które działają w podobny sposób, ale żadna z nich nie wyróżnia się szczególnie.

Jednym z większych minusów tego podejścia jest to, że korzystanie z JavaScriptu oznacza opóźnienie wczytywania obrazu do czasu zakończenia działania parsowania w przyszłości. Oznacza to, że pobieranie obrazów rozpocznie się dopiero po wywołaniu zdarzenia pageload. Więcej informacji na ten temat znajdziesz w artykule Jasona Grigsby'ego.

Wybór obrazu do załadowania na serwerze

Możesz odroczyć decyzję do strony serwera, pisząc niestandardowe przetwarzanie żądań dla każdego obrazu, który serwujesz. Taki handler sprawdza obsługę Retina na podstawie informacji User-Agent (jedynych informacji przekazywanych na serwer). Następnie, w zależności od tego, czy logika po stronie serwera chce wyświetlić zasoby HiDPI, wczytujesz odpowiedni zasób (nazwany zgodnie z jakiś znaną konwencją).

Niestety nagłówek User-Agent nie zawsze zawiera wystarczającą ilość informacji, aby określić, czy urządzenie powinno otrzymać obrazy o wysokiej czy niskiej jakości. Nie trzeba chyba dodawać, że wszystko, co jest związane z User-Agent, jest nielegalne i w miarę możliwości należy tego unikać.

Używanie zapytań mediów w kodzie CSS

Zapytania o media w CSS są deklaratywnymi zapytaniami, które pozwalają określić Twoje intencje i pozwolić przeglądarce na wykonanie odpowiednich działań w Twoim imieniu. Oprócz najczęstszego zastosowania zapytań o multimedia, czyli dopasowania do rozmiaru urządzenia, możesz też stosować dopasowanie do devicePixelRatio. Powiązane zapytanie o multimedia to device-pixel-ratio. Jak można się spodziewać, ma ono powiązane warianty minimalny i maksymalny. Jeśli chcesz wczytać obrazy o wysokiej rozdzielczości, a współczynnik pikseli urządzenia przekracza określony próg, wykonaj te czynności:

#my-image { background: (low.png); }

@media only screen and (min-device-pixel-ratio: 1.5) {
  #my-image { background: (high.png); }
}

Sprawa komplikuje się, gdy mieszamy ze sobą wszystkie prefiksy dostawców, zwłaszcza ze względu na szaleńcze różnice w umieszczaniu prefiksów „min” i „max”:

@media only screen and (min--moz-device-pixel-ratio: 1.5),
    (-o-min-device-pixel-ratio: 3/2),
    (-webkit-min-device-pixel-ratio: 1.5),
    (min-device-pixel-ratio: 1.5) {

  #my-image {
    background:url(high.png);
  }
}

Dzięki temu podejściu odzyskasz korzyści płynące z analizy wyprzedzającej, które zostały utracone w rozwiązaniu JS. Zyskasz też elastyczność w wybieraniu punktów przerwania w przypadku wersji responsywnych (np. możesz mieć obrazy o niskim, średnim i wysokim DPI), których nie można było wybrać w przypadku podejścia po stronie serwera.

Niestety, jest ona nadal nieco niepraktyczna i prowadzi do dziwnie wyglądającego kodu CSS (lub wymaga wstępnej obróbki). Ponadto to podejście jest ograniczone do właściwości CSS, więc nie ma możliwości ustawienia <img src>, a wszystkie obrazy muszą być elementami z tłem. Jeśli polegasz tylko na współczynniku proporcji pikseli urządzenia, może się zdarzyć, że Twój smartfon o wysokiej rozdzielczości pobiera zasób graficzny o rozmiarze 2 x, gdy masz połączenie EDGE. Nie jest to najlepsza opcja dla użytkowników.

Korzystanie z nowych funkcji przeglądarki

Ostatnio dużo dyskutowano na temat obsługi platformy internetowej w kontekście problemu z obrazami o wysokiej rozdzielczości. Apple niedawno wprowadziło na rynek funkcję image-set() do WebKit. W rezultacie zarówno Safari, jak i Chrome obsługują tę funkcję. Ponieważ jest to funkcja CSS, image-set()nie rozwiąże problemu w przypadku tagów <img>. Oto @srcset, który rozwiązuje ten problem, ale (w momencie pisania tego artykułu) nie ma jeszcze implementacji referencyjnych. W następnej sekcji omawiamy szczegółowo image-setsrcset.

Funkcje przeglądarki obsługujące wysoką rozdzielczość DPI

Ostateczna decyzja o tym, które podejście zastosować, zależy od Twoich konkretnych wymagań. Pamiętaj, że wszystkie wymienione powyżej podejścia mają wady. Jednak w przyszłości, gdy image-set i srcset będą powszechnie obsługiwane, będą one odpowiednimi rozwiązaniami tego problemu. Na razie porozmawiajmy o kilku sprawdzonych metodach, które mogą nas zbliżyć do tej idealnej przyszłości.

Na początek, czym się różnią? image-set() to funkcja CSS, która może być używana jako wartość właściwości CSS background. srcset to atrybut specyficzny dla elementów <img> o podobnej składni. Oba te tagi umożliwiają określenie deklaracji obrazu, ale atrybut srcset pozwala też skonfigurować, który obraz ma być wczytany na podstawie rozmiaru okna przeglądarki.

Sprawdzone metody dotyczące zestawu obrazów

Funkcja CSS image-set() jest dostępna z prefiksem -webkit-image-set(). Składnia jest dość prosta i polega na podaniu co najmniej 1 deklaracji obrazu oddzielonej przecinkami, która składa się z ciągu znaków adresu URL lub funkcji url(), po której następuje powiązana rozdzielczość. Na przykład:

background-image:  -webkit-image-set(
  url(icon1x.jpg) 1x,
  url(icon2x.jpg) 2x
);

Oznacza to, że przeglądarka ma do wyboru 2 obrazy. Jedna z nich jest zoptymalizowana pod kątem wyświetlaczy 1x, a druga – 2x. Przeglądarka wybiera, którą stronę ma wczytać, na podstawie różnych czynników, które mogą obejmować nawet prędkość sieci, jeśli jest wystarczająco inteligentna (o ile mi wiadomo, nie jest to obecnie wdrażane).

Oprócz wczytania prawidłowego obrazu przeglądarka odpowiednio go przeskaluje. Innymi słowy, przeglądarka zakłada, że obrazy w standardowym rozmiarze są dwa razy większe niż w podwójnym, więc zmniejszy obraz w podwójnym rozmiarze 2 razy, aby miał taki sam rozmiar na stronie.

Zamiast wartości 1x, 1, 5x lub Nx możesz też określić gęstość pikseli urządzenia w dpi.

To działa dobrze, z wyjątkiem przeglądarek, które nie obsługują właściwości image-set, w których przypadku obraz wcale się nie wyświetla. Jest to wyraźnie zła sytuacja, dlatego musisz użyć rozwiązania zastępczego (lub serii rozwiązań zastępczych), aby rozwiązać ten problem:

background-image: url(icon1x.jpg);
background-image: -webkit-image-set(
  url(icon1x.jpg) 1x,
  url(icon2x.jpg) 2x
);
/* This will be useful if image-set gets into the platform, unprefixed.
    Also include other prefixed versions of this */
background-image: image-set(
  url(icon1x.jpg) 1x,
  url(icon2x.jpg) 2x
);

W przeglądarkach obsługujących image-set wczytuje się odpowiedni zasób, a w przeciwnym razie wczytuje się zasób 1x. Oczywiste zastrzeżenie jest takie, że chociaż wsparcie przeglądarki image-set() jest niskie, większość agentów użytkownika otrzyma zasób 1x.

W tym pokazie do wczytania prawidłowego obrazu używana jest funkcja image-set(), która w przypadku braku obsługi tej funkcji CSS sięga po zasób 1x.

Zastanawiasz się może, dlaczego nie użyć polyfill (czyli nie stworzyć shimu JavaScriptu) dla image-set()? Okazało się, że implementacja wydajnych polyfilli dla funkcji CSS jest dość trudna. (szczegóły znajdziesz w tym dyskusyjnym artykule).

Srcset obrazu

Oto przykład atrybutu srcset:

<img alt="my awesome image"
  src="banner.jpeg"
  srcset="banner-HD.jpeg 2x, banner-phone.jpeg 640w, banner-phone-HD.jpeg 640w 2x">

Jak widać, oprócz deklaracji x, które udostępnia image-set, element srcset przyjmuje też wartości w i h, które odpowiadają rozmiarowi widoku, aby wyświetlić najbardziej odpowiednią wersję. W przypadku powyższych ustawień banner-phone.jpeg będzie wyświetlany na urządzeniach z szerokością widoku mniejszą niż 640 pikseli, banner-phone-HD.jpeg na urządzeniach z małym ekranem i wysoką rozdzielczością, banner-HD.jpeg na urządzeniach z wysoką rozdzielczością i ekranem większym niż 640 pikseli oraz banner.jpeg na wszystkich pozostałych urządzeniach.

Używanie zestawu obrazów w przypadku elementów graficznych

Większość przeglądarek nie obsługuje atrybutu srcset w elementach img, dlatego możesz chcieć zastąpić elementy img elementami <div> z tłem i wykorzystać podejście z zestawem obrazów. To zadziała, ale z pewnymi zastrzeżeniami. Wadą jest to, że tag <img> ma długotrwałą wartość semantyczną. W praktyce jest to ważne głównie ze względu na roboty internetowe i ułatwienia dostępu.

Jeśli ostatecznie użyjesz -webkit-image-set, możesz chcieć użyć właściwości CSS background. Wadą tego podejścia jest to, że musisz określić rozmiar obrazu, który jest nieznany, jeśli używasz obrazu niestandardowego. Zamiast tego możesz użyć właściwości CSS content w ten sposób:

<div id="my-content-image"
  style="content: -webkit-image-set(
    url(icon1x.jpg) 1x,
    url(icon2x.jpg) 2x);">
</div>

Spowoduje to automatyczne dostosowanie obrazu na podstawie atrybutu devicePixelRatio. W tym przykładzie zastosowano opisaną wyżej technikę, dodając dodatkowy wariant url() dla przeglądarek, które nie obsługują image-set.

wypełnianie zduplikowanych wartości atrybutu srcset,

Przydatną funkcją srcset jest to, że zawiera naturalne wartości domyślne. Jeśli atrybut srcset nie jest zaimplementowany, wszystkie przeglądarki wiedzą, że należy przetworzyć atrybut src. Ponieważ jest to tylko atrybut HTML, można tworzyć polyfille za pomocą JavaScriptu.

Ta funkcja polyfill jest dostarczana z testami jednostkowymi, aby zapewnić jak największe dopasowanie do specyfikacji. Oprócz tego wdrożone są mechanizmy kontroli, które uniemożliwiają polyfillowi wykonanie jakiegokolwiek kodu, jeśli srcset jest implementowany natywnie.

Oto demo funkcji polyfill.

Podsumowanie

Nie ma magicznego rozwiązania problemu obrazów o wysokiej rozdzielczości.

Najprostszym rozwiązaniem jest całkowite unikanie obrazów i zamiast tego używanie formatu SVG i CSS. Nie zawsze jest to jednak możliwe, zwłaszcza jeśli masz w witrynie obrazy wysokiej jakości.

Podejścia oparte na JS, CSS i używaniu serwera mają swoje zalety i wady. Najbardziej obiecujące jest jednak korzystanie z nowych funkcji przeglądarki. Chociaż obsługa przeglądarek w przypadku image-setsrcset jest nadal niepełna, obecnie można korzystać z rozwiązań alternatywnych.

Podsumowując, moje zalecenia są następujące: