Użyj picture, aby przełączać się między kwadratowymi i szerokimi plikami obrazów przy określonym progu szerokości widoku. Podaj wymiary każdego źródła i pozwól CSS proporcjonalnie skalować wybrany obraz. W tym poradniku tworzysz i testujesz lokalny przykład na Macu.

Jak picture przełącza się między różnymi proporcjami obrazu?

Umieść element source z warunkiem media przed zapasowym elementem img wewnątrz picture. Przeglądarka wybiera pierwsze kwalifikujące się źródło, którego warunek jest spełniony, a następnie wybiera obraz z jego srcset. Nazywa się to ukierunkowaniem artystycznym: dostarczaniem różnych kompozycji dla różnych układów. Standard HTML wyraźnie obsługuje takie podejście. Standard HTML: obrazy

Współdziałają tu trzy elementy: źródło wybiera zasób, atrybuty wymiarów opisują jego proporcje, a CSS kontroluje rozmiar wyświetlania. Atrybuty width i height wybranego źródła mogą określać proporcje używane przez zawarty w nim obraz. Sam element picture nie wyświetla obrazu — robi to jego img. Standard HTML: zawartość osadzona

Wybierz mechanizm odpowiedni do oczekiwanego rezultatu:

Wymaganie Odpowiedni mechanizm
Zmiana kompozycji lub proporcji obrazu przy określonym progu szerokości picture z elementem source używającym media
Różne rozdzielczości tej samej kompozycji srcset, z sizes w przypadku użycia deskryptorów szerokości
Jeden plik przycinany do stałej ramki Dopasowanie rozmiaru w CSS i object-fit: cover

Mechanizmy te służą do podejmowania różnych decyzji. Ukierunkowanie artystyczne określa, która kompozycja zostanie wyświetlona. Wybór rozdzielczości pozwala przeglądarce wybrać odpowiedni wariant w ramach danej kompozycji. Dopasowanie w CSS określa, jak wybrany zasób wypełnia ramkę. MDN opisuje te zastosowania picture oraz jego związek z srcset i właściwościami dopasowania. MDN: element picture

Utwórz kompletny lokalny przykład na Macu

Przykład wykorzystuje dwa oryginalne zasoby SVG: jeden zawiera pomarańczowe koło i turkusowy zaokrąglony prostokąt. W wersji kwadratowej kształty są ułożone jeden nad drugim, a w szerokiej obok siebie. Wszystkie pliki znajdują się w jednym folderze; przełączanie nie wymaga zewnętrznych zasobów ani JavaScriptu.

Prosta umowa dotycząca zasobów wygląda tak: przy szerokości widoku poniżej 700px używany jest zasób kwadratowy o wymiarach 600 × 600. Przy 700px i więcej — szeroki zasób o wymiarach 1200 × 600. Wyświetlany obraz wypełnia obszar treści z marginesem 16px po każdej stronie, a jego maksymalna szerokość wynosi 960px. Te wymiary i próg szerokości są przykładowymi decyzjami projektowymi.

Zapisz dwa zasoby z kształtami

Utwórz folder o nazwie picture-demo. W edytorze kodu obsługującym zwykły tekst utwórz w nim dwa poniższe pliki, zachowując dokładne nazwy i rozszerzenia. Każdy blok kodu zawiera kompletną zawartość pliku; skopiuj ją bez znaczników bloku Markdown.

Zapisz jako shapes-square.svg:

<svg xmlns="http://www.w3.org/2000/svg" width="600" height="600" viewBox="0 0 600 600">
  <rect width="600" height="600" fill="#fff5df"/>
  <circle cx="300" cy="180" r="100" fill="#de7b35"/>
  <rect x="150" y="340" width="300" height="160" rx="40" fill="#247d83"/>
</svg>

Zapisz jako shapes-wide.svg:

<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="600" viewBox="0 0 1200 600">
  <rect width="1200" height="600" fill="#fff5df"/>
  <circle cx="320" cy="300" r="180" fill="#de7b35"/>
  <rect x="650" y="150" width="400" height="300" rx="60" fill="#247d83"/>
</svg>

Zapisz stronę HTML

Utwórz index.html w tym samym folderze. Jeśli używasz TextEdit, wybierz File > New, a następnie Format > Make Plain Text przed wklejeniem kodu. Zapisz plik z rozszerzeniem .html i w razie wyświetlenia monitu wybierz Use .html. Apple opisuje ten sposób tworzenia plików HTML. Apple: Praca z dokumentami HTML w TextEdit na Macu

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Shape study</title>
  <style>
    body { margin: 0; font-family: system-ui, sans-serif; }
    main { width: calc(100% - 32px); max-width: 960px; margin: 24px auto; }
    picture { display: block; }
    .study-image { display: block; width: 100%; height: auto; }
  </style>
