...

вторник, 1 октября 2013 г.

Делаем css-спрайты отзывчивее на retina-дисплеях и не только [less]

image

Зачем нам вообще нужны спрайты?




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


  • Во-первых, используя спрайты, мы ускоряем загрузку страницы; в случае использования иконок, можно создать универсальное средство для применения в проектах;

  • Во-вторых, не все устройства с высоким ppi (например, Windows Phone 7.5-7.8, Android до 4 версии на стоковом браузере) поддерживают использование webfonts.

  • Легкая интеграция, используя специальные сервисы генерации спрайтов




Постановка проблемы или чтобы жизнь малиной не казалась




Используя css-спрайты со множеством элементов встает проблема о создании css-свойств с background-position; Их нужно писать много, иногда очень много. Конечно, нам помогают многие сервисы по генерации спрайтов — они выдают вместе со спрайтом еще и css/less/sass — файл с координатами. Но практически всегда все жестко завязано на пикселях:


  • Изменяя размер (например, для retina-экранов) исходного файла-спрайта все «едет»;

  • Мы не можем изменять размер элемента-контейнера, куда хотим вставить, допустим, иконку, чтобы эта иконка смасштабировалась: свойства background-size: cover/contain/100% не работают по понятным причинам;




Используя спрайты, подготовленные для 72ppi, на телефонах, планшетах и новых retina-ноутбуках вызывает размытие изображений, и выглядят некрасиво...



Дисклеймер о кроссбраузерности, кроссплатформенности и кросс-чего-нибудь-еще-сти

Использовать css3 в данном методе мы будем только для дисплеев с ppi, выше стандартных 72. Подобные дисплеи появились сравнительно недавно, и никакие IE 7.0- IE8.0 и им подобные старые версии Firefox или Opera там стоять не будут. С мобильным сегментом тоже все в порядке, поддержка media запросов реализована везде.

Приступим к формированию less-сниппета




Сразу замечу, что использовать less на рабочем проекте никто не заставляет, все можно скомпилировать в обычный css. Для mac подобных программ куча, для windows будет полезна программа WinLess.

Сейчас я рассматривать буду частный случай спрайта — спрайт с иконками, сгенерированный замечательным ресурсом icomoon.io

Чтобы мы делали с помощью простого css, если б нужно было настроить под ретину спрайт? Скорее всего, мы бы отказались от использовали спрайт с высоким разрешением. Возможно, подключали бы его только для устройств с высоким ppi.

Но здесь мы столкнемся с проблемой масштабирования этого спрайта под подходящий нам размер. А это, кроме как transform: scale(x); просто так не решить, и придется перерисовывать спрайт, переписывать все background-position. И все бы ничего, но иногда количество иконок зашкаливает, да и вообще хотелось бы универсальное решение.


Их есть у меня




Итак, приступим:


  • Первое, что нам нужно — это сгенерировать 2 спрайта (можно 3, если хотим охватить 400+ ppi) и css-код к ним. Делается это легко через приведенный мною выше сервис. Я сгенерировал 145 иконок, размеров 16px (25kb), 32px (62kb) и 64px (163kb)

    Изначально, прилагаемый css-файл для 16px-иконок выглядит так: (я намеренно сократил его до четырех иконок, чтобы не пугать огромными простынями кода)

    .icon-rss,.icon-e-mail,.icon-youtube,.icon-mailru {
    display: inline-block;
    width: 16px;
    height: 16px;
    background-image: url(sprites.png);
    background-repeat: no-repeat;
    }
    .icon-rss {
    background-position: 0 0;
    }
    .icon-e-mail {
    background-position: -32px 0;
    }
    .icon-youtube {
    background-position: -64px 0;
    }
    .icon-mailru {
    background-position: -96px 0;
    }




  • Затем узнаем размер картинки-спрайта. Для 16px-иконок он составил 496px. Это значение будет опорным для нашего less-кода. Теперь стоит добавить строчку background-size: 496px;

  • Теперь мы должны избавиться от единиц измерения во всем этом css-спрайте, заменив "px" на переменную, по-умолчанию равную 1px. Пусть она будет называться size. Делается это легко автозаменой. Попутно не забываем переименовать файл в расширение less и заинклудить к главному less-файлу вашего проекта:

    @size: 1px;
    .icon-rss,.icon-e-mail,.icon-youtube,.icon-mailru {
    display: inline-block;
    width: 16*(@size);
    height: 16*(@size);
    background-image: url(sprites.png);
    background-repeat: no-repeat;
    background-size:496*(@size);
    }
    .icon-rss {
    background-position: 0 0;
    }
    .icon-e-mail {
    background-position: -32*(@size) 0;
    }
    .icon-youtube {
    background-position: -64*(@size) 0;
    }
    .icon-mailru {
    background-position: -96*(@size) 0;
    }


  • Важно отметить, что мы не можем просто так добавлять получившиеся миксины к тегам — у нас указана ширина и высота в классах, а значит мы будем добавлять их к псевдоэлементам ::before или ::after

  • @media запросы less поддерживает в любом месте кода: в зависимости от плотности пикселей будем подключать тот или иной файл.

    @size: 1px;
    .icon-rss,.icon-e-mail,.icon-youtube,.icon-mailru {
    display: inline-block;
    width: 16*(@size);
    height: 16*(@size);
    background-image: url(sprites.png);
    @media
    only screen and (-webkit-min-device-pixel-ratio: 2),
    only screen and ( min--moz-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) {
    background-image: url(sprites32.png);
    }
    @media
    only screen and (-webkit-min-device-pixel-ratio: 4),
    only screen and ( min--moz-device-pixel-ratio: 4),
    only screen and ( -o-min-device-pixel-ratio: 4/1),
    only screen and ( min-device-pixel-ratio: 4),
    only screen and ( min-resolution: 360dpi),
    only screen and ( min-resolution: 4dppx) {
    background-image: url(sprites64.png);
    }
    background-repeat: no-repeat;
    background-size:496*(@size);
    }
    .icon-rss {
    background-position: 0 0;
    }
    .icon-e-mail {
    background-position: -32*(@size) 0;
    }
    .icon-youtube {
    background-position: -64*(@size) 0;
    }
    .icon-mailru {
    background-position: -96*(@size) 0;
    }





Комментарии для применения на практике





  1. Вам не обязательно генерировать через программу-генератор сразу три разных спрайта. Вы можете сгенерировать один (для очень-retina экранов), получить драгоценный css-файл, а затем через графический редактор сделать уменьшенную версию спрайта для обычных устройств (не retina).

  2. В своих проектах я не использую "px". Вместо этого, я переменной size присваиваю значение в единицах измерения "rem". Это дает свободу изменения размеров иконок до необходимого, а в случае, если мы открываем сайт с планшета, эти самые rem становятся чуть больше, т.к. я задаю чуть больший размер шрифта для планшетов, например:

    @media (min-width: 768px) and (max-width: 1366px) {
    html {font-size: 120%;}
    }



Когда стоит использовать данную технику





  • Для возможности подгружать спрайты разного качества для retina/не-retina экранов;

  • Когда предполагается возможное изменение размера иконки при разработке проекта;

  • Когда стоит адаптировать исходный спрайт при создании мобильной версии сайта;

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


P.S.: Об орфографических, синтаксических и лексических ошибках просьба писать в ЛС.

P.P.S.: Данный материал не претендует на добавление в палату мер и весов, и используемые примеры не совершенны. Гуру-less/sass в этом посте не найдет ничего особенного, а вот новичкам будет полезно.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



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

Отправить комментарий