Урок 5 · CSS
Адаптивность: сайт удобен на любом экране
Адаптивная вёрстка — подход, при котором одна и та же страница перестраивается под ширину экрана: на телефоне блоки встают в колонку, на мониторе — в ряды. Основа — тег meta viewport, резиновые размеры вместо фиксированных пикселей, гибкие сетки и медиазапросы для крупных перестроек.
- Без
<meta name="viewport">телефон покажет уменьшенную десктопную страницу. - Начинай с узкого экрана (mobile first), широкие добавляй медиазапросами.
- Контейнер:
width: min(100% - 32px, 1120px)вместо фиксированной ширины. - Картинкам —
max-width: 100%; height: auto. - Сетка
repeat(auto-fit, minmax(220px, 1fr))адаптируется без медиазапросов.
Зачем этот урок сейчас
Многие посетители открывают сайты с телефона, причём часто — по ссылке из мессенджера или поиска. Страница, которую приходится раздвигать пальцами и прокручивать вбок, теряет их за секунды, а поисковики оценивают удобство мобильной версии. Адаптивность — не отдельный «мобильный сайт», а несколько привычек, которые закладываются с первых строк CSS.
Первый обязательный тег
<meta name="viewport" content="width=device-width, initial-scale=1">Тег ставят в head. Он говорит телефону: ширина страницы равна ширине экрана, масштаб 1:1. Без него мобильный браузер рисует страницу шириной около 980px и уменьшает её — текст становится крошечным, а медиазапросы для узких экранов не срабатывают. Не запрещай масштабирование (user-scalable=no): людям со слабым зрением нужно увеличивать страницу.
Начинай с узкого экрана
.menu { display: grid; gap: 12px; }
@media (min-width: 48rem) {
.menu { grid-auto-flow: column; justify-content: end; }
}На телефоне всё стоит в колонку — это самая простая раскладка, её делают основой. Для широких экранов медиазапрос с min-width добавляет ряды и колонки. Так базовые стили короче, а горизонтальная прокрутка на телефоне почти невозможна. Подробно о синтаксисе — в справочнике медиазапросы.
Резиновые размеры вместо пикселей
.container {
width: min(100% - 32px, 1120px); /* не шире 1120px и с полями 16px на телефоне */
margin-inline: auto;
}
h1 {
font-size: clamp(1.75rem, 1.2rem + 2.5vw, 3rem); /* растёт с экраном в пределах */
}
.article { max-width: 70ch; } /* удобная длина строки */Фиксированная width: 1200px гарантирует горизонтальную прокрутку на телефоне. Вместо неё — проценты, max-width и функции min() и clamp(). clamp(минимум, желаемое, максимум) делает размер шрифта плавным без медиазапросов. ch — ширина символа «0», и 70ch держит строку около 70 знаков — читать удобно и на мониторе.
Какие единицы брать
| Единица | Относительно чего | Для чего |
|---|---|---|
% | родителя | ширина колонок и блоков |
rem | размера шрифта страницы | шрифты, отступы, точки перелома |
em | шрифта самого элемента | отступы внутри кнопки |
vw, vh | окна | крупные заголовки, первый экран |
dvh | видимой высоты окна | полноэкранные блоки на телефоне |
fr | свободного места в grid | колонки сетки |
На телефоне 100vh часто больше видимой области из-за адресной строки, и низ блока прячется. Единица 100dvh учитывает панели браузера.
Гибкие картинки и видео
img, video {
max-width: 100%;
height: auto;
}
.cover {
aspect-ratio: 16 / 9;
object-fit: cover;
width: 100%;
}Без max-width: 100% картинка сохраняет свою ширину в пикселях и выталкивает страницу за экран. aspect-ratio и object-fit: cover держат обложки одной пропорции, даже если исходники разные. Чтобы телефон не качал огромный файл, используй srcset — подробно в справочнике тег img.
Сетки, которые адаптируются сами
/* карточки: сколько поместится, каждая не уже 220px */
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
}
/* меню: пункты переносятся на новую строку */
.tags { display: flex; flex-wrap: wrap; gap: 8px; }Многие перестройки не требуют медиазапросов. Grid с auto-fit и minmax сам решает, сколько колонок помещается, а flex-wrap: wrap переносит пункты. Медиазапрос нужен там, где меняется сама структура: боковая колонка уходит под текст, меню сворачивается в кнопку.
Таблицы и длинные слова
.table-scroll { overflow-x: auto; }
.table-scroll table { min-width: 640px; }
.article { overflow-wrap: break-word; } /* длинный URL не раздвигает страницу */Широкую таблицу не сжимают до нечитаемых колонок — её оборачивают в блок с горизонтальной прокруткой, и прокручивается только таблица, а не вся страница. Длинные ссылки и слова без пробелов переносит overflow-wrap.
Удобство для пальца
Кнопки и ссылки на телефоне должны быть не меньше 44×44 пикселей с промежутками между ними, иначе промахи неизбежны. Не прячь важные действия за наведением — у сенсорного экрана его нет. Полям форм ставь правильный type и размер шрифта не меньше 16px: иначе iOS увеличивает страницу при фокусе на поле.
Как проверить адаптивность
- Режим устройства в DevTools: ширины 320, 390, 768, 1024 и 1440 пикселей.
- Медленно тяни край окна — ищи момент, где что-то ломается.
- Нет горизонтальной прокрутки:
document.documentElement.scrollWidthне больше ширины окна. - Увеличь шрифт до 200% — ничего не наезжает.
- Открой страницу на настоящем телефоне: эмулятор не покажет всё.
Адаптивная вёрстка или отдельная мобильная версия
Один адрес и один HTML для всех экранов. Проще поддерживать, лучше для поиска: нет дублей страниц.
Поддомен m.site.ru с другим HTML. Двойная работа, риск разного содержания и дублей в поиске.
Частые ошибки
- Забывают meta viewport — страница на телефоне мелкая.
- Задают блокам фиксированную ширину в пикселях.
- Не ограничивают картинки
max-width: 100%, и появляется прокрутка вбок. - Прячут текст на телефоне, вместо того чтобы перестроить блоки.
- Ставят шрифт полей меньше 16px, и iOS увеличивает страницу при вводе.
Доступность
Адаптивность — часть доступности: страница должна работать при увеличении до 200% и при ширине 320px без горизонтальной прокрутки (требование WCAG «Reflow»). Не запрещай масштабирование в meta viewport, оставляй крупные области касания и одинаковое содержание на всех экранах.
Поддержка браузерами
meta viewport, проценты, max-width, медиазапросы, Flexbox и Grid работают во всех актуальных браузерах. min(), clamp(), aspect-ratio и единицы dvh — современные и тоже поддерживаются свежими версиями браузеров.
Практика
Сверстай страницу: контейнер не шире 1120px с полями 16px на телефоне, заголовок с плавным размером от 28 до 48px, три карточки в одну колонку на телефоне и в несколько на широком экране без медиазапроса, картинки не вылезают за экран. Проверь ширины 320 и 1280px.
Показать решение
.container { width: min(100% - 32px, 1120px); margin-inline: auto; }
h1 { font-size: clamp(1.75rem, 1.2rem + 2.5vw, 3rem); }
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}
img { max-width: 100%; height: auto; }Частые вопросы
Зачем нужен meta viewport?
Он говорит мобильному браузеру, что ширина страницы равна ширине экрана. Без него телефон рисует страницу как монитор шириной около 980px и уменьшает её.
Что такое mobile first?
Подход, при котором базовые стили пишут для телефона, а медиазапросы с min-width добавляют раскладку для широких экранов.
Как убрать горизонтальную прокрутку на телефоне?
Найди элемент шире экрана: фиксированная ширина, картинка без max-width, длинное слово, широкая таблица. В DevTools удобно временно поставить всем элементам outline и посмотреть, что вылезает.
Нужны ли медиазапросы, если есть Grid и Flexbox?
Меньше, чем раньше. Число колонок решают auto-fit и flex-wrap, а медиазапросы остаются для смены структуры страницы.
Какие ширины экрана проверять?
Для первого прохода хватает 320, 390, 768, 1024 и 1440 пикселей, плюс медленное сужение окна, чтобы найти места, где вёрстка ломается.