На главную

Таргетинг стилей по устройству

.some-block {
    z-index: 1;
    position: relative;
    
    @include device(desktop, ie, tablet) {
        @include section(portfolio) {
            border: 1px solid #000;
            }
        }
    }

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

Публикация от . Крайнее обновление .

Принцип

Когда речь заходит об адаптации сайта, то, «То что можно сделать на сервере, то нужно делать на сервере».

А клиенту нужно отдать то, что ему может понадобиться, и не отдавать ему то, что точно не понадобится.

То есть, совсем незачем отдавать на desktop стили с указанием @media screen and (orientation : portrait) {…}, а мобильным устройствам совсем не нужно знать о ваших костылях для Internet Explorer.

Стремитесь к тому, чтобы таргетинг был максимальным, но разумным. Выносите в отдельные CSS-файлы стили с чётким делением по какому-либо признаку, например, по типу устройства.

«Выносить в отдельные CSS-файлы» — не значит держать/хранить код в отдельном файле, наоборот, стили для одной сущности нужно держать в одном месте, в одном файле, но в итоге, при генерации, у вас должны получиться файлы со стилями для определённого устройства в отдельном файле.

Есть мнение, что детектировать нужно не устройства, а фичи. А моё мнение таково, зная браузер клиента, нам уже нет смысла производить 99% проверок.

Будем руководствоваться основополагающим принципом:
«За один сеанс устройство изменить/сменить нельзя, а viewport можно».

Это означает, что при ответе на запрос, клиенту нужно отдать документы (разметку, стили, JS), а может и данные, соответствующие именно его устройству. Зачем? Я не сторонник отдавать клиенту «полный фарш», и после изменять его при помощи JS и CSS media query на клиенте. Нет, изменять можно, конечно, но лучще это делать как можно меньше.

Поклонники Modernizr скажите, на самом деле все используемые вами проверки реализуются только на клиенте?

Я практикую деление устройств на следующие типы:

  • desktop / стационарные ПК, ноутбуки
  • ie / Internet Explorer
  • tablet / планшеты
  • phone / смартфоны

Да-да, стили для IE я выношу в отдельные CSS-файлы. Уж слишком много отличий у данного творения от других броузеров: Flexible Box, classList, Promises, Srcset и т.д.

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

Реализация

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

в которой весь код относящийся к конкретной сущности, находится в одном файле, вне зависимости от деления на устройства, для которых он предназначен.

Для распарсивания UserAgent на Ruby я рекомендую использовать Device Detector for Ruby . Пользователи PHP могут обратить внимание на Device Detector for PHP.

Для многих актуален вопрос использования Ruby-переменных в Scss/Sass. Сам Chris Eppstein предлагает решение из разряда «дайте воды попить, аж переночевать не с кем негде» .

Передать переменную из Ruby в Scss можно намного проще. Заводим для этих целей отдельный файл, скажем, vars/dynamic.scss. Далее подключаем данный файл в общие таблицы стилей.

@import "vars/dynamic.scss";

И самое главное, попросите ваше Ruby-приложение записать значения необходимых переменных в ваш Scss-файл.

def dynamicVars( device, section )
    path = '/vars/dynamic.scss'
    string = "$device: #{device}; $section: #{section};"

    File.write(path, string)
end

dynamicVars( $device, $section )

Для удобства использования, в Scss создан mixin, который добавляет код по определённому признаку.

@mixin device($collection...) {
    @each $item in $collection {
        @if $item == $device {
            @content;
            }
        }
    }

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

.some-block {
    z-index: 1;
    position: relative;
    
    @include device(desktop, ie, tablet) {
        @include section(portfolio) {
            border: 1px solid #000;
            }
        }
    }

Классы на <html>

Помните, Paul Irish рекомендовал использовать классы на <html> для таргетинга стилей?

<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]>    <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->

Я предлагаю использовать данную модификацию по радителю, как способ более точечной кастомизации.

Например, есть стили для Android, но вам необходимо модифицировать стили для Android v.4.2.2. В контексте описанного примера метод модификации через классы на элементе <html> очень жизнеспособен.

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

.some-block {
    width: 60vw;
    text-align: center;

    .__android-422 & {
        width: 60%;
        }
    }

Определить имя и версию операционной системы пользователя вам поможет уже упомянутая библиотека Device Detector.

Быстрых сайтов вам и вашим пользователям!