Несколько дней новогоднего волшебства:
Успейте начать обучение в 2018-ом году со скидкой до 30%!
Выбрать курс

Про retina и @media

JS_Deep_6.07_Site.png

Retina — это зарегистрированный компанией Apple товарный знак. Под эти знаком выпускаются дисплеи (включая дисплеи мобильных устройств) с очень высоким разрешением экрана и маленьким размером пикселей. Сейчас это название «приклеилось» просто ко всем таким дисплеям.

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

Логические пиксели, это как раз те пиксели, которые фигурируют в разметке, и они не обязаны совпадать с физическими, которые их будут отображать. На классических Retina-дисплеях каждому логическому пикселю соответствует квадрат 2x2 физических пикселей.

Таким образом, данный блок:

.some-block {
  width: 100px;
  height: 100px;
}

на обычных дисплеях будет иметь размер 100x100 физических пикселей, а на экранах Retina — 200x200 пикселей.

А вот теперь начинаются проблемы

Особенно, если это не просто блок, а картинка, и причём растровая:

.some-image {
  background: url(http://via.placeholder.com/100x100) 100px 100px;
  width: 100px;
  height: 100px;
}

Данная картинка будет иметь размер 100x100 физических пикселей на обычных дисплеях, и целых 200x200 физических пикселей при разрешении всего 100x100. Такие изображения будут «размытыми». Предположим, что мы поставили разрешение 200x200:

.some-image {
  background: url(http://via.placeholder.com/200x200) 100px 100px;
  width: 100px;
  height: 100px;
}

Да, теперь на Retina-экранах картинка выглядит превосходно, но при открытии на обычных устройствах мы будем загружать ненужные данные. И что же делать?

Выход есть — @media-запросы!

.some-image {
  background: url(http://via.placeholder.com/100x100) 100px 100px;
  width: 100px;
  height: 100px;
}

@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
  .some-image {
    background: url(http://via.placeholder.com/200x200) 100px 100px;
  }
}

Оставим читателям вопрос, почему здесь фигурируют dpi. Но это запрос работает для Retina-устройств. И данный сайт прекрасно будет смотреться и достаточно быстро загружаться.

Что ещё?

Существуют также устройства с промежуточным количеством пикселей на один логический. Более того, этому помогают опции масштабирования как в самом браузере, так и операционной системе. Поэтому правильный работающий @media-query выглядит немного иначе:

@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) {

или даже так

@media (-webkit-min-device-pixel-ratio: 1.25), (min-resolution: 120dpi) {

Заключение

Собственно, всех этих штук вполне достаточно для красивого отображения сайта на подобных устройствах. Ну и с использованием CSS-препроцессоров этот @media-query можно вынести в константу и код выглядит уже не таким страшным.

Например, с less всё будет выглядеть таким образом:

@retina: ~"only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi)";

.some-image {
  background: url(http://via.placeholder.com/100x100) 100px 100px;
  width: 100px;
  height: 100px;

  @media @retina {
    background: url(http://via.placeholder.com/200x200) 100px 100px;
  }
}

Есть вопрос? Напишите в комментариях!

Автор
1 комментарий
1

Использую в scss такой миксин:

@mixin retina($density: 2) {
  @media only screen and (-webkit-min-device-pixel-ratio: $density),
  only screen and (min--moz-device-pixel-ratio: $density),
  only screen and (-o-min-device-pixel-ratio: #{$density}/1),
  only screen and (min-device-pixel-ratio: $density),
  only screen and (min-resolution: 192dpi),
  only screen and (min-resolution: $density dppx) {
    @content;
  }
}
body {
    background-image: url(./img/bg.jpg);
    @include retina {
        background-image: url(./img/bg@2x.jpg);
    }
}
Для комментирования необходимо авторизоваться