Адаптивный и отзывчивый дизайн
Разработчику
Аналитику
Тестировщику
Архитектору
Инженеру
Что такое адаптивность
Основы
Адаптивность — это способность веб-страницы автоматически подстраиваться под размер экрана устройства, на котором её открывают.
Когда вы заходите на один и тот же сайт с телефона, планшета и компьютера, он выглядит по-разному, потому что его макет адаптируется. Отсюда и адаптивность.
Цель адаптивности — обеспечить удобство использования независимо от устройства:
- текст читаем без увеличения;
- кнопки легко нажимать пальцем;
- изображения не выходят за границы экрана;
- контент не требует горизонтальной прокрутки.
Как можно понять, поскольку браузер находится на конечном устройстве клиента, можно добавить в клиентский код указание определённого поведения, в зависимости от типа устройства.
Адаптивность достигается за счёт трёх основных механизмов:
- Метатег
viewport— сообщает браузеру, как масштабировать страницу на мобильных устройствах. - Медиа-запросы (
@media) — позволяют применять разные стили при разных ширинах экрана. - Относительные единицы измерения — делают элементы гибкими, а не фиксированными в пикселях.
Эти инструменты работают вместе. Без viewport медиа-запросы не сработают корректно. Без относительных единиц макет будет «ломаться» при изменении размера.
Ключевые понятия
Метатег viewport
На мобильных устройствах браузеры по умолчанию показывают страницу так, будто она открыта на компьютере, а затем уменьшают её, чтобы уместить целиком. Это приводит к мелкому тексту и необходимости масштабировать страницу.
Метатег viewport отключает это поведение:
<meta name="viewport" content="width=device-width, initial-scale=1">
width=device-width— делает ширину области просмотра равной ширине экрана устройства.initial-scale=1— отключает начальное масштабирование.
Этот тег обязателен в каждом современном HTML-документе.
Details
Что такое viewport?
Viewport — это видимая область браузера, в которой отображается веб-страница. На мобильных устройствах она отличается от физического размера экрана, если не задан метатег.Относительные единицы измерения
Фиксированные значения вроде width: 300px не подходят для адаптивного дизайна. Вместо них используются относительные единицы:
| Единица | Описание |
|---|---|
% | Процент от родительского элемента |
em | Относительно размера шрифта текущего элемента |
rem | Относительно размера шрифта корневого элемента (html) |
vw | 1% от ширины области просмотра |
vh | 1% от высоты области просмотра |
ch | Ширина символа «0» в текущем шрифте |
Пример:
.container {
width: 100%; /* Занимает всю ширину родителя */
max-width: 1200px; /* Но не больше 1200px */
margin: 0 auto; /* Центрирует блок */
padding: 0 1rem; /* Отступы в rem — масштабируются с шрифтом */
}
📌 Внимание
Используйтеmax-width, а неwidth, чтобы контент не растягивался на огромных экранах.
Медиа-запросы
Медиа-запросы позволяют применять CSS-правила только при определённых условиях — например, когда ширина экрана меньше 768 пикселей.
Базовый синтаксис:
@media (min-width: 768px) {
/* Стили для планшетов и больше */
}
Обычно применяют подход mobile-first: сначала пишут стили для мобильных устройств, а затем добавляют правила для больших экранов через min-width.
Пример полного адаптивного макета:
/* Базовые стили — для мобильных */
.card {
width: 100%;
padding: 1rem;
margin-bottom: 1rem;
}
/* Планшеты и больше */
@media (min-width: 768px) {
.card {
width: calc(50% - 0.5rem);
float: left;
margin-right: 1rem;
margin-bottom: 1rem;
}
.card:nth-child(2n) {
margin-right: 0;
}
}
/* Десктопы */
@media (min-width: 1024px) {
.card {
width: calc(33.333% - 0.75rem);
margin-right: 1.5rem;
}
.card:nth-child(3n) {
margin-right: 0;
}
}
⛔ Осторожно
Не привязывайте точки разрыва к конкретным устройствам (например, «768px = iPad»). Лучше выбирать их по содержимому: когда макет перестаёт быть удобным.
Гибкие макеты: Flexbox и Grid
Современные CSS-технологии — Flexbox и CSS Grid — позволяют создавать макеты, которые сами перестраиваются при изменении ширины.
Пример с Flexbox:
.container {
display: flex;
flex-wrap: wrap; /* Разрешает перенос элементов */
gap: 1rem;
}
.card {
flex: 1 1 100%; /* На мобильных — 100% ширины */
}
@media (min-width: 768px) {
.card {
flex: 1 1 calc(50% - 0.5rem); /* Две колонки */
}
}
@media (min-width: 1024px) {
.card {
flex: 1 1 calc(33.333% - 0.75rem); /* Три колонки */
}
}
Преимущество: не нужно использовать float или nth-child для сброса отступов.
Контекст использования
Адаптивность — это не только про ширину экрана. Также учитываются:
- Способ взаимодействия: сенсорный экран требует крупных зон нажатия (минимум 48×48 CSS-пикселей).
- Ориентация устройства: портретная vs альбомная.
- Плотность пикселей: не влияет на CSS, но важна для изображений (используйте
srcset). - Системные настройки: тёмная тема, уменьшенные анимации.
Пример учёта предпочтений пользователя:
/* Тёмная тема */
@media (prefers-color-scheme: dark) {
:root {
--bg: #121212;
--text: #e0e0e0;
}
}
/* Минимизация анимаций */
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
Эти медиа-запросы не обязательны для базовой адаптивности, но делают интерфейс более дружелюбным.
Динамические изменения
Viewport может меняться в реальном времени:
- при повороте устройства;
- при скрытии адресной строки в мобильном браузере;
- при открытии клавиатуры.
Поэтому важно:
- избегать
height: 100vh— используйте100dvh(dynamic viewport height) илиheight: stretchв Flex/Grid; - не использовать
width: 100vw— оно может вызывать горизонтальный скролл из-за системных панелей.
Пример безопасного full-width блока:
.full-width {
width: 100%;
margin-left: calc(-50vw + 50%);
margin-right: calc(-50vw + 50%);
}
Или проще — используйте width: stretch внутри flex-контейнера.
Добавление адаптивности
Шаг 1. Добавьте метатег viewport
Без этого тега сайт на мобильных устройствах будет отображаться как настольная версия, уменьшенная до размера экрана. Это приведёт к мелкому тексту, горизонтальному скроллу и неудобству.
Добавьте в <head> HTML-документа:
<meta name="viewport" content="width=device-width, initial-scale=1">
📌 Внимание
Этот тег обязателен. Без него медиа-запросы могут работать некорректно.
Шаг 2. Используйте относительные единицы вместо фиксированных
Замените px на относительные единицы:
- ширина контейнеров →
%илиmax-width - отступы и размеры →
rem,em - полноразмерные элементы →
vw,vh(осторожно)
Пример:
.container {
width: 100%;
max-width: 1200px; /* Не больше 1200px */
margin: 0 auto; /* Центрирует */
padding: 0 1rem; /* Отступы масштабируются */
}
💡 Совет
max-widthзащищает от растягивания на огромных экранах. Без него текст может занимать всю ширину 4K-монитора — и стать нечитаемым.
Шаг 3. Применяйте подход mobile-first
Начинайте писать CSS с мобильной версии. Это означает:
- базовые стили — для малых экранов (до 768px);
- расширения — через
@media (min-width: ...).
Пример:
/* Базовые стили — для мобильных */
.card {
width: 100%;
padding: 1rem;
}
/* Планшеты и больше */
@media (min-width: 768px) {
.card {
width: calc(50% - 0.5rem);
}
}
/* Десктопы */
@media (min-width: 1024px) {
.card {
width: calc(33.333% - 0.75rem);
}
}
⛔ Осторожно
Не используйтеmax-widthв медиа-запросах при mobile-first. Это нарушает логику нарастания сложности.
Шаг 4. Сделайте изображения гибкими
Изображения часто ломают макет, выходя за границы экрана. Исправьте это:
img {
max-width: 100%;
height: auto;
}
Теперь любое изображение будет масштабироваться, но не превысит ширину своего контейнера.
Шаг 5. Используйте Flexbox или Grid для макета
Эти технологии позволяют создавать гибкие сетки, которые сами перестраиваются.
Пример с Flexbox:
.grid {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.item {
flex: 1 1 100%; /* На мобильных — 100% */
}
@media (min-width: 768px) {
.item {
flex: 1 1 calc(50% - 0.5rem); /* Две колонки */
}
}
Преимущество: не нужно использовать float, clear, nth-child.
Шаг 6. Ограничьте ширину текста
Длинные строки утомляют глаза. Оптимальная длина — 45–75 символов.
Способы ограничения:
max-width: 65ch—ch= ширина символа «0»max-width: 800px— фиксированное значение
Пример:
p {
max-width: 65ch;
line-height: 1.6;
}
Шаг 7. Убедитесь, что нет горизонтального скролла
Горизонтальный скролл — главный признак неправильной адаптивности. Проверьте:
- все блоки имеют
width ≤ 100%; - нет
margin,paddingилиborder, выталкивающих элемент за край; - изображения и видео — гибкие (
max-width: 100%); - не используется
width: 100vw(оно включает системные панели).
💡 Совет
В браузере откройте DevTools → Toggle device toolbar → выберите iPhone SE (320px). Если появился горизонтальный скролл — ищите виновника.
Шаг 8. Проверьте зоны нажатия
На сенсорных экранах кнопки и ссылки должны быть не меньше 48×48 CSS-пикселей. Это требование доступности.
Пример:
button, a {
min-height: 48px;
min-width: 48px;
padding: 12px;
}
Шаг 9. Тестируйте на реальных устройствах
DevTools — удобный инструмент, но он не заменяет реальное устройство. Обязательно проверьте:
- на своём смартфоне (в обычном браузере, не в Telegram/Instagram);
- в альбомной ориентации;
- после поворота экрана;
- при открытии клавиатуры.
Шаг 10. По желанию: добавьте современные улучшения
Когда базовая адаптивность работает, можно улучшить опыт:
-
Плавное масштабирование текста:
h1 { font-size: clamp(1.5rem, 4vw, 3rem); } -
Контейнерные запросы (для компонентов):
.card { container-type: inline-size; }
@container (min-width: 300px) { .card__title { font-size: 1.25rem; } } -
Учёт системных настроек:
@media (prefers-color-scheme: dark) { :root { --bg: #121212; } }
Эти шаги не обязательны для базовой адаптивности, но делают интерфейс современнее.