Адаптивность: медиазапросы и контейнерные запросы
Зачем:Сайт открывают на телефоне, ноутбуке и большом мониторе, причём чаще всего на телефоне. После урока вы делаете mobile first, ставите точки перелома по содержимому и используете контейнерные запросы, чтобы компонент подстраивался под своё место.
30 минут
Озвучено синтезом речи (Qwen3-TTS), голос не принадлежит человеку.
Адаптивный дизайн — один сайт, который подстраивается под любой экран медиазапросами. Контейнерные запросы подстраивают компонент под ширину его родителя.
Один сайт для всех экранов
В 2007 году вышел iPhone, и сайты, которые прекрасно выглядели на ноутбуке, вдруг оказались на экране в несколько раз меньше. Сначала делали отдельный мобильный сайт на другом адресе: m.example.ru, и вели две копии. Это было дорого и путало. В 2010 году американский дизайнер Итан Маркотт описал другой путь и назвал его адаптивным веб-дизайном: один сайт, один HTML, а вид подстраивается под экран. Он состоит из трёх вещей:
- резиновая сетка: ширины колонок в долях, а не в пикселях;
- гибкие изображения это картинки сжимаются вместе с колонкой:
img { max-width: 100%; height: auto; }; - медиазапросы: правила, которые включаются на определённой ширине.
К этому добавились два соглашения. Viewport: строка <meta name="viewport" content="width=device-width, initial-scale=1">, о которой вы знаете из урока про head. Без неё телефон уменьшает страницу, как «широкий экран», и медиазапросы не срабатывают. И mobile first: идея Люка Вроблевски (2009–2011): начинайте не с настольного вида, а с мобильного.
Mobile first и медиазапросы
Mobile first на практике: основные правила пишутся для узкого экрана, и для широкого к ним добавляют:
/* для всех: один столбец */
.layout {
display: grid;
grid-template-areas: "main" "aside";
gap: 2rem;
}
/* от 48rem (768px) и шире: добавляем два столбца */
@media (min-width: 48rem) {
.layout {
grid-template-columns: minmax(0, 2fr) minmax(14rem, 1fr);
grid-template-areas: "main aside";
}
} Почему так, а не наоборот? Телефону достаётся простой код, и ему не надо ничего отменять, а усложнение приходит только на экраны, которым оно по силам. Условие min-width читается «шире или равно».
Другие правила: точки перелома выбирают по содержимому, а не по устройствам. Потяните окно вширь и там, где строка становится слишком длинной, а карточки слишком растянутыми, поставьте точку. Моделей телефонов тысячи и они меняются, а ваш контент остаётся. Размеры пишите в rem: тогда точки уважают настройку шрифта читателя. И не забывайте, что адаптивность это не только ширина: есть высота, ориентация, а ещё настройки человека (prefers-color-scheme, prefers-reduced-motion), о которых в следующих уроках.
Попробуйте сами: двигайте ширину и смотрите, что происходит в этой странице. Внутри рамки настоящие медиазапросы.
- Медиазапрос min-width: 48rem (768 px): не сработал, один столбец.
- Карточка в основном блоке: контейнер около 358 px, а порог контейнерного запроса 416 px (26rem): вертикальная.
- Карточка сбоку: контейнер около 358 px: вертикальная.
Окно одно, а карточки ведут себя по-разному: каждая смотрит на ширину своего места. В этом разница между медиазапросом и контейнерным запросом.
Проверьте себя: почему в mobile first пишут min-width, а не max-width?
Основные правила для узкого экрана, а min-width добавляет усложнение там, где места больше. Телефону ничего не приходится отменять.
Контейнерные запросы: подстраиваемся под своё место
Медиазапрос смотрит на окно. Но компонент не знает, где его поставят: одна и та же карточка может оказаться в широкой основной колонке и в узкой боковой, и окно у них общее. До недавних пор решения не было, и приходилось писать разные классы на каждое место.
В 2022–2023 годах во всех браузерах появились контейнерные запросы: компонент смотрит на ширину своего родителя.
.cards {
container-type: inline-size;
}
@container (min-width: 40rem) {
.card {
display: grid;
grid-template-columns: 1fr auto;
}
} Родителю объявляют, что он «контейнер» (container-type: inline-size, по ширине), а потомок спрашивает: «а контейнер шире 40rem?». Если да, карточка раскладывается в две колонки, если нет, остаётся вертикальной. Теперь карточку можно поставить куда угодно, и она сама выберет вид. Посмотрите на схему выше: там две одинаковые карточки в одном окне, и ведут они себя по-разному.
Заметьте: контейнер не может быть тем же элементом, который меняется. Правила внутри @container действуют на потомков контейнера, а не на него самого.
Проверьте себя: чем контейнерный запрос лучше медиазапроса для карточки?
Он смотрит на ширину своего места, а не окна, поэтому одна и та же карточка в широкой и узкой колонках одного окна выбирает свой вид.
Пальцы и глаза
Адаптивность это ещё и удобство на ощупь. Кнопка должна быть достаточно большой для пальца: около 44 на 44 пикселя (min-height: 2.75rem): столько рекомендует Apple и стандарт WCAG уровня AAA; минимум в WCAG 2.2 для уровня AA это 24 пикселя. Между кнопками нужен зазор. Главное действие вашего проекта должно быть видно без прокрутки на экране телефона: для этого у вас есть кнопка вверху страницы.
Практика
Сделайте страницу адаптивной. В предпросмотре есть ширина, и вы можете посмотреть, что получается, но надёжнее другой способ: откройте инструменты разработчика (F12) и включите режим устройств (значок телефона, Ctrl+Shift+M). Там можно выбрать телефон и потянуть ширину от 320 пикселей.
Предупреждение: проверки в упражнении видят вашу страницу при одной ширине, поэтому они не смогут сказать, написали ли вы @media и в какую сторону. Они проверят то, что видно на любой ширине: viewport, гибкие изображения, размер кнопки и контейнер карточек. За медиазапросом следите сами, потянув окно.
Что было не так с 2014 годом
В 2014-м «адаптивность» часто означала «ужать десктопный вид»: колонки столбиком, меню в «гамбургер», а лишнее прячем display: none. Текст всё равно оставался слишком мелким, а картинки грузились в полном размере. Привычка писать «десктоп сначала, а потом всё отменять» дала миру тысячи страниц, где телефон разбирает правила, которые тут же отменяются.
Практика
Готовлю вашу страницу…
Тест
Вопрос 1 из 6
Карточки
Эти карточки попадут в повторение, когда вы завершите урок.
Три составляющие адаптивной вёрстки?
Ответ
Резиновая сетка (доли, а не пиксели), гибкие изображения (max-width: 100%) и медиазапросы. Термин ввёл Итан Маркотт в 2010 году.
Что такое mobile first?
Ответ
Базовые стили пишут для узкого экрана, а для широкого добавляют @media (min-width: …). Телефону достаётся простой код, и ничего не надо отменять.
Как ставить точки перелома?
Ответ
По содержимому: где макет начинает ломаться, там и точка. Не по моделям телефонов. Пишите в rem, чтобы они уважали размер шрифта читателя.
Что такое контейнерный запрос?
Ответ
container-type: inline-size у родителя и @container (min-width: …) у потомка: компонент подстраивается под ширину своего места, а не окна.
Какой размер у кнопки для пальца?
Ответ
Около 44 × 44 пикселей (2.75rem): так рекомендуют Apple и WCAG 2.5.5. Минимум по WCAG 2.2 уровня AA 24 пикселя.
Источники
- Responsive design (MDN) CC BY-SA, по-английски
- CSS container queries (MDN) CC BY-SA, по-английски
- Container queries (web.dev) CC BY, по-английски
- Mobile first и desktop first — Дока только ссылка, по-русски
- Responsive web design (Википедия) CC BY-SA, по-английски
Дальше
Теперь вы знаете: адаптивная вёрстка и mobile first, медиазапросы, контейнерные запросы.