Растр и вектор, JPG и PNG, адаптивность, оптимизации, облачные хранилища, CDN — работа с изображениями это нелёгкая тема
Работа с изображениями в вёрстке это та ещё задача: выбрать правильный формат — jpg/png/svg/webp и др;, подумать об адаптивности — зачем на мобайле грузить большие изображения с десктопа; заморочиться с размерами — не все изображения будут одинаковой ширины и высоты. Ух! Давайте разбираться.
Первое, чем отличаются изображения — форматом. Одни растровые, другие векторные.
Изображение состоит из сетки пикселей. Растровые изображения плохо масштабируются, потому что по сути вы увеличиваете размер пикселя.
Векторные изображения построены из геометрических фигур: точек, квадратов, кругов, кривых, векторов. Масштабируются отлично: потому что геометрия.
По форматам легко: в JPG или PNG хранят фотографии и другой контент, а в SVG — иконки.
Ещё у PNG есть прозрачность, а у JPG — качество сжатия: можно понизить "вес" файла просто поставив качество в 80% вместо 100%, особой разницы вы не заметите.
В изображениях хранятся мета-данные — данные, которые в Вебе нам не особо нужны: фотоаппарат, используемый софт для обработки и другие. Обычно они хранятся в EXIF. Все эти данные можно вырезать — это первый путь оптимизации.
Второй: пожать само изображение (как в случае с процентным качеством JPG). Вручную это делать утомительно, поэтому есть tinypng.com — сервис, который сожмёт изображения.
Но руками каждое изображение жать не очень удобно, поэтому есть много готовых библиотек. Одна из самых популярных ImageMagick, её используют на серверах: человек залил изображение, оно прошло через ImageMagick и указанные настройки, затем сохранилось куда-то.
Куда-то? Это куда? В проекте (мы же говорим про фронтэнд) можно хранить только иконки, а контентные изображения (например, фотографии меню, блюд или ресторанов) хранятся в облачных хранилищах и за них отвечает бэкэнд и база данных.
Какие бывают облачные хранилища? Обычно используют Amazon AWS S3 либо аналоги от Гугла (Google Cloud Storage), Майкрософта (Azure Blob Storage), DigitalOcean (Digital Ocean Spaces) и других. Ещё есть Uploadcare — законченное решение вместе с виджетом и хранением.
Кстати, хранение изображений это одно, а ведь нужно ещё отвечать за распространение! Этим занимается CDN — Content Delivery Network.
В самом примитивном варианте CDN раздаёт изображения с ближайшего до пользователя сервера: если вы в Европе, то явно вам нужно отдавать данные не из Японии, Франкфурт больше подойдёт.
Как это работает? Банальным дублированием файлом на каждый сервер в каждом регионе — поэтому нужно обычно ждать несколько часов пока изображения появятся на всех CDN-точках провайдера.
Как всегда, есть решения от Amazon (Amazon AWS Cloudfront), Google (Google Cloud CDN) и других.
Вам нужно об этом знать — вы отвечаете за сайт. Если фронтэндер не будет обращать внимания на вес изображений, на скорость загрузки и другие вещи — сайт будет работать медленно. Интерфейс будет работать медленно, бизнес будет терять деньги.
Поэтому в ваших и только в ваших интересах форсить нарезку изображений (когда одно изображение режется несколько раз — для мобайла, планшета и десктопа), их сжатие, использование CDN и другие оптимизации.
Продолжим.
Я упомянул, что изображения режутся под разные разрешения, а как понять как резать?
В своей практике я видел много подходов, но остановился на одном идеальном: уменьшать по высоте, а за высоту взять степень двойки.
Чего? Почему по высоте? Потому что зачастую изображения на странице ограничены по высоте, но не по ширине: если вы поставите всем изображениям 256 пикселей ширины, то у одних высота будет в 452 пикселя, у других 211, у третьих 987.
Представьте такую ситуацию на сайте ЦУМ-а? Невозможно.
Или вот ещё пример: фотографии домов. Они могут быть 16:9, могут быть 4:3, могут 3:4, могут 16:10, но при подходе ограничения высоты это не играет никакой роли.
А что за степень двойки? Это просто самый удобный формат, который легко запоминается: 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 и выше.
При таком подходе и ретина-изображения встают идеально: если вам для ретины нужна картинка в 256 пикселей, то берёте 512. Удобно!
Есть два подхода: либо background-image
, либо тег <img>
. Разница в их индексируемости поисковиками.
Индексируются, особенно если прописывать alt=""
— описание изображения. Поисковики вас полюбят.
Не индексируются.
Гугл рекомендует использовать svg и вставлять их либо через тег <img>
, либо сразу в код; но второй подход неудобен, потому что представьте что вам нужно пройтись по всему проекту, чтобы заменить одну иконку?
Если изображение находится в сетке, то обычно им задают ширину в 100% чтобы они растягивались. → Пример.
Если изображение на фоне или само по себе, то задают высоту, чтобы на всё остальное пространство оно растягивалось.
Задают только одну сторону, иначе есть риск сломать пропорции и изображение будет сжатым или растянутым.
Раньше с адаптивностью была дичь — её вообще не было. Сейчас у нас есть тег picture
, его поддержка сейчас — 88.22%.
Один из его жирных плюсов — обратная совместимость: даже если браузер не поддерживает тег picture
, то изображение всё равно будет у пользователя за счёт тега img
.
Пример использования:
<picture>
<source media="(max-width: 767px)" srcset="https://via.placeholder.com/100x100/E61E7F/ffffff, https://via.placeholder.com/100x100/44BB51/ffffff 2x">
<source media="(min-width: 768px)" srcset="https://via.placeholder.com/768x100/E61E7F/ffffff, https://via.placeholder.com/768x100/44BB51/ffffff 2x">
<img src="https://via.placeholder.com/768x100/E61E7F/ffffff" srcset="https://via.placeholder.com/768x100/E61E7F/ffffff 2x" alt="a head carved out of wood">
</picture>
iframe: https://jsfiddle.net/774s3y62/embedded/result/
Если у вас Ретина, то изображение будет зеленым, а если нет — розовым.
Если фронтэндер не позаботится об изображениях, о них никто не позаботится.
- использовать JPG когда на изображении нет текста или прозрачности, плюс он дешевле в весе;
- использовать PNG когда есть текст или прозрачность, придется пожертвовать весом;
- использовать SVG для иконок;
- использовать тег
<picture>
и атрибутыsrcset
уже можно; - оптимизировать через ImageMagick;
- им же и нарезать по высоте, взяв степень двойки за основу;
- хранить изображения в облачных сервисах;
- использовать CDN чтобы пользователь получал изображение с ближайшего сервера.