x
 
Юрий Мазурский
30 января 2020
Советы почтой каждую неделю
Пожалуйста, получите наше письмо, чтобы подтвердить свой адрес:
Вы подписаны на «Советы за неделю»:

Адаптивные изображения, атрибуты srcset и sizes


В одном из преды­ду­щих сове­тов мы разо­брали, как управ­лять адап­тив­но­стью стра­ницы в целом.

С адап­та­цией изоб­ра­же­ний под кон­крет­ный раз­мер экрана воз­ни­кает куча про­блем, ведь диа­па­зон раз­ме­ров экра­нов устройств очень боль­шой. Изоб­ра­же­ние, пред­на­зна­чен­ное для мони­тора ста­ци­о­нар­ного ком­пью­тера с аль­бом­ной ори­ен­та­цией, может совсем не под­хо­дить для вер­ти­каль­ного экрана мобиль­ного устрой­ства. Сами экраны могут быть с рети­ной или без. На мобиль­ных устрой­ствах нет смысла загру­жать огром­ные изоб­ра­же­ния, пред­на­зна­чен­ные для боль­шого мони­тора, потому что физи­че­ский раз­мер экрана теле­фона маленький.

Объём тра­фика и ско­рость загрузки стра­ницы важны для поль­зо­ва­теля, поэтому было бы неплохо уметь под­би­рать опти­маль­ное изоб­ра­же­ние для его устройства.

В ХТМЛ есть инстру­менты для выбора изоб­ра­же­ния в зави­си­мо­сти от пара­мет­ров экрана, на кото­ром открыта страница.

Srcset

Один из самых про­стых спо­со­бов авто­ма­ти­зи­ро­вать под­ста­новку наи­бо­лее под­хо­дя­щего изоб­ра­же­ния — исполь­зо­вать атри­бут srcset у эле­мента img.

Через запя­тую ука­зы­ваем пути ко всем вари­а­циям изоб­ра­же­ния и раз­меры в пикселях:

Обратите внимание на специальную единицу измерения w в размере изображения. Это число указывает на количество «настоящих» пикселей
<img srcset="/img/3000x1500.png 3000w,
             /img/2000x1000.png 2000w,
             /img/1000x500.png 1000w,
             /img/600x300.png 600w,
             /img/300x150.png 300w"
     src="/img/2000x1000.png"
     alt="При­мер 1"
/>
Обратите внимание на специальную единицу измерения w в размере изображения. Это число указывает на количество «настоящих» пикселей

Бра­у­зер сам под­ста­вит наи­бо­лее близ­кое к теку­щей ширине экрана изоб­ра­же­ние. Осталь­ные изоб­ра­же­ния при этом не будут загру­жены. Атри­бут src оста­вим на слу­чай, если srcset не под­дер­жи­ва­ется браузером.

Пример 1
Попро­буйте поме­нять ширину окна. В зави­си­мо­сти от бра­у­зера изоб­ра­же­ние может под­гру­жаться не на лету, а только после пере­за­грузки стра­ницы

Есть аль­тер­на­тив­ный вари­ант выби­рать изоб­ра­же­ние — ука­зы­вать коэф­фи­ци­енты, а не ширину. Изоб­ра­же­ние будет выбрано исходя из плот­но­сти точек экрана:

<img srcset="/img/3000x1500.png 2x,
             /img/2000x1000.png 1.5x,
             /img/1000x500.png"
     src="/img/2000x1000.png"
     alt="При­мер 1"
/>

Но что если наше изоб­ра­же­ние зани­мает не всю ширину экрана, а, напри­мер, поло­вину? С при­ме­ром выше воз­ник­нет про­блема — на ширине окна 1440 пик­се­лей (2880 без ретины) мы пока­жем изоб­ра­же­ние с раз­ме­рами 3000×1500 пик­се­лей, хотя ширина обла­сти, выде­лен­ной под изоб­ра­же­ние, будет равна 634 пик­се­лям (1268 без ретины):

3000 / 1268 = 2,36

Мы пока­жем изоб­ра­же­ние, кото­рое в 2,36 раза больше, чем нужно, при­том что у нас есть вари­а­ции, одно­значно более под­хо­дя­щие для такого слу­чая. Рас­хож­де­ния будут и при дру­гих раз­ме­рах окна.

<div style="width: 50%;">
  <img srcset="/img/3000x1500.png 3000w,
               /img/2000x1000.png 2000w,
               /img/1000x500.png 1000w,
               /img/600x300.png 600w,
               /img/300x150.png 300w"
       src="/img/2000x1000.png"
       alt="При­мер 2"
  />
</div>
Пример 2
Изоб­ра­же­ние зани­мает поло­вину ширины стра­ницы, но выби­ра­ется тот же раз­мер, что и для боль­шого изоб­ра­же­ния на всю ширину из при­мера выше

С реше­нием этой про­блемы нам может помочь ещё один атри­бут эле­мента img — sizes.

