22 August 2012

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

Website developmentDevelopment of mobile applications
Translation
Original author: Smashing Magazine: Reda Lemeden
После недавнего выпуска Retina MacBook Pro и The new IPad, экраны с увеличенной плотностью пикселей начали активно входить в нашу жизнь. Что это значит для веб-разработчиков?

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

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




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

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

CSS-пиксели




CSS-пиксели (CSS pixels) — абстрактная величина, используемая браузерами для точного отображения контента на страницах, вне зависимости от экрана (DIPs: device-independent pixels). Пример:
<div height="200" width="300"></div>

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


Соотношение между физическими и 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


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



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

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


Оптимизация


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

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


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


А таким на 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-дисплеев. Используется 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)


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



Вне зависимости от используемого метода растровые изображения по своей природе остаются ограниченными в масштабировании. Тут нам может помощь векторная графика. 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


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



Популярный благодаря 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-устройствах будет долгим. Можно сидеть и ждать его, а можно уже сейчас делать сайты, которые приятно посещать с любых устройств.
Tags:RetinaAppleвеб-дизайнвеб-графика
Hubs: Website development Development of mobile applications
+120
188k 1055
Comments 57
Top of the last 24 hours