Адаптивные изображения в CSS

Адаптивные изображения в CSS

От автора: термин адаптивные изображения стал ассоциироваться с адаптивными изображениями в HTML. Другими словами, это атрибуты srcset и sizes тега img и тег picture. Но как это относится к CSS?

CSS, на самом деле, не был вовлечен в развитие адаптивных изображений последние несколько лет. Это было сделано не просто так: у CSS уже есть свои инструменты. Адаптивные изображения, в некотором смысле, просто догоняют CSS. Давайте же разберемся.

Замена атрибута srcset в CSS

В HTML атрибут srcset записывается так (взято с сайта Picturefill ):

<img srcset="
  examples/images/image-384.jpg 1x, 
  examples/images/image-768.jpg 2x
" alt="...">

Одно изображение для 1х дисплеев, более крупное изображение для 2х дисплеев. Если сделать то же самое, но только через CSS свойство background-image, это выглядело бы так:

.img {
  background-image: url(examples/images/image-384.jpg); 
}
@media 
  (-webkit-min-device-pixel-ratio: 2), 
  (min-resolution: 192dpi) { 
  .img {
    background-image: url(examples/images/image-768.jpg);
  }
}

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

Есть и другой способ, более близкий к принципу работы srcset. Данный метод использует CSS функцию image-set():

.img {
  background-image: url(examples/images/image-384.jpg);
  background-image: 
    -webkit-image-set(
      "examples/images/image-384.jpg" 1x,
      "examples/images/image-768.jpg" 2x,
    );
  background-image: 
    image-set(
      "examples/images/image-384.jpg" 1x,
      "examples/images/image-768.jpg" 2x,
    );
}

У данного метода поддержка чуть-чуть хуже, чем у медиа запросов по разрешениям экрана:

Намного ближе к srcset не только из-за синтаксиса, но и потому что так у браузера есть варианты действий. Из спецификации (все еще черновик). В CSS нет полной замены атрибуту srcset, но этот метод очень близок.

Замена атрибута sizes в CS

HTML атрибут sizes напрямую связан с CSS. На деле атрибут как бы говорит: «Именно вот так я изменю размер изображения в CSS, а я просто показываю тебе это, чтобы ты знал на тот случай, если эта информация тебе понадобится прямо сейчас, и у тебя нету времени ждать, пока загрузится CSS.» Пример:

<img
  sizes="(min-width: 40em) 80vw, 100vw"
  srcset=" ... "
  alt="...">

В CSS это будет выглядеть так:

img {
  width: 100%;
}
@media (min-width: 40em) {
  /* Некий родительский блок, ограничивающий ширину изображения */
  main {
    width: 80%;
  }
}

Но сам по себе атрибут sizes не делает ровным счетом ничего. Данный атрибут необходимо записывать вместе с srcset, через который задается ширина, чтобы браузер мог выбирать. К примеру, у нас есть пара изображений:

<img
  sizes="(min-width: 400px) 80vw, 100vw"
  srcset="examples/images/small.jpg 375w,
          examples/images/big.jpg 1500w"
  alt="...">

Информация в разметке выше позволяет браузеру определить, какое изображение подходит лучше всего. Браузер знает про 1) размер окна и 2) про плотность пикселей.

К примеру, окно браузера имеет ширину 320px и 1х дисплей. Теперь браузер знает, что он будет отображать изображение на 100vw. Браузер должен выбрать одно из двух изображений, и он производит вычисления.

375 (размер изображения 1) / 320 (пикселей на отображение изображения) = 1.17

1500 (размер изображения 2) / 320 (пикселей на отображение изображения) = 4.69

1.17 ближе к 1 (1х дисплей), поэтому изображение 375w выиграет. Насколько я понял, браузер не будет занижать значение, поэтому он выберет 1.3, а не 0.99. А теперь для 2х дисплея. На таком экране пикселей для отображения изображения в два раза больше. Расчеты будут такими:

375 / 640 = 0.59

1500 / 640 = 2.34

Тут выиграет значение 2.34, и будет показано изображение 1500w. А если взять 1х дисплей с шириной 1200px?

375 / (80% от 1200) = 0.39

1500 / (80% от 1200) = 1.56

Тут выиграет изображение 1500w. Довольно сложно записать такое в CSS. Если взять 1х дисплеи, то логика будет следующая…

Если ширина окна меньше 365px, использовать изображение 375px.

Если ширина окна больше 375px, но меньше 400px, использовать изображение 1500w (в обратном случае пришлось бы увеличивать изображение).

