Retina-дисплей (ретина) - маркетинговый термин компании Apple, описывающий устройства с экранами повышенной пиксельной плотности. В тот же размер экрана вмещается больше физических пикселей, за счёт того что их размер меньше. Это повышает качество и чёткость изображения, делает цвета более насыщенными и живыми.
Физические пиксели (device pixel или hardware pixel) - самые маленькие элементы любого экрана (его матрицы), каждый из которых имеет свой цвет и яркость.
Разрешение экрана (screen resolution) - это количество физических
пикселей на экране устройства. Например, разрешение 1920x1080 означает
что экран 1920 физических пикселей по ширине и 1080 по высоте. Если
умножить получится общее количество пикселей на таком экране - 2073600.
Плотность экрана (pixel density) - это количество физических
пикселей, которое помещается в один дюйм. Измеряется в ppi (pixels per
inch). Чем выше плотность, тем меньше размер пикселя и тем больше их на
экране.
CSS-пиксели (device-independent pixels) - абстрактная величина не зависящая от экрана устройства и используемая браузером для рассчёта размеров контента на странице.
На обычных экранах один CSS-пиксель соответствует одному физическому
пикселю устройства. При масштабировании и на экранах высокой пиксельной
плотности, в одном CSS-пикселе может помещаться больше одного
физического пикселя.
Например, есть блок размером 2x2 пикселя. Все размеры элементов, которые
указываются в CSS или HTML, это CSS-пиксели.
div {
width: 2px;
height: 2px;
}
На обычных экранах он будет занимать область 2x2 физических пикселя, а на Retina-экранах, например с плотностью 2, этот же блок получит 4x4 физических пикселя. То есть в два раза больше по горизонтали и вертикали. Таким образом, на Retina-экранах с плотностью пикселей в два раза выше стандартной, количество пикселей в 4 раза больше, чем на обычных.
Растровые пиксели (bitmap pixels) - самые маленькие части, составляющие растровое изображение (png, jpg, gif и т. д.). Каждый пиксель содержит информацию о своём цвете и расположении в системе координат изображения.
В коде размеры изображения задаются в CSS-пикселях. При отображении на обычном экране, один растровый пиксель соответствует одному CSS-пикселю. На Retina-экранах с плотностью 2, каждый растровый пиксель умножается в 4 раза, что приводит к потере качества изображения не подготовленного к ретине.
Именно поэтому растровые изображения для Retina-экранов должны иметь большее количество пикселей. Это гарантирует их чёткость при отображении в браузере.
Для Retina-экранов необходимы специально подготовленные ресурсы. Текст и
векторная графика (SVG) отображаются одинаково хорошо на любом экране,
так как их рендерит сам браузер по набору точек и соединяющих их кривых.
Ретинизация - это приём для подготовки растровой графики.
Для того чтобы подготовить растровую графику к ретине, небходимо
экспортировать из макета большее изображение. Например, чтобы показать
фотографию 200x300 CSS-пикселей на экране с плотностью 2, необходимо
подготовить её вариант в размере 400x600 растровых пикселей. Для экрана
с плотностью 3 это изображение должно быть 600x900 растровых пикселей.
info Для растровой веб-графики достаточно подготовить только 1x и 2x версии. Большинство людей с хорошим зрением не заметят разницу между 2x и 3x изображением, из-за физических ограничений человеческого глаза, но вес последнего будет значительно больше, что негативно скажется на скорости его загрузки.
Процесс подготовки состоит из экспорта изображений в N-раз больше размера оригинала и сохранения их с соответствующими префиксами @2x и @3x. Для оригинала префикс не нужен.
После чего достаточно задать нужный размер тегу <img /> в HTML или CSS коде.
В примере используется онлайн-сервис изображений. Загружается три картинки 320x240 (1x), 640x480 (2x) и 960x720 (3x) пикселей. Размер всех элементов <img /> одинаковый - 320x240 CSS-пикселей. Если перейти в пример с телефона или просто увеличить масштаб страницы с примером, будет заметно что первое изображения сильно размывается, второе остаётся вполне качественным, а третье всегда кристально чёткое.
info Это не значит что всегда нужно экспортировать и загружать самое большое изображение. На этом шаге мы рассмотрели проблему и научились делать ретинизацию растровой графики. Дальше мы научимся загружать различные изображения под каждую ширину или плотность экрана.
Представьте изображение 1200x600 пикселей. Оно отлично выглядит на
широком экране. А что будет, если мы откроем страницу на телефоне или
планшете? Ничего хорошего. Изображение будет оставаться шириной 1200
пикселей и появится горизонтальная полоса прокрутки, а на ретине оно
будет выглядеть размыто.
Отзывчивые изображения - это термин для описания набора приёмов
используемых в HTML и CSS, при помощи которых контентные и фоновые
изображения выглядят одинаково хорошо на устройствах с различными
размерами и плотностью экрана.
Самый простой способ реализовать отзывчивость, это использовать одно
изображение для всех устройств, задав ему определённый набор
CSS-свойств.
/* Свойства нужно применить ко всем изображениям,
поэтому используется селектор тега. */
img {
display: block;
max-width: 100%;
height: auto;
}
Так работает техника простого отзывчивого контентного изображения - одна картинка для всех устройств, которая подстраивается под текущую ширину своего родительского элемента.
Создадим контейнер для картинки div.thumb, зададим ему минимальную и максимальную ширину. Картинке дадим отзывчивые свойства. Теперь картинка будет всегда красиво заполнять «тумбу», изменяя свой размер в зависимости от ширины родителя.
Этот базовый подход для контентных изображений слишком простой и не решает проблему Retina-экранов и веса большого изображения на мобильных устройствах, но это хороший старт.
Для ретинизации фонового изображения необходимо задать размер фона элемента равным размеру самого элемента.
.box {
width: 200px;
height: 300px;
background-image: url('photo@2x.png');
background-size: 200px 300px;
}
В случае когда у элемента нет фиксированной ширины и высоты, размер фона можно задать значением cover, чтобы фон полностью заполнял элемент.
.box {
background-image: url('photo@2x.png');
background-size: cover;
}
При таком подходе браузер загрузит 2x изображение на любом экране - не идеально. Поэтому существуют медиа-функции позволяющие определить плотность пикселей экрана в CSS. Внутри набора таких медиа-функций, переопределяем путь к фоновому изображению.
/* Базовые стили и 1x изображение */
.box {
width: 480px;
height: 320px;
background-image: url('photo.png');
background-size: 480px 320px;
}
/* Переопределяем путь к 2x изображению
если плотность экрана как минимум 2 */
@media (min-device-pixel-ratio: 2),
(min-resolution: 192dpi),
(min-resolution: 2dppx) {
.box {
background-image: url('photo@2x.png');
}
}
В медиа-функции min-device-pixel-ratio указывается численное значение пиксельной плотности экрана - коэфициент между физическими и CSS-пикселями. Также необходимо указать функцию min-resolution с двумя разными значениями.
Медиа-функция min-device-pixel-ratio поддерживается некоторыми браузерами только с вендорным префиксом, поэтому если обработать этот код автопрефиксером получим финальный вариант.
.box {
width: 480px;
height: 330px;
background-image: url('photo.png');
background-size: 480px 320px;
}
@media (min-device-pixel-ratio: 2),
(-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi),
(min-resolution: 2dppx) {
.box {
background-image: url('photo@2x.png');
}
}
infoТакая солянка из медиа-функций и их значений нужна потому, что они еще не стандартизированы между разными браузерами.
В примере задано одинаковое фоновое изображение в различных размерах для экранов со стандартной (1x) и удвоенной (2x) плотностью пикселей.
Если открыть инструменты разработчика и перейти на вкладку Network, то будет видно, что загружается только одно изображение - подходящее под плотность экрана на котром открыта веб-страница. При входе с Macbook Pro 15" 2017, плотность пикселей экрана которого равна 2, браузер загрузит изображение в два раза больше стандартного.
Отзывчивый элемент <img> используется браузером для загрузки только подходящего под текущее устройство изображения из предложенных разработчиком. Разработчик указывает список доступных к загрузке изображений, а браузер, основываясь на размере экрана устройства и его пиксельной плотности, выбирает самое подходящее.
Например, разработчик указал два доступных изображения - 300×300 и 600×600 пикселей. Если браузеру достаточно картинки 300×300, это четырёхкратная экономия веса загружаемого изображения. Чем меньше размер экрана устройства, тем больше выгода от такого подхода. Экономия трафика на мобильном устройстве может достигать 70-90% по сравнению с десктопом.
Определяет список версий одного и того же изображения в разных размерах. Не стоит пытаться загрузить разные изображения (по контенту или формату) при помощи этой техники, браузер обращает внимание только на размер и считает что всё что передают в srcset это версии одного и того же изображения.
<img srcset="" src="" alt="" />
Самый простой способ использования отзывчивого элемента <img> это применение дескриптора x, который буквально указывает браузеру для какой плотности экрана подходит эта версия изображения.
<img
srcset="photo.jpg 1x, photo@2x.jpg 2x"
src="photo.jpg"
alt="Описание изображения для всех версий"
/>
В атрибуте src указывается версия изображения в стандартном качестве,
которая будет использована в случае если браузер старый и не значет о
srcset. В атрибуте srcset указываем 1x и 2x версии изображения, разделяя
объявления запятой. Если страница будет открыта на устройстве с
плотностью пикселей 2 или выше, вместо стандартного будет использовано
изображение photo@2x.jpg.
В примере для атрибута srcset указаны изображения стандартной и двойной
плотностей, а так же оригинальное изображение по умолчанию в атрибуте
src.
Если открыть инструменты разработчика и перейти на вкладку Network, то будет видно, что загружается только одно изображение - подходящее под плотность экрана на котром открыта веб-страница. При входе с Macbook Pro 15" 2017, плотность пикселей экрана которого равна 2, браузер загрузит изображение у которого указан дескриптор 2x.
Единственный недостаток такого подхода кроется в ограниченности
критериев по которым браузер выбирает изображение - только плотность
пикселей экрана. Отзывчивые изображения используются в отзывчивой
вёрстке, размеры блоков в которой изменяются в зависимости от размера
вьпорта.
Задать жёсткие размеры изображения на экране не всегда возможно, потому
что при увеличении вьюпорта необходимо будет показывать изображение
300x200 в блоке размерами 600x400 пикселей или больше.
Идеально если бы браузер выбирал изображения не только по плотности
пикселей, но ещё учитывал текущий размер вьюпорта и размер самой
картинки на экране. Для этого ему необходимо знать размер оригинального
изображения в предлагаемом списке. Как раз эту задачу и решает
дескриптор w и атрибут sizes.
Мы по-прежнему предоставляем одно и то же изображение в разных размерах, но при этом даём браузеру больше информации, чтобы он мог сам выбрать необходимое изображение, исходя из плотности пикселей, размера вьюпорта и оригинального размера изображения.
<img
srcset="photo-300.jpg 300w, photo-600.jpg 600w, photo-1200.jpg
1200w"
src="photo-300.jpg"
alt="Описание изображения для всех версий"
/>
Помечая каждое изображение дескриптором w, в котором указана ширина этого изображения в пикселях, мы перекладываем все вычисления и выбор изображения на браузер.
infoЕсли изображение photo-600.jpg размером 600x400 пикселей, то помечаем его дескриптором 600w. В имени файла изображения указываем его физическую ширину, чтобы не забыть, так как версий изображения может быть много.
При использовании дескриптора w, то есть при привязке к физическим
рамзерам изображения, необходимо использовать атрибут sizes, чтобы
подсказать браузеру приблизительный размер холста на котором в браузере
будет отрисовываться изображение. Размеры можно указывать как в
пикселях, так и в относительных единицах.
Например, если изображение на экране всегда будет 300px, достаточно
указать одно значение.
<img
srcset="photo-300.jpg 300w, photo-600.jpg 600w, photo-1200.jpg
1200w"
sizes="300px"
src="photo-300.jpg"
alt="Описание изображения для всех версий"
/>
В случае когда изображение должно быть на 100% ширины вьюпорта на мобильных устройствах до 600px, 300px на экранах 601-900px и 600px на экранах шире, значение sizes будет включать в себя медиа-запросы.
<img
srcset="photo-300.jpg 300w, photo-600.jpg 600w, photo-1200.jpg
1200w"
sizes="(min-width: 900px) 600px, (min-width: 600px) 300px,
100vw"
src="photo-300.jpg"
alt="Описание изображения для всех версий"
/>
infoБраузер читает медиа-выражения указанные в атрибуте sizes слева направо и выбирает первое подходящее, поэтому надо внимательно следить за порядком их объявления.
Бразуер выбирает картинку по очень простому алгоритму - умножает размер холста (значение sizes) на плотность пикселей и выбирает ближайшее подходящее по размеру изображение.
На илюстрации показан десктоп и смартфон с шириной изображения 100% ширины вьюпорта. Напишем разметку отзывчивого элемента <img /> для этого случая.
<img
srcset="img-1200x714.png 1200w, img-3000x1768.png 3000w"
sizes="100vw"
src="img.png"
alt="Описание изображения для всех версий"
/>
Браузер умножает ширину вьюпорта на плотность пикселей.
В случае когда в sizes задано фиксированное значение ширины изображения, браузер умножит его на плотность пикселей. Например, sizes задано значение 400px.
<img
srcset="
photo-300.jpg 300w,
photo-600.jpg 600w,
photo-900.jpg 900w,
photo-1200.jpg 1200w
"
sizes="400px"
src="photo-300.jpg"
alt="Описание изображения для всех версий"
/>
То есть для мобильного устройства будет взято большее изображение? Не всегда, браузер выбирает то изображение, которое лучше всего подходит в данной ситуации.
infoВ отличии от разработчика, который знает только размер изображения и приблизительный размер холста на котором оно будет отображаться, браузер знает все важные технические характеристики устройства на котором была открыта веб-страница. Кроме того браузер может учитывать другие факторы, такие как скорость интернет-соединения и состояние заряда батареи.
Как мы уже разобрались, отзывчивый элемент <img> позволяет загружать разные версии (размеры) одного и того же изображения. Элемент <picture> используется в случае когда необходимо загрузить изображения разного формата (расширения), изображения различные по геометрии (кадрирование) или изображения для поддержки режима тёмной темы..
infoВ каждой ситуации необходимо использовать правильный инструмент, в большинстве случаев будет достаточно отзывчивого элемента <img>, не обязательно везде применять <picture>.
Элемент <picture> это контейнер для одного или более элементов <source>, в которых перечисляются возможные варианты, и одного обязательного элемента <img>.
<picture>
<source srcset="" media="" sizes=""
type="" />
< source srcset="" media="" sizes=""
type="" />
<img src="" alt="" />
</picture>
Элемент <picture> применяется для загрузки изображений в
современных форматах (например webp). Для браузеров которые не
поддерживают такие форматы, указывается дефолтное изображение в
альтернативном формате (например jpg или png). Атрибут type указывает
MIME-тип изображения. Если браузер не подерживает его, то этот элемент
<source> пропускается.
Следующий пример определяет элемент <picture>, который позволит
браузерам загрузить photo.webp, при этом предоставляется альтернатива
photo.jpg для браузеров которые еще не поддерживают webp.
<picture>
<source srcset="photo.webp 1x, photo@2x.webp 2x"
type="image/webp" />
<source srcset="photo.jpg 1x, photo@2x.jpg 2x"
type="image/jpeg" />
<img src="photo.jpg" alt="Кот" />
</picture>
Все варианты доступных изображений перечисляются в тегах
infoДля того чтобы быстро и удобно сконвертировать изображения в формат webp, можно использовать онлайн-инструменты, например squoosh.app.
Техника кадрирования используется для загрузки различных изображений для
каждого экрана. Это позволяет показать пользователю максимум полезной
информации и деталей изображения даже на маленьких устройствах.
Например, загружать альбомную (landscape) или книжную (portrait) версию
изображения в зависимости от ориентации или разрешения устройства.
Атрибут media позволяет определить медиа-запрос, который браузер будет
анализировать для выбора элемента <source>. Если медиа-запрос
определяется как ложный (не подходит), то этот элемент <source>
пропускается.
<!-- Для экранов шире 600px будет загружен photo-wide.jpg -->
<picture>
<source srcset="photo-wide.jpg" media="(min-width:
600px)" />
<img src="photo.jpg" alt="Фотография" />
</picture>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptas repellat rerum numquam labore quos, obcaecati ad id saepe nam eius.
Для поддержики экранов с высокой плотностью пикселей, каждому элементу
<source> необходимо добавить набор изображений с дескрипторами в
атрибут srcset, и не забыть задать атрибут sizes.
Добавим в код предыдущего примера поддержку ретины с плотностью 2x
используя дескриптор w. Ограничим ландшафтную версию изображения
максимальной шириной 800px, если вьюпорт шире чем 800 пикселей. В
противном случае изображение тянется на 100% вьюпорта.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptas repellat rerum numquam asd quos, obcati ad id saepe nam eius.