</head>
<body>
  <main>
    <h1>Shape study</h1>
    <picture>
      <source media="(min-width: 700px)" srcset="shapes-wide.svg"
              width="1200" height="600">
      <img class="study-image" src="shapes-square.svg"
           width="600" height="600"
           alt="An orange circle and a teal rounded rectangle on cream.">
    </picture>
    <p>Resize the viewport to compare the two arrangements.</p>
  </main>
</body>
</html>

Otwórz index.html w Safari. Przy odpowiednio szerokim widoku kształty powinny być ułożone obok siebie. Przy węższym widoku powinny znaleźć się jeden nad drugim. Trzymaj wszystkie trzy pliki razem: względne adresy zasobów są rozwiązywane względem lokalizacji pliku HTML.

Szerokie źródło używa srcset, mimo że zawiera tylko jeden URL. Wewnątrz picture element source wymaga srcset; jego atrybut src jest niedozwolony. Atrybuty wymiarów są liczbami całkowitymi bez jednostek, więc użyj width="1200", a nie width="1200px". MDN: element source

Dlaczego podawać wymiary zarówno źródła, jak i obrazu zapasowego?

Wymiary 600 × 600 obrazu zapasowego opisują zasób kwadratowy. Wymiary 1200 × 600 szerokiego źródła opisują zasób szeroki. Podanie obu par pozwala przeglądarce obsługującej tę funkcję ustalić proporcje wybranego obrazu przed jego pobraniem. Użycie wymiarów kwadratowych dla szerokiego źródła podałoby błędne początkowe proporcje. Standard HTML: atrybuty wymiarów źródła

CSS ustawia następnie szerokość obrazu na szerokość dostępnego obszaru treści, pozostawiając automatyczną wysokość. Dzięki temu proporcje obrazu określają jego wysokość. Projekt specyfikacji CSS dotyczący rozmiarów opisuje, jak preferowane proporcje wpływają na automatyczne ustalanie rozmiaru; jawne ustalenie obu wymiarów odbiera tę elastyczność. Moduł CSS Box Sizing, poziom 4

W tym przykładzie układ można sprawdzić za pomocą prostego obliczenia:

szerokość obrazu = min(szerokość widoku - 32, 960)
wysokość obrazu kwadratowego = szerokość obrazu
wysokość obrazu szerokiego = szerokość obrazu / 2
Szerokość widoku w pikselach CSS Wybrany zasób Obliczony rozmiar obrazu
500 shapes-square.svg 468 × 468
699 shapes-square.svg 667 × 667
700 shapes-wide.svg 668 × 334
1000 shapes-wide.svg 960 × 480

Są to wartości obliczone na podstawie podanego CSS, przy założeniu, że szerokość paska przewijania nie zmniejsza dostępnego obszaru treści. Składnię SVG, nazwy zasobów, zadeklarowane wymiary i obliczenia sprawdzono programowo; podczas przygotowywania przykładu nie renderowano go w przeglądarce.

Zwróć uwagę na dużą zmianę wysokości między 699px a 700px. Wynika ona bezpośrednio z przejścia z kompozycji kwadratowej na szeroką. Taka zmiana jest oczekiwana podczas zmiany rozmiaru widoku. Jeśli po załadowaniu pojawi się kolejny skok przy niezmienionej szerokości widoku, sprawdź zadeklarowane wymiary i ewentualny nadpisujący je CSS.

Dokładne testowanie progu szerokości w Safari

Tryb Responsive Design w Safari pozwala zmieniać rozmiar widoku strony niezależnie od rozmiaru okna na pulpicie. W ustawieniach Advanced Safari włącz Show features for web developers. Otwórz przykład, a następnie wybierz Develop > Enter Responsive Design Mode lub naciśnij Control-Command-R. WebKit opisuje to ustawienie, skrót i podgląd o regulowanym rozmiarze. WebKit: uproszczony tryb Responsive Design

Najpierw przetestuj 699px i 700px, a potem wygodnie wąski i szeroki widok. Sprawdź, czy kompozycja zmienia się na zamierzonej granicy, pomarańczowy kształt pozostaje kołem, a akapit pod obrazem podąża za zmianą jego wysokości. Odśwież stronę po obu stronach progu, aby sprawdzić zarówno początkowy układ, jak i jego zmianę podczas zmiany rozmiaru.

Aby bezpośrednio sprawdzić, który plik wybrało Safari, uruchom opcjonalny fragment diagnostyczny w konsoli Web Inspector podczas wyświetlania przykładu:

const studyImage = document.querySelector('.study-image');
if (!studyImage) {
  throw new Error('Open the Shape study example before running this snippet.');
}
const studyBox = studyImage.getBoundingClientRect();
console.table({
  selectedURL: studyImage.currentSrc,
  displayedWidth: studyBox.width,
  displayedHeight: studyBox.height
});

