Frontender Magazine

Простой способ сделать отзывчивые изображения с помощью фоновых картинок в CSS

Примечание редактора Frontender Magazine: cтатья была написана в 2012 году, когда не было элемента <picture>, о использовании которого можно прочесть, например, в статьях «Отзывчивые изображения: примеры использования и документированные снипеты, чтобы вы могли начать их использовать» и более ранней «Как избежать лишних загрузок для отзывчивых изображений». Данная статья, однако, содержит интересные приемы, о которых стоит знать.

Примечание редактора Smashing Magazine: в этой статье описано только одно из многих близких к оптимальному решений для создания отзывчивых изображений. Перед выбором конкретного решения мы рекомендуем ознакомиться с разными подходами, в том числе вот с этими: «Как избежать лишних загрузок при использовании отзывчивых изображений» и «Выбираем решение для изображений в отзывчивом дизайне».

Учитывая все разговоры о новых стандартах HTML5, таких как атрибут srcset и элемент <picture>, и применении серверных решений вроде Отзывчивого вебдизайна + Серверных компонентов (RESS), у вас могло сложиться впечатление, что на сегодняшний день простые статические сайты не могут содержать отзывчивые изображения. Однако это впечатление несколько преждевременно. На самом деле, есть простой и незамысловатый способ представления отзывчивых изображений, поддерживаемый всеми современными веб-браузерами: фоновые изображения в CSS.

У этого подхода тоже есть некоторые ограничения, и в некоторых случаях он работать не будет, но, если ваши требования не слишком завышены, и вы готовы приложить усилия, чтобы обеспечить доступность изображений, возможно, фоновые изображения в CSS - это именно то решение, которое вам нужно.

В этой статье мы в несколько этапов рассмотрим подход с использованием фоновых изображений в CSS:

  1. Сначала мы рассмотрим задачи и требования к отзывчивым изображениям.
  2. Затем выясним как CSS-медиазапросы могут помочь нам определить главные характеристики пользовательских устройств.
  3. Подробно рассмотрим ключевое свойство background-image, которое позволяет подстраивать изображение под эти характеристики.
  4. Рассмотрим стратегию оптимизации отдельных изображений, из которых формируется набор изображений, решающий проблему отзывчивости.
  5. Изучим ограничения этого подхода — в большинстве случаев их можно легко обойти.
  6. И, наконец, определим проблемные моменты, для которых нет решения.

Примечание: чтобы использовать этот подход, вам понадобится полный контроль над таблицей стилей и HTML-разметкой вашего сайта. Если для него используется система управления контентом (CMS), у вас может быть недостаточно доступа к управлению этими компонентами сайта.

Потребность в отзывчивых изображениях

Отзывчивые изображения - это важная составляющая отзывчивого вебдизайна, подхода, предложенного Итаном Маркоттом (Ethan Marcotte) для удовлетворения требований мобильных устройств, которые очень широко используются для просмотра сайтов. Итан признал, что прежний подход, состоящий в создании отдельных сайтов для разных типов устройств, был не в состоянии справиться с требованиями огромного разнообразия устройств, которые используют посетители сайтов для доступа в интернет.

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

Во многих случаях вся отзывчивость дизайна заканчивается именно здесь — на простых изменениях в расположении контента и его представлении. Если мы уделяем внимание только этим моментам, цель отзывчивого дизайна нельзя считать достигнутой, потому что удовлетворяются не все потребности пользователей.

Чтобы полностью соответствовать контексту, в котором пользователь просматривает сайт, дизайн этого сайта должен учитывать все аспекты, влияющие на удобство использования, включая изображения. Вот пример из жизни: взгляните на сайт contfont.net. Этот одностраничный сайт состоит из одного изображения и типичного набора из HTML, таблицы стилей, шрифтов и JavaScript.

Компонент Тип Размер в сжатом виде
Главная страница HTML 6 Кб
Таблица стилей CSS 10 Кб
Шрифты Веб-шрифт 221 Кб
Скрипты JavaScript 21 Кб
Вспомогательные изображения Изображение 48 Кб
Главное изображение Изображение ??

