C 2007 года очень быстро растёт количество используемых в мире смартфонов. В числе прочих причин резкого скачка популярности несколько лет назад покупателей привлекла способность этих устройств отображать сайты так, как они выглядели на экранах компьютеров. Но, купив смартфон и начав им пользоваться, люди отмечали, что для чтения отдельных блоков текста на относительно небольшом экране приходилось постоянно масштабировать страницу. Плюс к тому, многие элементы управления сайтов оказалось неудобно использовать. Это происходило потому, что страницы не были рассчитаны на управление с помощью прикосновений к экрану и зачастую требовали компьютерную мышь или другой манипулятор. Для решения этих проблем начали появляться отдельные версии сайтов, предназначенные исключительно для устройств с маленьким экраном. При этом пользователям оказалось не нужно знать адреса мобильных сайтов. Вместо этого сервер считывает информацию об устройстве из обращённого к нему запроса и определяет, какую версию предпочтительнее отдать посетителю.
Вскоре многим стало понятно, что разработка отдельной мобильной версии — это долго и дорого в поддержке. Кроме того, это противоречит идеологии веба, который подразумевает, что размеченный документ универсален и может быть прочитан практически на любом устройстве вывода. Для решения возникшего противоречия в CSS был добавлен стандарт Media Queries. Появились новые возможности по определению особенностей устройства, в частности появилась возможность применять различное оформление страницы для произвольных размеров окна.
Теперь посетители сайтов обладают множеством разных устройств, начиная с мобильных телефонов и заканчивая телевизорами. Удобная мобильная версия сайта позволяет достичь следующих преимуществ:
- Приоритетная позиция в мобильной выдаче поисковиков по сравнению с традиционными версиями сайтов.
- Увеличение прибыли сервиса за счёт повышения удобства использования интерфейса на любом устройстве.
Адаптивная вёрстка заключается в динамическом изменении CSS-стилей при различных размерах окна браузера. Часто учитывается именно ширина окна. Хороший пример адаптивной вёрстки можно увидеть на smashingmagazine.com, где страница адаптируется под пять интервалов окна браузера, каждый раз сохраняя максимальный комфорт для чтения.
Существует два подхода к реализации адаптивной вёрстки:
- От меньшего экрана к большему (progressive enchancement или mobile-first)
- От большего экрана к меньшему (graceful degradation)
Мы остановимся на втором подходе, когда у вас уже есть обычный сайт для настольного компьютера, который необходимо адаптировать под мобильные устройства.
Для проверки результатов нашей работы можно просто изменять размеры окна браузера. Но есть специально предназначенные для этого инструменты — например, эмуляция в инспекторе компонентов Chromium:
В качестве примера возьмём сайт Yandex Data Factory, демонстрирующий технологии автоматической модерации изображений, — imagemoderation.yandexdatafactory.com. Изначально он был свёрстан под большие экраны, но однажды потребовалась и мобильная версия. Давайте рассмотрим, какие у этого сайта были проблемы на мобильных устройствах и шаг за шагом устраним их.
1. Проблема: мелкие элементы управления и плохо различимый текст
Если открыть любой сайт для настольного компьютера на мобильном телефоне, сложно не обратить внимание на неудобный интерфейс с массой плохо различимых мелких элементов. Попав на такой сайт, человек сразу увеличивает масштаб страницы.
Давайте сразу зададим комфортный масштаб, для этого достаточно добавить один тег в <head>
:
<meta name="viewport" content="width=device-width,initial-scale=1" />
Мы изменили viewport браузера — видимую область страницы, размеры которой изменяются при масштабировании окна браузера. Мы поменяли ширину и первоначальный масштаб viewport.
Без мета-тега страница обрезалась по ширине стандартной величины viewport браузера:
После мы добавили мета-тег, устанавливающий ширину видимой области страницы в оптимальное значение, определённое производителем устройства:
Основные свойства мета-тега viewport:
width
— ширина видимой области. Рекомендуемое значение:device-width
.
Принимает натуральное число или ключевое словоdevice-width
, устанавливающее оптимальную ширину viewport для устройства. Таблицу значений по различным устройствам можно посмотреть на сайте mydevice.io/devices.height
— высота видимой области.
Работает аналогичноwidth
, только используется ключевое словоdevice-height
.initial-scale
— первоначальный масштаб страницы. Рекомендуемое значение:1
.
Принимает число от 1 до 5.minimum-scale
— минимальный масштаб страницы.
Принимает натуральное число, которое идеологически должно быть меньше или равнымinitial-scale
.
Значение1
запретит уменьшение масштаба страницы.maximum-scale
— максимальный масштаб страницы.
Принимает натуральное число, которое идеологически должно быть больше или равнымinitial-scale
.
Значение1
запретит увеличение масштаба страницы.user-scalable
— отключает или включает возможность масштабирования страницы.
Принимает значениеno
илиyes
. Масштабирование отключается также при указании одинаковых значенийminimum-scale
иmaximum-scale
.
В стандарте CSS есть черновик, описывающий специальное правило @viewport, которое на сегодняшний день почти не поддерживается браузерами. Мета-тег с аналогичной функциональностью был придуман в Apple и сегодня поддерживается всеми современными мобильными браузерами, поэтому на практике используем его.
2. Проблема: не все элементы помещаются на экране, появилась горизонтальная прокрутка
Теперь наша страница имеет комфортный масштаб, но некоторые элементы перестали помещаться на экране, из-за чего появляется горизонтальная прокрутка. Просматривать такой сайт неудобно.
Дело в том, что для мобильной вёрстки нельзя задавать элементам большую фиксированную ширину.
Лучше использовать свойство max-width
вместо width
:
.section__content {
max-width: 1200px; /* Вместо width: 1200px; */
}
Теперь содержимое растягивается по ширине экрана, а на большом экране компьютера ширина ограничена прежним значением.
3. Проблема: слишком крупный текст на мобильном экране
Текст на странице уже хорошо различим и полностью влезает в экран, но для комфортного восприятия информации осталось уменьшить шрифт заголовка. Рассмотрим два способа реализации.
3.1. Media Queries
Уменьшим размер шрифта заголовка с 72px
до 36px
для экранов, ширина которых меньше или равна 400px
, для этого воспользуемся следующим медиа-выражением:
@media all and (max-width: 400px) {
.header__title {
font-size: 36px;
}
}
.header__title {
font-size: 72px;
}
Используя эту тактику для других элементов на странице, можно добиться красивых результатов:
Синтаксис медиа-выражений:
Основные типы носителей:
all
— все типы, значение по умолчанию.screen
— экраны настольных компьютеров, планшетов и современных мобильных телефонов.print
— принтеры.speech
— речевые браузеры, которыми пользуются люди с ограниченными возможностями.
Наиболее часто используемые медиа-функции:
width (min-width, max-width)
— ширина окна браузера.min-width
означает, что стили будут применены при ширине, равной или большей указанной.max-width
означает, что стили будут применены при ширине не больше указанной.
height (min-height, max-height)
— высота окна браузера.device-width (min-device-width, max-device-width)
— ширина экрана устройства (может быть больше ширины браузера).device-height (min-device-height, max-device-height)
— высота экрана устройства.orientation
— принимает значенияlandscape
илиportrait
для определения альбомной и портретной ориентации соответственно.
При использовании медиа-выражений сразу возникает вопрос — какие интервалы ширин и высот использовать? К ответу на на него лучше подходить индивидуально по каждому элементу сайта, плавно изменяя размеры окна браузера. Когда вёрстка начнёт выглядеть неприемлемо, это и будет сигналом к необходимости использования медиа-выражений.
Медиа-выражения хорошо поддерживаются браузерами и предоставляют широкие возможности по определению параметров используемого устройства. Подробнее ознакомиться с ними можно в справочнике.
3.2. Media Queries + Rem
Есть другой приём, который позволит изменить размер шрифта на всей странице разом — это единица размера rem
(root em), которая похожа на em
, но вместо сложной цепочки зависимостей по родительским элементам, она вычисляется только на основе размера шрифта элемента <html>
.
Для удобства вычислений можно использовать базовый размер шрифта в 10px
. Таким образом, при изменении размера шрифта корневого элемента, пропорционально изменяются все размеры, указанные в rem
:
html {
font-size: 10px;
}
.header__title {
font-size: 7.2rem; /* 72px */
}
.header__sub-title {
font-size: 4.2rem; /* 42px */
}
@media all and (max-width: 400px) {
html {
font-size: 5px;
/*
.header__title → 36px
.header__sub-title → 21px
*/
}
}
Единица размера rem
хорошо поддерживается современными браузерами.
Такой подход менее гибок, чем указание размеров для каждого отдельного элемента, но зато с ним мы можем изменять размеры всех элементов одновременно.
4. Проблема: узкие элементы горизонтального списка
Сейчас наша страница неплохо выглядит на мобильном экране, но ещё есть над чем поработать. Горизонтальные списки, которые хорошо выглядят на экране настольного компьютера, становится неудобно читать на вертикальном экране мобильного устройства. Оптимальное решение — трансформировать горизонтальные списки в вертикальные. Давайте рассмотрим несколько способов сделать это.
4.1. Min-width
Добавив минимальную ширину для элемента списка, мы уже получим неплохой результат:
.item {
float: left;
width: 33%;
min-width: 265px; /* Добавляем минимальную ширину. */
}
Однако, у этого способа есть недостатки: элементы списка не растягиваются на всю доступную ширину и указание минимальной ширины может вызвать лишнюю горизонтальную полосу прокрутки.
4.2. Flexbox
Есть другое, более универсальное решение — раскладка с помощью Flexbox. Эта возможность CSS хорошо подходит, поскольку у нас есть отдельный компонент на странице, состоящий из контейнера и элементов:
.list {
display: flex; /* Flex-контейнер. */
flex-wrap: wrap; /* Многострочный режим. */
}
.item {
flex-basis: 260px; /* Базовая ширина элемента. */
flex-grow: 1; /* Элементы должны максимально растягиваться. */
max-width: 360px; /* Последний элемент не должен расползаться на всю ширину страницы в горизонтальной ориентации. */
}
В результате мы получим почти такой же результат, как с min-width
, но лишённый его недостатков: элементы списка растягиваются на всю доступную ширину (с ограничением до 360px
) и появление горизонтальной полосы прокрутки исключено.
Сейчас список уже выглядит достаточно хорошо, но есть ещё идея — расположить иконки каждого элемента слева от текста, так, чтобы они использовались в качестве маркеров. Важно, что такая раскладка должна быть только на мобильных экранах:
.item {
flex-basis: 260px;
flex-grow: 1;
max-width: 360px;
display: flex; /* Каждый элемент, в свою очередь, тоже становится Flex-контейнером. */
flex-direction: column; /* Для больших экранов сохраняем расположение иконки сверху. */
align-items: flex-start; /* Выравниваем иконку по левому краю. */
}
@media screen and (max-width: 400px) { /* Для мобильных экранов. */
.item {
flex-direction: row; /* Ставим иконку в один ряд с текстом. */
}
}
Flexbox может показаться сложным, но в действительности он открывает широчайшие возможности. Используя только CSS-стили, мы можем изменить порядок следования блоков! И наконец-то, в CSS можно легко задекларировать вертикальное центрирование.
Лучший способ разобраться с Flexbox — начать его использовать, а поможет в этом полное руководство и шпаргалка.
Покрытие поддержки Flexbox в современных браузерах достаточно хорошее, за исключением IE11, где есть баги реализации стандарта.
5. Проблема: фотографии некрасиво вписываются в экран
Финальный штрих — немного поработаем с графикой. Красивые изображения на сайте — это очень здорово, но если у нас есть фотографии, которые неудобно смотреть, весь эффект пропадает.
Так на мобильном экране будет выглядеть большая картинка без каких-либо стилей:
Благодаря новой единице размера vh
(viewport height) мы можем легко установить высоту картинки, равную высоте экрана:
Теперь давайте впишем картинку в экран по ширине:
Из-за ограничения максимальной ширины изображение исказилось, сплющившись по ширине. Это можно исправить с помощью нового свойства object-fit
:
В итоге красиво вписать картинку в мобильный экран можно всего тремя свойствами:
.image {
height: 100vh; /* Устанавливаем высоту картинки, равную высоте экрана. */
max-width: 100%; /* Ограничиваем ширину картинки шириной экрана. */
object-fit: cover; /* Масштабируем картинку с соблюдением пропорций. */
}
Новые единицы размеров в CSS:
vw
— 1% от ширины viewport.vh
— 1% от высоты viewport.vmin
— 1% от меньшей стороны (ширины или высоты) viewport.vmax
— 1% от большей стороны (ширины или высоты) viewport.
Наконец-то, в CSS можно легко указывать относительные вертикальные размеры! Поддержка современными браузерами достаточно хорошая, за исключением IE11 и Edge14, где не работает vmax
.
Свойство object-fit позволяет легко управлять масштабом и соотношением сторон изображений, но при этом обязательно должны быть заданы как ширина, так и высота. Можно сказать, что это свойство является неким аналогом свойства background-size, только для обычных изображений, а не фоновых. Поддержка современными браузерами также на высоте, за исключением IE11 и Edge13.
Заключение и полезные ссылки
Мы рассмотрели ряд практических техник, которые помогут быстро сделать обычный сайт адаптивным под любые размеры экрана. Адаптивная вёрстка — это удобно, как для пользователя, так и для разработчика, который со временем станет смотреть на дизайн сразу с точки зрения экранов различных размеров. Такой подход лёгок в поддержке и выглядит достойно даже в сравнении с отдельной мобильной версией.
Существует ряд инструментов, облегчающих задачу построения адаптивных раскладок. Они вводят единые соглашения написания кода, что может быть полезно в средних и больших командах. Наиболее популярные из них:
- Bootstrap — пожалуй, самый известный CSS-фреймворк.
- Foundation — мощный CSS-фреймворк для сайтов, писем и веб-приложений.
- Skeleton — минималистичный CSS-фреймворк с фиксированными сетками.
- Jeet — система сеток для SCSS и Stylus.
- Susy — система сеток для SASS.
- Fluidable — система сеток для LESS.
Автор: Яндекс