Uruchom fragment ponownie po przekroczeniu progu. Wybrany URL powinien kończyć się odpowiednią nazwą pliku kwadratowego lub szerokiego. Właściwość currentSrc zwraca URL wybrany przez przeglądarkę; sama jej wartość nie dowodzi, że zasób został poprawnie załadowany. MDN: właściwość currentSrc obiektu HTMLImageElement

Co sprawdzić, gdy przełączanie nie działa prawidłowo?

Sprawdzaj po kolei wybór, wymiary zasobu i sposób wyświetlania. Dzięki temu problemu z rozmiarem w CSS nie pomylisz z problemem wyboru zasobu.

  1. Przy szerokim widoku nadal wybierany jest plik kwadratowy. Sprawdź, czy szerokość widoku osiąga 700px, czy source występuje przed img oraz czy źródło używa srcset. Jeśli jest wiele źródeł, sprawdź ich kolejność: pierwszeństwo może mieć wcześniejsze źródło, którego warunek jest spełniony. Standard HTML: wybór według ukierunkowania artystycznego
  2. Zasób się nie pojawia. Porównaj nazwy plików w znacznikach z plikami w folderze, uwzględniając rozszerzenia. W tym przykładzie oba pliki SVG muszą znajdować się obok index.html.
  3. Wyświetlany jest właściwy zasób, ale ma nieprawidłowy kształt. Sprawdź reguły CSS zastosowane do właściwego img, zwłaszcza te, które przypisują stałą wysokość. Aby zachować proporcje, przywróć height: auto.
  4. Po załadowaniu obraz przeskakuje. Porównaj każdą zadeklarowaną parę wymiarów z rzeczywistymi proporcjami zasobu. Sprawdź też, czy jawna właściwość CSS aspect-ratio nie nadpisuje zamierzonych proporcji.

Jeśli projekt wymaga stałej ramki, świadomie wybierz sposób dopasowania. object-fit: contain zachowuje cały zasób i może pozostawić puste miejsce; cover wypełnia ramkę i może przyciąć zawartość; fill może ją rozciągnąć. Stosuj właściwości dopasowania do img. Podany przykład nie wymaga stałej ramki, ponieważ układ dopasowuje się do proporcji wybranego zasobu. MDN: object-fit

Jakie są ograniczenia obsługi przez przeglądarki?

Obsługa picture i obsługa wymiarów właściwych dla poszczególnych źródeł to osobne kwestie. Zestawienie zgodności w standardzie HTML wymienia picture we współczesnych silnikach przeglądarek. MDN oznacza właściwość źródła width, która odzwierciedla jego atrybut wymiaru, jako dostępną we wszystkich przeglądarkach od grudnia 2022 r. Nie należy zakładać, że starsze przeglądarki poprawnie zarezerwują miejsce na wymiary właściwe dla źródła. Standard HTML: element picture, MDN: właściwość width obiektu HTMLSourceElement

Gdy żadne źródło nie pasuje albo przeglądarka nie obsługuje picture, obraz dostarcza zapasowy img. W tym przykładzie jest to kompozycja kwadratowa. Przeglądarka, która przełącza zasoby, ale nie obsługuje wymiarów źródła, może ustalić ostateczne proporcje szerokiego obrazu dopiero po jego załadowaniu. MDN: element picture

Jeśli docelowa przeglądarka obsługuje CSS aspect-ratio, ale wymaga jawnej reguły rozmiaru, dodaj poniższy fragment CSS na końcu istniejącego arkusza stylów. Odzwierciedla on próg szerokości HTML i podaje tymczasowe proporcje, pozwalając, by po załadowaniu zaczęły obowiązywać naturalne proporcje obrazu:

.study-image {
  aspect-ratio: auto 1 / 1;
}

@media (min-width: 700px) {
  .study-image {
    aspect-ratio: auto 2 / 1;
  }
}

MDN opisuje takie połączenie auto z proporcjami i podaje, że CSS aspect-ratio jest obsługiwany we wszystkich przeglądarkach od września 2021 r. Fragment ma więc własne ograniczenie dotyczące obsługi. Zachowaj zgodność jego progu szerokości z warunkiem źródła i przetestuj wersje przeglądarek, które musisz uwzględnić. MDN: aspect-ratio

Gdy przykład działa poprawnie, zastąp przykładowe pliki własnymi kompozycjami i odpowiednio zaktualizuj ich wymiary. Zachowaj zgodność warunku źródła, proporcji zasobów i reguł CSS określających rozmiar, a następnie ponownie sprawdź szerokości bezpośrednio poniżej i powyżej progu.

Źródła