На больших экранах сайт выглядит просто шикарно благодаря большому разрешению главного изображения. Загрузка этого изображения, однако, обходится недёшево: при разрешении 1940 × 1229 пикселей изображение даже после сжатия весит 446 Кб.

Теоретически можно использовать одно и то же изображение для всех пользователей без ущерба для визуального представления — браузеры на небольших устройствах могут подстроить его размер под размер экрана. Однако при таком подходе удобство пользователя серьезно пострадает, хоть визуальное впечатление от сайта и остаётся неизменным.

Сравнение

На iPhone изображение с разрешением 290 × 183 пикселей и размером 18 Кб выглядит точно так же, как изображение с разрешением 1940 × 1229 пикселей и размером 452 Кб выглядит на MacBook Pro. Крупнее.

Что это значит для пользователя, который просматривает сайт, скажем, на смартфоне старого поколения? Для этого пользователя изображение с разрешением 290 × 183 пикселей и размером 18 Кб будет выглядеть точно также, как его большая версия. Если не применять отзывчивый подход к изображениям, пользователю придётся скачивать дополнительные и абсолютно ненужные 429 Кб данных. И это создаёт не только теоретические неудобства — лишний вес значительно влияет на время загрузки сайта. Пользователь смартфона может просматривать сайт используя обычное подключение через 3G со скоростью 2 Мб/с. Если не использовать отзывчивое изображение, время загрузки сайта увеличивается от 1,3 секунд до 3 секунд — больше чем вдвое!

Статистика

При соединении через 3G изображение исходного размера грузится 3 секунды, отзывчивое - 1,3 секунды. Крупнее.

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

Определение пользовательского контекста

Поскольку сайты должны подстраиваться под контекст пользователя, нам нужен способ определения этого контекста. На сегодняшний день CSS предлагает наиболее эффективный способ различать устройства. Мы получаем ответы на два важных вопроса: какой размер экрана на устройстве пользователя? Поддерживаются ли изображения, оптимизированные под ретину?

Эту информацию мы можем получить благодаря CSS-медиазапросам. Медиазапросы позволяют прописать набор стилей, которые будут применяться только для устройств с определёнными характеристиками. Изначально медиазапросы ограничивались только типом носителя. В спецификации CSS описано достаточное их количество, например, braille (тактильные устройства на системе Брайля), speech (речевые синтезаторы), tty (устройства, поддерживающие только моноширинные шрифты, например, телетайпы) и tv (устройства вроде телевизоров с низким разрешением и без возможности прокрутки). На данный момент большинство браузеров понимает только два типа носителей: print (печатный материал, разбитый на страницы) и screen (экраны компьютеров).

В CSS3 была добавлена возможность указания определённых характеристик устройств, а не только типа носителя. Для устройств screen, можно указать множество характеристик экрана, в том числе его ширину, ориентацию, разрешение и соотношение логических и физических пикселей. Эти характеристики дают нам достаточно информации, чтобы подобрать изображение, подходящее под конкретное устройство.

Медиазапросы могут помочь решить дилемму, описанную немного выше. К примеру, у MacBook Pro с диагональю 15 дюймов ширина экрана составляет 1440 пикселей (пока что не будем рассматривать наличие ретины). В таблице стилей нашего сайта стиль для экранов таких размеров можно прописать так:

@media only screen and (min-width: 1440px) {
    /* стили для экранов с размером как у MacBook Pro и больше */
}

Любые стилевые характеристики, описанные в этом блоке кода, будут применяться только когда пользователь открывает веб-страницу на устройстве с шириной экрана в 1440 пикселей. Однако здесь есть маленький нюанс: под размером экрана следует понимать не физический размер экрана устройства, а размер области просмотра в окне браузера. Размер области просмотра равен размеру окна браузера без различных окантовок вроде полосы прокрутки.

В общем-то, ширина окна браузера наверняка будет меньше 1440 пикселей, если только что пользователь не переключился на полноэкранный режим просмотра. Нам стоит это учесть в таблице стилей, 1200 пикселей наверное будет ближе к истине.

@media only screen and (min-width: 1200px) {
    /* стиль для широких экранов */
}

Этот медиазапрос состоит из двух частей. Первая часть, only screen, указывает на то, что стиль не должен применяться при печати страницы или на нестандартных устройствах. (Слово only никак не влияет на сам медиазапрос: оно используется для очень старых браузеров, которые не распознают параметры устройства. Так как эти браузеры не понимают синтаксис only, они просто проигнорируют блок со стилями целиком). Во второй части медиазапроса, min-width: 1200px, указана минимальная ширина экрана, при которой должен применяться стиль. Оператор and, соединяющий эти части, указывает на то, что для срабатывания стиля оба условия должны быть верны.

Похожий приём можно использовать прописывая стили для смартфонов в портретной ориентации.

@media only screen and (max-width: 320px) {
    /* стили для узких экранов */
}

В этом случае в медиазапросе можно смело указывать размер самого экрана устройства, так как браузеры на смартфонах всегда работают в полноэкранном режиме.

С помощью условий min-width и max-width можно легко определить ширину устройства пользователя. К сожалению, с определением ретины не всё так просто. Разные браузеры используют разный синтаксис для этого параметра, поэтому следует использовать вендорные префиксы. Ещё одна ложка дёгтя: в синтаксисе многих версий Firefox присутствует ошибка, так что для браузеров от Mozilla нам придётся использовать и нормальный синтаксис, и «дефектный». На данный момент для ретины рекомендуется использовать медиазапросы такого вида:

@media
only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (min--moz-device-pixel-ratio: 2),
only screen and (-moz-min-device-pixel-ratio: 2),
only screen and (-o-min-device-pixel-ratio: 2/1),
only screen and (min-device-pixel-ratio: 2),
only screen and (min-resolution: 192dpi),
only screen and (min-resolution: 2dppx) { 
    /* стили для дисплеев Retina */
}

Когда-нибудь все браузеры будут поддерживать стандартную запись dppx (точки на дюйм), и мы сможем отказаться от вендорных префиксов в CSS.

CSS-cвойство background-image

Поскольку CSS позволяет достоверно определить контекст пользователя, может показаться, что теперь можно легко обеспечить поддержку отзывчивых изображений. Логично вроде бы задать display: none для изображений, которые не должны загружаться. Вот как этот способ будет выглядеть с привязкой к размеру экрана (для краткости опустим код для ретины):

<!DOCTYPE html>
<html lang="ru">
    <head>
        <meta charset="utf-8">
        <title></title>
        <style>
        img.smallscreen { display: none; }
        @media only screen and (max-width: 320px) {
            img { 
                display: none; 
            }
            img.smallscreen { 
                display: inline; 
            }
        }
        </style>
    </head>
    <body>
        <img src="largeimage.jpg">
        <img class="smallscreen" src="smallimage.jpg>
    </body>
</html>

Приведенный выше код будет отображать нужное изображение в зависимости от размера экрана, однако display: none не предотвращает загрузку скрытых изображений. Браузеры на смартфонах будут скачивать большое изображение, хоть оно и не будет отображено, так что, к сожалению, этот вполне логичный подход не решает главную задачу отзывчивых изображений.

Причина этой проблемы в том, что браузеры обрабатывают HTML отдельно от CSS. Разметка HTML запрашивает два файла с изображениями, и браузер их послушно загружает. Затем он проводит разбор стилей CSS и обнаруживает, что одно из изображений не должно отображаться, но уже поздно.

Наши медиазапросы в CSS будут работать только если они будут использоваться сугубо для свойств CSS, а не для содержимого HTML. Это может показаться невозможным, но, оказывается, есть хитрый способ использовать для изображений только CSS: с помощью свойства background-image. Вот как это делается:

  1. В разметку HTML не помещайте никакие запросы на файлы изображений. Вместо этого используйте пустые элементы <div> или <span>.
  2. Задайте этим элементами фоновые изображения через свойство background-image.
  3. Используйте медиазапросы, чтобы изменять изображение в зависимости от размера и разрешения экрана.

Следуя этому алгоритму мы можем подкорректировать приведенный выше пример, чтобы наши отзывчивые изображения начали работать правильно:

<!DOCTYPE html>
<html lang="ru">
    <head>
        <meta charset="utf-8">
        <title></title>
        <style>
        #image { 
            background-image: url(largeimage.jpg); 
        }
        @media only screen and (max-width: 320px) {
            #image { 
                background-image: url(smallimage.jpg); 
            }
        }
        </style>
    </head>
    <body>
        <div id="image"></div>
    </body>
</html>

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

Создание отзывчивых изображений

Теперь, когда мы разобрались как использовать отзывчивые изображения, следующий шаг, собственно, создать разные варианты одного изображения. Исходное изображение должно иметь максимально большое разрешение, как минимум равное максимальному разрешению, в котором оно будет представлено на сайте. (В случае с contfont.net разрешение исходного изображения равно 3888 × 2592 пикселей). Ваш графический редактор должен уметь изменять размер исходного изображения под контрольные точки дизайна вашего сайта.

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

Когда дело доходит до определения контрольных точек, не поддавайтесь искушению использовать одни и те же контрольные точки для разметки сайта и изображений. Очень редко отличные контрольные точки для разметки сайта оказываются подходящими для изображений. Вместо этого выберите оптимальные контрольные точки для конкретного изображения. Далее изложена стратегия, которой я пользуюсь при поиске оптимальных размеров изображения.

Сначала определитесь каким будет наименьшее оптимальное разрешение для изображения на вашем сайте. На contfont.net ширина наименьшей области просмотра на реально существующем устройстве составляет 320 пикселей — это iPhone без ретины в портретной ориентации. (Устройства с меньшей областью просмотра существуют и будут существовать - в виде смарт-часов, например - но вряд ли их будут использовать для просмотра сайтов). На сайте contfont.net при области просмотра шириной в 320 пикселей под изображение остаётся 290 пикселей, значит самое маленькое изображение, которое нам нужно подготовить, должно иметь разрешение 290 × 183 пикселя. С помощью графического редактора изменяем размер исходного изображения соответственным образом.

Затем создаём простую тестовую страницу для этого изображения. Я использую такую разметку:

<!DOCTYPE html>
<html lang="ru">
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <img src="test.jpg" width="100%">
        <p>Размер окна: <span id="size"></span> пикселей</p>
        <script>
        window.onresize = function() {
            document.getElementById("size").innerHTML = window.innerWidth;
        };
        </script>
    </body>
</html>

На этой странице отображается тестовое изображение и текущий размер окна. Открываем её в браузере и изменяем размер окна до наименьшей контрольной точки. Изображение должно выглядеть хорошо, так как его размер соответствует ширине окна.

Теперь медленно растягиваем окно браузера, увеличивая его ширину. По мере увеличения ширины окна, браузер будет автоматически перерассчитывать и изменять размер изображения. При увеличении размера начинает страдать качество изображения, и в определённый момент оно становится неприемлемо плохим. Обратите внимание при какой ширине экрана это происходит - это наша первая контрольная точка.

Качество

Увеличиваем размер окна браузера до ширины, при которой изображение будет выглядеть недопустимо некачественным. Эта ширина экрана - наша контрольная точка. Крупнее

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

На этом этапе у нас есть контрольные точки для изображений и набор соответствующих изображений. Для экранов с ретиной нужно создать дополнительный набор изображений с удвоенным разрешением. Вот полный список изображений для сайта contfont.net:

Файл с изображением Разрешение Размер (без сжатия)
candc290.jpg 290 × 183 19,378 байт
candc290@2x.jpg 290 × 183 (Retina) 56,277 байт
candc538.jpg 538 × 341 52,914 байт
candc538@2x.jpg 538 × 341 (Retina) 159,867 байт
candc970.jpg 970 × 614 132,766 байт
candc970@2x.jpg 970 × 614 (Retina) 451,939 байт

Этот подход можно использовать отдельно для каждого изображения на вашем сайте, так как нет причины, по которой для всех изображений должны быть использованы одинаковые контрольные точки. Однако, если на вашем сайте много изображений, более разумным будет найти общие контрольные точки для нескольких изображений и затем использовать их для всех изображений.

Обходим ограничения

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

Делаем изображения доступными

Стандартный тег <img> поддерживает атрибут alt, который позволяет добавить альтернативное текстовое описание изображения. Это описание является важным для доступных сайтов, ведь содержимое alt, описывающее изображение, необходимо пользователям, которые посещают сайт с помощью скринридера. У фоновых изображений в CSS нет тега <img> и, соответственно, атрибута alt, но их всё же можно сделать доступными для слабовидящих пользователей. Для этого добавляем в разметку два дополнительных атрибута:

<div id="image" role="img" aria-label="Текстовое описание"></div>

Первый дополнительный атрибут, role, позволяет скринридерам узнать, что <div> исполняет роль тега <img>, даже если по разметке этого не скажешь. Второй атрибут, aria-label служит для той же цели, что и атрибут alt в <img>. Эти два дополнения позволяют скринридеру уведомить пользователя, что элемент является изображением, и прочитать альтернативное текстовое описание, предоставленное для этого изображения.

Масштабирование изображений в браузере

У тега <img> есть еще одно полезное свойство, которое не используется при нашем подходе: автоматический перерасчет размеров и сохранение пропорций изображения браузером. Используя стандартный <img>, можно задать ширину в процентах от содержащего элемента, и браузер автоматически рассчитает ширину изображения и пропорционально подстроит высоту. Например, взгляните на фрагмент ниже, в котором у изображения image.jpg естественный размер 600 × 300 пикселей.

<div style="width: 400px">
    <img src="image.jpg">
</div>

Браузер автоматически уменьшает изображение, чтобы оно поместилось в контейнер <div>, при этом ширина уменьшается от 600 до 400 пикселей. Он также сохраняет соотношение сторон изображения, уменьшая высоту от 300 до 200 пикселей. В результате получается изображение без каких-либо искажений, которое прекрасно вписывается на страницу.

С помощью подхода, впервые описанного Грейди Кунлайном, можно добиться того же эффекта и для фоновых изображений в современных браузерах. (Внимание: подход, описанный в следующей части статьи не работает в Internet Explorer 8 и старше, так как эти версии не поддерживают необходимые CSS-свойства)

Проблему подстройки ширины решить не сложно. Так же как и при использовании тега <img>, можно поместить наш элемент в <div> с фиксированной шириной; всего лишь нужно чётко прописать, что фон должен заполнить этот <div>. Разметка HTML не сильно отличается:

<div style="width: 400px">
    <span id="image"></span>
</div>

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

  1. Задаём значение inline-block для свойства display элемента #image. Без этого свойства элемент <span> будет отображаться как строчный элемент, и ему нельзя будет задать ширину или высоту.
  2. Для свойства width этого элемента задаём значение 100% чтобы наше изображение заполнило контейнер <div>.
  3. Свойствам font-size и line-height присваиваем значение 0, чтобы никакое содержимое span не могло повлиять на его размер.
  4. Центрируем элемент с изображением по вертикали в контейнере <div> с помощью значения middle для свойства vertical-align.
  5. Задаём значение 100% свойству background-size чтобы изображение полностью заполнило элемент, к которому оно привязано.
  6. Для свойства background-position указываем значение 50% 50% чтобы выровнять фоновое изображение относительно элемента.
  7. Указываем значение no-repeat для свойства background-repeat чтобы предотвратить повторение изображения по вертикали или горизонтали.

В результате получаем стили для элемента с привязанным изображением (элемент <span> с id="image")

#image {
    display: inline-block;
    width: 100%;
    font-size: 0;
    line-height: 0;
    vertical-align: middle;
    background-size: 100%;
    background-position: 50% 50%;
    background-repeat: no-repeat;
    background-image: url(image.jpg); 
}

Эти свойства задают изображению ширину, однако нам ещё нужно разобраться с высотой. Ни одна составляющая разметки или стилей, приведённых выше, не говорит браузеру какой должна быть высота элемента с изображением, поэтому мы получим элемент с высотой по умолчанию, которая, к сожалению, равна нулю, ведь, по сути, в элементе <span> нет содержимого. К счастью, это можно исправить с помощью пары незначительных дополнений.

Сперва нам нужно добавить в разметку ещё один элемент <span>. Этот дополнительный элемент помещаем внутрь элемента с изображением.

<div style="width: 400px">
    <span id="image">
        <span id="image-inner">
        </span>
    </span>
</div>

Теперь прописываем несколько стилевых свойств для этого внутреннего <span>.

  1. Добавляем свойство display со значением block, чтобы ему можно было задать высоту и ширину.
  2. Устанавливаем для height значение 0, поскольку в элементе нет реального содержимого.
  3. Добавляем свойство padding-top с процентным значением равным соотношению высоты и ширины изображения.

Последний пункт является ключевым: <span> не наследует высоту от своего содержимого, но, благодаря padding-top, в нём появляется отступ по вертикали. Кроме того, свойство padding-top принимает процентное значение, которое рассчитывается относительно ширины элемента. Разрешение нашего изображения 970 × 614 пикселей, значит процентное значение, которое мы будем использовать, равно (614 ÷ 970) × 100%, или же 63.3%. Теперь браузер позаботится о том, чтобы изображение сохраняло соотношение сторон при увеличении или уменьшении.

#image-inner {
    display: block;
    height: 0;
    padding-top: 63.3%;
}

А теперь всё вместе

Чтобы проверить как эти все компоненты сочетаются между собой, вот код для сайта contfont.net, который мы взяли в качестве примера. Сначала разметка HTML для главного изображения:

<div class="hero">
    <span id="cafe" role="img" aria-label="Кофе и круассан">
        <span class="inner">
        </span>
    </span>
</div>

В таблице стилей описаны свойства, которые позволяют масштабировать изображение с сохранением пропорций:

.hero #cafe {
    width: 100%;
    display: inline-block;
    vertical-align: middle;
    font: 0/0 serif;
    text-shadow: none;
    color: transparent;
    background-size: 100%;
    background-position: 50% 50%;
    background-repeat: no-repeat;
}
.hero #cafe .inner {
    padding-top: 63.35%; /* высота/ширина изображения */
    display: block;
    height: 0;
}

И наконец, набор медизапросов для подбора подходящего изображения в зависимости от контекста пользователя (для краткости в примере опущены вендорные префиксы):

/* стандартный экран, не retina */
.hero #cafe { 
    background-image: url("../img/candc970.jpg"); 
}

@media only screen {
    /* маленький экран, не retina */
    .hero #cafe { 
        background-image: url("../img/candc290.jpg"); 
    }
}
@media
only screen and (min-resolution: 2dppx) {
    /* маленький экран, retina */
    .hero #cafe { 
        background-image: url("../img/candc290@2x.jpg");
    }
}
@media only screen and (min-width: 321px) {
    /* экран среднего размера, не retina */
    .hero #cafe { 
        background-image: url("../img/candc538.jpg"); 
    }
}
@media
only screen and (min-resolution: 2dppx) and (min-width: 321px) {
    /* экран среднего размера, retina */
    .hero #cafe { 
        background-image: url("../img/candc538@2x.jpg"); 
    }
}
@media
only screen and (min-resolution: 2dppx) and (min-width: 539px) {
    /* большой экран, retina */
    .hero #cafe { 
        background-image: url("../img/candc970@2x.jpg"); 
    }
}

Возможные проблемы