Sizes

С помо­щью sizes можно зада­вать кри­те­рии выбора того или иного изоб­ра­же­ния через меди­аза­просы. Каж­дому меди­аза­просу соот­вет­ствует целе­вой раз­мер, кото­рый слу­жит для бра­у­зера ори­ен­ти­ром при выборе кон­крет­ного изоб­ра­же­ния из srcset. Выпол­ня­ется пер­вое под­хо­дя­щее усло­вие, осталь­ные игно­ри­ру­ются, поэтому поря­док усло­вий важен:

<img srcset="/img/3000x1500.png 3000w,
             /img/2000x1000.png 2000w,
             /img/1000x500.png 1000w,
             /img/600x300.png 600w,
             /img/300x150.png 300w"
     sizes="(max-width: 350px) 150px, 
            (max-width: 600px) 300px,
            (max-width: 1400px) 500px,
            1000px"
     src="/img/2000x1000.png"
     alt="При­мер 3"
/>

Целе­вые раз­меры изоб­ра­же­ний могут быть ука­заны в любых еди­ни­цах изме­ре­ния, кроме про­цен­тов. Инструк­ции рас­шиф­ро­вы­ва­ются так:

Инструкция

(max-width: 350px) 150px

Что означает

При ширине ≤ 350 пик­се­лей под­ста­вить изоб­ра­же­ние, бли­жай­шее к 150 пикселям

Инструкция

(max-width: 600px) 300px

Что означает

При ширине ≤ 600 пик­се­лей под­ста­вить изоб­ра­же­ние, бли­жай­шее к 300 пикселям

Инструкция

(max-width: 1400px) 500px

Что означает

При ширине ≤ 1400 пик­се­лей под­ста­вить изоб­ра­же­ние, бли­жай­шее к 500 пикселям

Инструкция

1000px

Что означает

Во всех осталь­ных слу­чаях под­ста­вить изоб­ра­же­ние, бли­жай­шее к 1000 пикселей

Без sizes
Пример 2
Раз­ре­ше­ние изоб­ра­же­ния слиш­ком боль­шое
С sizes
Пример 3
Раз­ре­ше­ние изоб­ра­же­ния выби­ра­ется более опти­мально

Нужно пом­нить об экра­нах с рети­ной. Целе­вые раз­меры изоб­ра­же­ния при­во­дятся к ЦСС‑пик­се­лям — это озна­чает, что на экране с рети­ной бра­у­зер поста­ра­ется под­ста­вить изоб­ра­же­ние с удво­ен­ным разрешением.

В сле­ду­ю­щем совете мы раз­бе­рём ещё один, более про­дви­ну­тый, спо­соб управ­ле­ния изоб­ра­же­ни­ями на раз­лич­ных раз­ме­рах экранов.

Что ещё почитать

P. S. Это был совет о веб‑разработке. Хотите знать всё о коде, тестах, фронтенд‑разработке, цеэсэсе, яваскрипте, рельсах и джейде? Присылайте вопросы.

Поделиться
Отправить

Комментарии

Василий Мишустин
30 января 2020

> Но что если наше изображение занимает не всю ширину экрана, а, например, половину?

Если известно, что оно занимает половину экрана, то можем вместо <img srcset="/img/3000x1500.png 3000w написать <img srcset="/img/3000x1500.png 6000w и т. д. Или мы так не можем?

Или мы так можем, но только в случае, если точно знаем, что не будет варианта, когда от размера экрана меняется раскладка и относительные размеры изображений на экране?

Вариант, когда от размера экрана меняется раскладка и относительные размеры изображений на экране, понятен. Тогда действительно стоит использовать sizes="(max‑width: 350px) 150px и т. д.

Юрий Мазурский
30 января 2020

Василий!

Написать 6000w будет некорректно. Через этот параметр мы сообщаем браузеру, какой ширины изображение, чтобы он не скачивал его и не проверял сам. Возможно такой вариант сработает, но больше похоже на хак


Цель рубрики — обсуждение вопросов дизайна всех видов, текста в дизайне и взаимоотношений дизайнеров с клиентами.

Мы публикуем комментарии, которые добавляют к уже сказанному новые мысли и хорошие примеры. Мы ожидаем, что такие комментарии составят около 20% от общего числа.

Решение о публикации принимается один раз; мы не имеем возможности комментировать или пересматривать свое решение, хотя оно может быть ошибочно. Уже опубликованные комментарии могут быть удалены через некоторое время, если без них обсуждение не становится менее ценным или интересным.

Вот такой веб 2.0.

Автотесты «на пальцах» 1 Как написать аккуратный код? Часть первая: зацепление 2 Автотесты «на пальцах» 2 Почему лучше разделить фронтенд и бэкенд? 7




Недавно всплыло

Банальное перечисление языков через запятую не подходит, работодателя интересует уровень владения каждым из языков. 12 7 Нужно ли писать века римскими цифрами? 3 4