На 400px изображение переходит на ширину 80vw, поэтому безопасно будет использовать изображение 375w на очень маленьком промежутке (от 400px до 468px).

Свыше 468px использовать изображение 1500w.

Все это можно переписать в:

img {
  background-image: url(small.jpg);
}
/* Перепишите, если выполняется одно из условий для изображения 1500w */
@media 				
  (min-width: 375px) and (max-width: 400px),
  (min-width: 468px) {
  main {
    background-image: url(large.jpg);
  }
}

Конкретно в этом примере 2х дисплеи, даже с очень маленькой шириной 300px, требуют 600px для отображения 1:1. В таком случае необходимо добавить:

.img {
  background-image: url(small.jpg);
}
/* Перепишите, если выполняется одно из условий для изображения 1500w */
@media 
  (min-width: 375px) and (max-width: 400px),
  (min-width: 468px),
  (-webkit-min-device-pixel-ratio: 2), 
  (min-resolution: 192dpi) {
  .img {
    background-image: url(large.jpg);
  }
}

Код становится сложнее из-за все большего количества разрешений и изображений. Данная реализация все еще не идеально заменяет возможности адаптивных изображений в HTML, так как браузер не может сам делать выбор. К примеру, возможность браузера решать на основе различных факторов (качество соединения) и подбирать нужное изображение.

Замена тегу picture в CSS

Пример:

<picture>
  <source srcset="extralarge.jpg" media="(min-width: 1000px)">
  <source srcset="large.jpg" media="(min-width: 800px)">
  <img srcset="medium.jpg" alt="...">
</picture>

Такую разметку можно очень просто преобразовать в медиа запросы. Точная копия кода выше, но в медиа запросах:

.img {
  background-image: url(medium.jpg);
}
@media (min-width: 800px) {
  .img {
    background-image: url(large.jpg);
  }
}
@media (min-width: 1000px) {
  .img {
    background-image: url(extralarge.jpg);
  }
}

Такой код более сложный. То же самое можно сделать с атрибутом srcset и тегом picture:

<picture>
  <source srcset="large.jpg, extralarge.jpg 2x" media="(min-width: 800px)">
  <img srcset="small.jpg, medium.jpg 2x" alt="…">
</picture>

Что можно перевести в:

.img {
  background-image: url(small.jpg);
}
@media
  (-webkit-min-device-pixel-ratio: 2), 
  (min-resolution: 192dpi) {
  .img {
    background-image: url(medium.jpg);
  }
}
@media
  (min-width: 800px) {
  .img {
    background-image: url(large.jpg);
  }
}
@media
  (-webkit-min-device-pixel-ratio: 2) and (min-width: 800px), 
  (min-resolution: 192dpi) and (min-width: 800px) {
  .img {
    background-image: url(extralarge.jpg);
  }
}

И опять же, код станет намного сложнее, если добавить больше изображений и условий. Немного лучше получится с image-set():

.img {
  background-image: url(small.jpg);
  background-image: 
    -webkit-image-set(
      "small.jpg" 1x,
      "medium.jpg" 2x,
    );
  background-image: 
    image-set(
      "small.jpg" 1x,
      "medium.jpg" 2x,
    );
}
@media
  (min-width: 800px) {
  .img {
    background-image: url(large.jpg);
    background-image: 
      -webkit-image-set(
        "large.jpg" 1x,
        "extralarge.jpg" 2x,
      );
    background-image: 
      image-set(
        "large.jpg" 1x,
        "extralarge.jpg" 2x,
      );
  }
}

Могут ли помочь миксины?

Возможно. Я был бы рад найти Sass миксин, который брал бы все параметры, факторы размеров изображений и разбивал бы их по разному качеству в CSS коде. Может быть, даже есть способ объединить медиа запросы по разрешениям экрана и синтаксис image-set()?

Будем ли мы использовать такие методы?

Мне интересно, сколько людей активно обрабатывают адаптивные изображения в CSS. Может, есть способ просто переключаться на большие изображения с увеличением разрешения? Зачастую picture/srcset больше автоматизированы. Может быть, это влияет на более частое принятие решения в их пользу?

Автор: Chris Coyier

Источник: https://css-tricks.com/

Редакция: Команда webformyself.

Практика HTML5 и CSS3 с нуля до результата!

Получите бесплатный пошаговый видеокурс по основам адаптивной верстки с полного нуля на HTML5 и CSS3

Получить

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree