Оптимизация графики для Retina-экранов

в 19:11, , рубрики: apple, веб-дизайн, Веб-разработка, Мобильный веб

После недавнего выпуска Retina MacBook Pro и The new IPad, экраны с увеличенной плотностью пикселей начали активно входить в нашу жизнь. Что это значит для веб-разработчиков?

Для начала разберемся в терминологии.

Физические пиксели

Оптимизация графики для Retina экранов

Физические пиксели (device pixel или physical pixel) — привычные нам пиксели: самые маленькие элементы любого дисплея, каждый из которых имеет свой цвет и яркость.

Плотность экрана (Screen density) — это количество физических пикселей дисплея. Обычно измеряется в пикселях-на-дюйм (PPI: pixels per inch). Apple, разработав Retina-экраны с двойной плотностью пикселей, утверждает, что человеческий глаз не способен различить бо′льшую плотность.

CSS-пиксели

Оптимизация графики для Retina экранов

CSS-пиксели (CSS pixels) — абстрактная величина, используемая браузерами для точного отображения контента на страницах, вне зависимости от экрана (DIPs: device-independent pixels). Пример:

<div height="200" width="300"></div>

Такой блок на обычных экранах будет занимать область 200x300 пикселей, а на Retina-экранах тот же блок получит 400x600 пикселей.Таким образом, на Retina-экранах плотность пикселей в 4 раза больше, чем на обычных:
Оптимизация графики для Retina экранов

Соотношение между физическими и CSS-пикселями можно устанавливать так:

        device-pixel-ratio,
     -o-device-pixel-ratio,
   -moz-device-pixel-ratio,
-Webkit-device-pixel-ratio {
…
}

Или так:

            device-pixel-ratio,
     -o-min-device-pixel-ratio,
   min--moz-device-pixel-ratio,
-Webkit-min-device-pixel-ratio {
…
}

В Javascript добиться этого можно, используя

window.devicePixelRatio

Растровые пиксели

Оптимизация графики для Retina экранов
Растровые пиксели (bitmap pixels) — самые маленькие части, составляющие растровое изображение (PNG, JPF, GIF и т.д.) Каждый пиксель содержит информацию, о цвете и расположении в системе координат изображения. В некоторых форматах пиксель может содержать дополнительную информацию, например, прозрачность.

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

Оптимизация

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

HTML и CSS-масштабирование

Самый простой способ подготовить графику к Retina-дисплею — это просто разделить пополам физические размеры изображения. Например, чтобы показать фотографию 200x300 пикселей на экране с увеличенной плотностью пикселов, необходимо загрузить фото размером 400x600 пикселей и уменьшить его, используя CSS-аттрибуты или HTML-параметры. Таким будет отображение на обычном экране:
Оптимизация графики для Retina экранов

А таким на Retina:
Оптимизация графики для Retina экранов

Есть несколько способов реализации HTML и CSS-масштабирования:

HTML

Самый простой способ — просто задать параметры width и height тегу img:


<img src="example@2x.png" width="200" height="300" />

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

Javascript

Такого же результата можно добиться, используя Javascript для того, чтобы делить пополам размеры изображений для Retina-экранов. С использованием библиотеки jQuery это выглядит так:

$(window).load(function() {
  var images = $('img');
    images.each(function(i) {
      $(this).width($(this).width() / 2);
    });
});

Где использовать: на сайтах с несколькими изображениями в контенте.

CSS (SCSS)

Также можно использовать изображение в качестве фона с необходимыми размерами (background-size) определенного div'а. Параметр background-size не поддерживается в IE 7 и 8.

.image {
  background-image: url(example@2x.png);
  background-size: 200px 300px;
  /* Alternatively background-size: contain; */
  height: 300px;
  width: 200px;
}

Можно использовать псевдоэлементы :before или :after

.image-container:before {
  background-image: url(example@2x.png);
  background-size: 200px 300px;
  content:'';
  display: block;
  height: 300px;
  width: 200px;
}

Техника работает и при использовании спрайтов:

.icon {
  background-image: url(example@2x.png);
  background-size: 200px 300px;
  height: 25px;
  width: 25px;

  &.trash {
    background-position: 25px 0;
  }

  &.edit {
    background-position: 25px 25px;
  }
}

Где использовать: на сайтах с ограниченным количеством фоновых изображений (например одним в качестве спрайта).

HTML и CSS-масштабирование: плюсы

  • Простота реализации
  • Кроссбраузерность

HTML и CSS-масштабирование: минусы

  • Устройства и обычными экранами будут скачивать лишние мегабайты
  • На обычных экранах четкость изображений может пострадать из-за алгоритмов сжатия
  • Параметр background-size не поддерживается в IE 7 и 8.

Определение плотности пикселей экрана

Оптимизация графики для Retina экранов
Возможно это самый популярный способ оптимизации графики для Retina-дисплеев. Используется CSS или Javascript.

CSS

В этом способе используется device-pixel-ratio, чтобы установить нужное соотношение между физическими и CSS-пикселями:

.icon {
  background-image: url(example.png);
  background-size: 200px 300px;
  height: 300px;
  width: 200px;
}

@media only screen and (-Webkit-min-device-pixel-ratio: 1.5),
only screen and (-moz-min-device-pixel-ratio: 1.5),
only screen and (-o-min-device-pixel-ratio: 3/2),
only screen and (min-device-pixel-ratio: 1.5) {
  .icon {
    background-image: url(example@2x.png);
  }
}

Где использовать: на сайтах или в приложениях, в которых применяется background-image для элементов дизайна. Не подходит для изображений внутри контента.

Плюсы

  • Устройства не скачивают лишние изображения
  • Кроссбраузерность
  • Контроль плотности пикселей на сайте

Минусы

  • Утомительно внедрять, особенно на крупных сайтах
  • Использование изображения контента в качестве фона семантически некорректно

Javascript

Того же результата можно добиться, используя window.devicePixelRatio:

$(document).ready(function(){
  if (window.devicePixelRatio > 1) {
    var lowresImages = $('img');

    images.each(function(i) {
      var lowres = $(this).attr('src');
      var highres = lowres.replace(".", "@2x.");
      $(this).attr('src', highres);
    });
  }
});

Существует специальный Javascript плагин Retina.js, который умеет делать все вышеописанное, но с дополнительными возможностями, такими как пропуск внешних изображений и пропуск внутренних, но не имеющих retina-копий.

Где использовать: на любых сайтах с изображениями в контенте.

Плюсы

  • Простота внедрения
  • Устройства не скачивают лишние изображения
  • Контроль плотности пикселей на сайте

Минусы

  • Retina-устройства скачивают оба варианта каждого изображения
  • Подмена изображений заметна на retina-устройствах
  • Не работает в некоторых популярных браузерах (IE и Firefox)

Масштабируемая векторная графика

Оптимизация графики для Retina экранов
Вне зависимости от используемого метода растровые изображения по своей природе остаются ограниченными в масштабировании. Тут нам может помощь векторная графика. SVG (Scalable Vector Graphics) формат на основе XML поддерживается большинством браузеров. Самый простой способ использования SVG-изображений — в теге img или CSS-параметрами background-image и content:url().

В этом примере простое SVG-изображение может быть как угодно масштабировано:


<img src="example.svg" width="200" height="300" />

То же самое получится с применением CSS:

/* Использование фонового изображения */

.image {
  background-image: url(example.svg);
  background-size: 200px 300px;
  height: 200px;
  width: 300px;
}

/* Использование content:url() */

.image-container:before {
  content: url(example.svg);
  /* width and height do not work with content:url() */
}

Для поддержки IE 7 или 8 и Android 2.x потребуется использование заменяющих PNG-изображений. Это можно легко сделать с помощью Modernizr:

.image {
  background-image: url(example.png);
  background-size: 200px 300px;
}

.svg {
  .image {
    background-image: url(example.svg);
  }
}

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

В HTML можно реализовать аналогичное с помощью нужного data в теге a:


<img src="example.svg" data-png-fallback="example.png" />

С использованием jQuery и Modernizr:

$(document).ready(function(){
  if(!Modernizr.svg) {
    var images = $('img[data-png-fallback]');
    images.each(function(i) {
      $(this).attr('src', $(this).data('png-fallback'));
    });
  }
});

Где использовать: на любых сайтах, подходит для иконок, логотипов и простых векторных иллюстраций.

Плюсы

  • Единый набор изображений для всех устройств
  • Простота реализации
  • Бесконечное масштабирование

Минусы

  • Нет точного сглаживания «до пикселя»
  • Не подходит для сложной графики из-за больших размеров файла
  • Нет встроенной поддержки в IE 7, 8 и в ранних версиях Android

Иконочные шрифты

Оптимизация графики для Retina экранов
Популярный благодаря Twitter Botstrap способ, заключается в замене букв в шрифте на нужные символы с последующим их отображением на странице с помощью CSS. Существует множество иконочных шрифтов с символами на любой вкус, но можно также создать свой с помощью Fontello, Font Builder или даже Inkscape.

Наиболее распространенный способ использования иконочных шрифтов — это применение нужного класса к определенному элементу страницы:


<span class="icon">a</span>

А в стилях указывается нужный шрифт:

.icon {
  font-family: 'My Icon Font';
}

Таже можно использовать псевдоэлемент :before и параметр content с уникальным классом к каждой иконке:


<span class="glyph-heart"></span>
[class^="glyph-"]:before {
  font-family: 'My Icon Font';
}

.glyph-heart:before {
  content: 'h';
}

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

Плюсы

  • Бесконечное масштабирование
  • Кроссбраузерность
  • Более универсальное решение, чем набор графических элементов

Минусы

  • Нет точного сглаживания «до пикселя»
  • Сложность реализации: отдельный символ шрифта к каждой иконке
  • Способ основан на семантически некорректной разметке

Favicon

Favicon'ки все чаще используется вне браузера в качестве графического представления сайта или приложения. Чтобы оптимизировать favicon для Retina-устройств, необходимо подготовить .ico в двух размерах: 16x16 и 32x32 пикселей.

Взгляд в будущее

Существует специальный -Webkit-image-set от Apple, представленный весной, который позволяет использовать несколько вариантов одного изображения в CSS:

.image {
  background-image: -Webkit-image-set(url(example.png) 1x, url(example@2x.png) 2x);
  background-size: 200px 300px;
}

Но этот способ не распространяется на изображения внутри тега img.

Еще одно инструмент — Picturefill, автор Scott Jehl. Это HTML и Javascript решение:


<div data-picture>
     <div data-src="example.png"></div>
     <div data-src="example@2x.png" data-media="(min-device-pixel-ratio: 1.5)"></div>

  <!-- Fallback content for non-JS browsers -->
  <noscript>
    <img src="example.png" >
  </noscript>
</div>

Несмотря на такую разметку, это вполне нормальное кроссбраузерное решение.

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

Заключение

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

Автор: grokru

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js