Page Content
Сайты нужно делать адаптивными, а для этого хорошо бы уметь управлять содержимым и представлением сайта в зависимости от типа устройства пользователя.
Публикация от ⁠. Крайнее обновление ⁠.
Принцип
Когда речь заходит об адаптации сайта⁠, то, «⁠То что можно сделать на сервере⁠, то нужно делать на сервере⁠». А клиенту нужно отдать то⁠, что ему может понадобиться, и не отдавать ему то⁠, что точно не понадобится⁠.
То есть⁠, совсем незачем отдавать на desktop
стили с указанием @media screen and (orientation : portrait)
⁠, а мобильным устройствам совсем не нужно знать о ваших «костылях» для Internet Explorer.
Стремитесь к тому⁠, чтобы таргетинг был максимальным⁠, но разумным⁠. Выносите в отдельные CSS-файлы стили с чётким делением по какому-либо признаку, например, по типу устройства.
«Выносить в отдельные CSS-файлы⁠» — не значит держать/хранить код в отдельном файле⁠, наоборот, стили для одной сущности нужно держать в одном месте⁠, в одном файле⁠, но в итоге⁠, при генерации⁠, у вас должны получиться файлы со стилями для определённого устройства в отдельном файле⁠.
Есть мнение⁠, что детектировать нужно не устройства⁠, а фичи⁠. А моё мнение таково, зная браузер клиента, нам уже нет смысла производить 99% проверок⁠.
Будем руководствоваться основополагающим принципом: «⁠За один сеанс устройство изменить/сменить нельзя, а viewport — можно».
Это означает⁠, что при ответе на запрос⁠, клиенту нужно отдать документы (разметку, стили, JS), а может и данные⁠, соответствующие именно его устройству⁠. Зачем? Я не сторонник отдавать клиенту «⁠полный фарш⁠», и после изменять его при помощи JS и CSS media query на клиенте⁠. Нет, изменять можно, конечно, но лучше это делать как можно меньше⁠.
Поклонники Modernizr скажите, на самом деле все используемые вами проверки реализуются только на клиенте⁠?
Я практикую деление устройств на следующие типы⁠:
- desktop / стационарные ПК⁠, ноутбуки;
- tablet / планшеты;
- phone / смартфоны;
- ie / Internet Explorer.
Да-да⁠, стили для IE я выношу в отдельные CSS-файлы⁠. Уж слишком много отличий у данного творения от других броузеров: Flexible Box⁠, classList, Promises, Srcset и т.д. На практике нам необходимо иметь в шаблонах и стилях переменную, например, со значением устройства.
Реализация
Все просто⁠, определяем тип устройства на сервере и прокидываем значение типа в переменную в шаблонах и стилях⁠. Таким образом мы получаем структуру, в которой весь код относящийся к конкретной сущности, находится в одном файле⁠, вне зависимости от деления на устройства⁠, для которых он предназначен⁠.
Для распарсивания UserAgent на Ruby я рекомендую использовать Device Detector for Ruby⁠.
Передать переменную из Ruby в Scss можно не обладая глубокими знаниями Ruby⁠. Создаём отдельный файл 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. Быстрых сайтов вам и вашим пользователям!
Update
Более корректная передача переменной между Ruby и Sass⁠. Спасибо, Макс⁠!
require 'sass'
require 'sass/plugin'
# Sass module extension
module Sass::Script::Functions
# SASS-method - device type
def device
Sass::Script::Value::String.new(Sass::Plugin.options[:custom][:device])
end
declare :get_device []
end