Тринадцатый урок. Адаптивная верстка

Современная верстка обязательно должна быть адаптивной. Под этим словом обычно понимают возможность страницы адаптироваться под произвольную ширину экрана.

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

Техническая реализация адаптивности целиком ложится на CSS. За последние несколько лет верстальщиками были отработаны основные приемы адаптивной верстки. Возможно вы будете встречаться со старыми методиками, но мы будем рассматривать только новые проверенные.

Вначале кратко о проблеме разной ширины экранов.

Представим себе страницу, где две основных колонки: контент и сайдбар в пропорции 70/30%. Пусть общая ширина сайта 1000px, таким образом на широком экране, например десктопе контент будет 700px, сайдбар 300px.

При просмотре этого сайта через планшет в портретной ориентации, ширина экрана будет уже 768px. Исходя из пропорций конент займет уже 537px, то есть на 163px меньше. Сайдбар — 231px.

Пользователь телефона, у которого размер экрана 640px, увидит контент еще меньше — 448px, а сайдбар — всего 192px.

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

В адаптивной верстке задаётся поведение сетки. Для десктопа сохраняется базовая пропорция 70/30. Для планшета от 768px пропорция уже меняется, скажем 60/40 или вообще фисируется минимальная ширина сайдбара в 300px. Когда экран еще меньше, то пропорция становится 100/100, то есть контент и сайдбар будут располагаться друг под другом на всю ширину браузера.

70
30
60
40
100
100

Существуют и другие приёмы верстки. Например для телефона можно изменить размер текста или его выравнивание. Или меняется отступ от края блока.

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

Все эти вещи базируются на CSS свойствах @media, которые называются медиа-условия (медиа-правила). Вначале рассмотрим теорию, а после её реализацию в UniCSS.

Медиа-условия похожи на обычные css-классы, но на самом деле являются ограничивающим блоком, задающим css-классы в пределах своего условия.

@media условие {
	класс1 {}
	класс2 {}
	класс3 {}
}

Рассмотрим реальный пример:

@media (max-width: 640px) {
	.w50-phone { width: 50%; }
	.w100-phone { width: 100%; }
}

Условие max-width: 640px указывает на то, что оно будет выполнено для максимальной ширины экрана 640px (телефоны). Как только ширина браузера окажется в этом диапазоне, то браузер подключит классы w50-phone и w100-phone. Если же условие не соблюдается, то классов как будто бы и нет.

Сами условия можно комбинировать между собой. Например:

@media (max-width: 768px) and (min-width: 640px) {
	.w50-tablet { width: 50%; }
	.w100-tablet { width: 100%; }
}

В данном примере условие ограничивает экраном от 640px до 768px (планшет в портретной ориентации). Таким образом, если у блока задать:

<div class="w50-table w100-phone"></div>

то ширина этого блока для телефона будет 100%, а для планшета 50%, поскольку классы сработают только в пределах своих условий.

Существует два принципиально разных подхода к адаптивной верстки. Первый mobile first в котором базовая верстка — это верстка под самые малые экраны (телефоны), а медиа-условия подключают уже классы для более широких экранов. Второй подход — противоположный — desktop first — вначале обычные десктоп, а медиа-классы уже для уменьшенных экранов.

С практической точки зрения, да и с точки зрения повседневной логики, проще верстать desktop first. Но вы будете сталкиваться и с первым подходом, который реализован в различных CSS-фреймворках.

Технически между ними различие в объявлении и перекрытии css-стилей. Если например написать:

.my-block { color: red;  }
.my-block { color: blue; }

то при проверке div.my-block окажется с синим текстом, поскольку браузер берёт в расчёт только последнее объявление свойства. Происходит перекрытие стиля более поздним. Точно также работает и перекрытие в @media-блоках, но нам сейчас не важна техническая реализация: мы будем пользоваться готовыми классами UniCSS.

В UniCSS по умолчанию используются медиа-условия для phone (телефоны 640px) и tablet (планшет 768px), что обычно хватает для любых задач. Обычно медиа-условия нужны для классов ширины, некоторых свойств flex-сетки, размера и вывнивания текста, сброса отступов, а также специальные классы для показа и скрытия блоков (visible/hide). Классы для медиа-условий указываются с постфиксами -phone или -tablet.

На самом деле UniCSS можно настроить на любые медиа-условия и дополнительные точки. Эти возможности мы будем рассматривать когда речь пойдет о sass-компиляции.

Для проверки адаптивности используйте в FireFox режим мобильного просмотра Ctrl+Shift+M. Изменяя ширину, будет видно поведение блоков.

Первое, что обычно настраивается в адаптивном дизайне — это ширина flex-ячеек. Вначале настраивается вид на широком экране (desktop). Поскольку это обычное отображение, то для него не требуется каких-то особых классов. Вторым действием указываются классы для планшета шириной 768px. Здесь обычно нужно смотреть и подбирать визуально красивое поведение. И в конце-концов прописываются классы для телефонов. Из-за того, что это очень малые экраны, то обычно для блоков просто выставляется 100%-ширина. Особого дизайна здесь уже не сделаешь. Часто на телефонах применяют скрытие второстепенных блоков, особенно тех, которые в силу своих особенностей просто не могут корректно отображаться на малых экранах.

Рассмотрим простой пример адаптивной верстки. Пусть это будет два блока. На десктопе (то есть по умолчанию) это выглядит так:

<div class="flex t-white bg-teal700 pad10 flex-vcenter">
	<div class="w60 t150">Название сайта</div>
	<div class="w40 t-right">Иконки</div>
</div>
Название сайта
Иконки

Для планшета и телефона разместим блоки по отдельности один за одним. При этом применим выравнивание текста по центру. Для названия сайта увеличим размер текста.

<div class="flex t-white bg-teal700 pad10 flex-vcenter flex-wrap-tablet">
	<div class="w60 w100-tablet t150 t-center-tablet t200-tablet">Название сайта</div>
	<div class="w40 w100-tablet t-right t-center-tablet">Иконки</div>
</div>

Вот так это будет выглядеть на планшете и телефоне:

Название сайта
Иконки

Классы с постфиксом -tablet действуют только для ширины экрана менее 768px. Класс flex-wrap-tablet разрешает wrap-перенос для планшетов. Теоретически можно указать просто flex-wrap, но может возникнуть ситуация, когда размеры ячеек окажутся более 100% и тогда произойдет перенос, что для десктопа нежелателен. С -tablet мы избегает такой ситуации.

Постфикс -tablet действует и на телефоны (phone), поэтому если для телефонов классы будут такими же, то можно не использовать классы с -phone.

Как показывает опыт, поведение блоков для разных экранов подбирается уже по ходу, после верстки для десктопа. Иногда встречаются сложные задачи, где нужно так поменять вид блока, что выполнить его довольно сложно. В этом случае верстаюся две/три версии блока, один из которых показывается только для десктопа, а другой для планшета и/или телефона.

В UniCSS для этого применяются классы visible и hide.

<div class="hide-tablet-phone">desktop only</div>
<div class="b-hide visible-tablet">tablet only</div>
<div class="b-hide visible-phone">phone only</div>

Такие управляющие блоки видимости должны быть контейнерами для того, что следует скрывать. Класс b-hide просто скрывает любой блок: display: none. В своей работе старайтесь не использовать скрытие блоков, поскольку это не самая лучшая практика вёрстки.

Задания

Задания доступны только после авторизации.