На сегодняшний день фоновые изображения в CSS дают нам удобный способ создания отзывчивых изображений, однако этот подход не идеален. Его основная часть нарушает один из фундаментальных принципов веб-стандартов: разделение содержания и представления. Более продвинутые приёмы, применяемые для улучшения этого подхода, не полностью поддерживаются браузерами. Кроме того, этот подход не решает некоторые глубокие проблемы отзывчивых изображений в целом.

Разделение стиля и содержания

CSS придумали специально для того, чтобы разделить стиль и содержание. В современном вебе HTML-страницы несут в себе всё содержание сайта, а таблицы стилей влияют только на представление этого содержания. Таблицы стилей не должны определять содержание сайта. Спору нет, принцип разделения стиля и содержания уже в некоторой степени нарушен внедрением CSS-свойств content-before и content-after, однако эти свойства обычно используются для улучшения представления (например, чтобы добавить к элементу иконку).

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

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

Поддержка масштабирования изображений в браузерах

Как было отмечено выше, улучшения, добавленные для масштабирования изображений, не будут работать в Internet Explorer 8 и старше. Соответствующие стандартам подходы, вроде использования srcset, возможно, совместимы со старыми версиями браузеров, тем не менее, как известно, сам srcset на данный момент не поддерживается ни одним из популярных браузеров.

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

Серьезная проблема контекста пользователя

Наверное, самой важной проблемой этого подхода является проблема, собственно, использования отзывчивых изображений. Мы определяем контекст пользователя исходя из ширины экрана и пиксельной плотности, однако трудно сказать всегда ли такой подход будет уместным. Представьте, например, что пользователь ноутбука подключается к интернету через точку доступа Wi-Fi на смартфоне.

Подключение

Браузер этого пользователя будет обладать всеми характеристиками широкоэкранного устройства с высокой пиксельной плотностью, и отзывчивый сайт будет загружаться с большими изображениями с высоким разрешением. Изображения похуже выглядели бы плохо на таком экране, но изображения хорошего качества через безпроводное соединение могут грузиться долго. Они могут значительно повлиять на длительность загрузки сайта, и в результате будут стоить нашему пользователю существенных денег за использование безпроводного подключения. Будь у него выбор, возможно, он предпочёл бы изображения с низким разрешением.

Оказывается, эту проблему трудно решить. Неглупые люди в интернет-сообществе уже вовсю её обсуждают, однако единая точка зрения насчёт практического решения ещё не сформирована. Определение контекста с помощью CSS пока остаётся лучшим подходом из доступных.

Благодарности

Большое спасибо Грейди Кунлайну за то, что он первым описал как можно с помощью стилей сделать изображения масштабируемыми с сохранением пропорций. Вебсайт contfont.net, который используется в этой статье в качестве примера можно найти на github.

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Stephen Thomas
Автор:
Stephen Thomas
Сайт:
http://sathomas.me/
Twitter:
@stephen_thomas
GitHub:
sathomas
Наталья Фадеева
Переводчик:
Наталья Фадеева
вКонтакте:
natatik_l
Twitter:
@very_busy_girl
GitHub:
NatalieF

Комментарии (5 комментариев, если быть точным)

Автар пользователя
pepelsbey

В 2013 году эта статья имела хоть какой-то смысл, публиковать её в 2015 просто вредно. Предлагать заменять <img> на <div role="img"> с фоновой картинкой, когда можно использовать <picture> с полифилом — это очень вредный совет.

Автар пользователя
SilentImp

Да, надо иметь в виду то, когда публиковалась статья. У нас есть несколько неопубликованных старых статей, которые интересны с той или иной точки зрения. Просто выбрасывать их не хочется. Так что я планирую все же пустить их на публикацию.

Автар пользователя
pepelsbey

@SilentImp, для этого есть редактор, который в начале статьи скажет:

Привет, читатель! Эта статья писалась тогда, когда ещё не было <picture>, поэтому прочитай и забудь, а вот тебе ссылка на статью про <picture>.

Скажи.

Автар пользователя
SilentImp

И скажу. Спасибо.

Автар пользователя
serzhei

Спасибо за статью, интересно role="img" aria-label="Кофе и круассан" в Сео будут восприниматься как обычная картинка?