Введение

Адаптивность

Адаптивная вёрстка — это когда один и тот же сайт удобно выглядит и на телефоне, и на планшете, и на десктопе. Контент не «ломается», шрифты и отступы масштабируются, меню на узком экране может превращаться в гамбургер, а сетки — перестраиваться в одну колонку.

В этом занятии: подход Mobile first, медиа-запросы @media, единицы rem и em, vh/vw, кратко — container queries и адаптивные изображения. В практике — три брейкпоинта, меню-гамбургер и проверка через DevTools.

Подход

Mobile first

Mobile first — это когда базовые стили пишутся под маленький экран (мобильный), а затем с помощью медиа-запросов добавляются правила для планшетов и десктопов. Так проще: не нужно «отменять» лишнее на мобильных, и контент по умолчанию доступен именно там, где часто критичен размер и скорость.

Альтернатива — «desktop first»: сначала стили для широкого экрана, потом @media (max-width: ...) для сужения. Оба подхода допустимы; Mobile first часто удобнее, потому что прогрессивное усиление (добавляем, а не убираем) проще поддерживать.

Демо

Mobile first — базовые и расширенные стили

Ниже один и тот же блок. Кнопки имитируют: «только база» (как на мобильном) и «база + дополнения для широкого экрана». Обратите внимание: на «мобильном» меньше padding и размер шрифта.

Контент блока: на mobile — компактно, на desktop — больше отступы и шрифт.
Медиа-запросы

Media queries

Медиа-запросы позволяют применять CSS в зависимости от характеристик устройства: ширины экрана, ориентации, плотности пикселей. Синтаксис: @media (условие) { ... }.

Чаще всего используют ширину viewport: @media (min-width: 768px) — «когда ширина не меньше 768px», @media (max-width: 600px) — «когда ширина не больше 600px». Так задают брейкпоинты: от какой ширины менять раскладку (например колонки в ряд, сайдбар сбоку).

Комбинированные запросы — «от и до», то есть в промежутке — на практике используются очень часто. Условия объединяют через and: @media (min-width: 600px) and (max-width: 900px) { ... } — стили применяются только когда ширина от 600px до 900px включительно. Так задают отдельные стили для планшетов между мобильными и десктопом.

Демо

Media queries — наблюдайте за блоком

Растягивайте или сужайте окно браузера и наблюдайте за блоком ниже: в зависимости от ширины viewport меняются размер текста, отступы и цвет фона. Так работают медиа-запросы в реальной странице.

Узкое окно (≤600px) — компактный блок, светлый фон. Средняя ширина (601–900px) — больше отступы, другой оттенок. Широкое (≥901px) — крупнее текст и ещё один оттенок фона.

Медиа-запросы работают и во внешнем файле .css, и внутри блока <style> на странице — браузер применяет их одинаково. Ниже код, который управляет этим блоком:

@media (max-width: 600px) {
  #demoMediaBoxLive {
    font-size: 0.9rem;
    padding: 12px;
    background: #e8f0fe;
  }
}
@media (min-width: 601px) and (max-width: 900px) {
  #demoMediaBoxLive {
    font-size: 1rem;
    padding: 18px;
    background: #cfe2f3;
  }
}
@media (min-width: 901px) {
  #demoMediaBoxLive {
    font-size: 1.1rem;
    padding: 24px;
    background: #9fc5e8;
  }
}
Мария
min-width — от такой ширины и выше применяются стили, да?
Александр
Да, верно. min-width: 768px — стили применятся при ширине от 768px и выше; max-width — наоборот, до этой ширины.
Единицы

rem

rem — размер относительно корневого элемента (html). Если у html задано font-size: 16px, то 1rem = 16px, 1.5rem = 24px. Меняете один размер в корне — все элементы в rem масштабируются. Удобно для доступности (пользователь меняет базовый шрифт) и для единообразия масштаба по всему сайту.

Единицы

em

em — размер относительно font-size текущего элемента (или родителя для свойств вроде margin/padding, в зависимости от свойства). 1em = текущий размер шрифта. Удобно для отступов и размеров, которые должны быть «пропорциональны тексту»: например padding: 0.5em всегда даёт половину высоты строки. Минус — вложенность: у вложенных элементов em множится от своего контекста.

Демо

rem и em — изменение базы

В блоке ниже размеры заданы в em (относительно контейнера). Кнопки меняют font-size у демо-контейнера — текст и отступы в em масштабируются вместе. Так же rem зависит от корня: изменили базу — всё пересчиталось.

Текст 1em · 1.2em · padding 0.5em

Сейчас у контейнера font-size: 18px. Все em пересчитываются от этой базы.

Единицы viewport

vh и vw

vh — 1% высоты окна браузера (viewport). 100vh — вся высота экрана. vw — 1% ширины окна; 100vw — вся ширина (с учётом полосы прокрутки, поэтому на страницах с вертикальным скроллом иногда предпочитают 100% для ширины).

Удобно для полноэкранных блоков, баннеров «на весь экран», фиксированных шапок по высоте. Минус: на мобильных адресная строка браузера меняет видимую высоту — 100vh может быть больше видимой области. Для точной «высоты экрана» иногда используют dvh (dynamic viewport height) в современных браузерах.

Демо

vh и vw — блок относительно окна

Ниже блок с высотой и шириной в vh/vw. Кнопки задают разные значения — видно, как размер зависит от размера окна (здесь окно — это страница урока; на большом мониторе блок будет больше).

Блок: высота в vh, ширина в % или vw. Измените размер окна — высота блока изменится.
Обзор

Container queries

Container queries (контейнерные запросы) — это когда стили зависят не от размера окна, а от размера родительского контейнера. Контейнер задаётся через container-type: inline-size (или size), затем в потомках можно писать @container (min-width: 400px) { ... }. Полезно для компонентов: карточка, сайдбар — перестраиваются в зависимости от того, сколько места им выделили в макете, а не от ширины всего экрана.

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

Практический пример: меняем ширину контейнера

Ниже блок с container-type: inline-size. Кнопки задают ширину контейнера. Когда ширина ≥ 220px, срабатывает @container (min-width: 220px) — внутренняя раскладка переключается в две колонки и меняется фон. При необходимости можно также уменьшить или увеличить окно браузера — контейнер ограничен шириной страницы.

Карточка Текст 1 Текст 2

Ширина контейнера: 180px → одна колонка. Увеличьте кнопкой до 250px или 320px — появится сетка в две колонки и другой фон.

Дмитрий
То есть карточка сама решает, в один столбец или в ряд, по своей ширине — круто.
Изображения

Responsive images

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

srcset и sizes

  • srcset — список источников и их ширина: srcset="photo-320.jpg 320w, photo-640.jpg 640w, photo-800.jpg 800w". Дескриптор 320w говорит: «этот файл имеет внутреннюю ширину 320 пикселей». Браузер учитывает ширину viewport и плотность пикселей (retina) и выбирает подходящий файл.
  • sizes — подсказка, какой шириной будет отображаться картинка: sizes="(max-width: 600px) 100vw, 50vw" означает: «при ширине экрана до 600px картинка занимает 100% ширины окна, иначе — 50%». Без sizes браузер считает, что изображение на всю ширину (100vw), и может загрузить слишком большой файл.
  • Атрибут src остаётся fallback для старых браузеров; обычно в него ставят «средний» или самый частый вариант.

picture

  • Элемент <picture> даёт полный контроль: несколько <source> с атрибутами media (условие по ширине) или type (формат: image/webp, image/avif). Браузер выбирает первый подходящий source; если ни один не подошёл — используется <img> внутри.
  • Удобно для разного кадрирования (crop) на мобильном и десктопе, для форматов WebP/AVIF с fallback в JPEG, для art direction (разная картинка под разную ширину).
Демо

Responsive images — какой файл выбран

В реальной странице выбор источника зависит от ширины окна и плотности пикселей. Нажмите кнопку: в блоке кода ниже будет показано, какой src браузер подставит при узком или широком экране (имитация).


          

При узком экране браузер подставит photo-320.jpg (320w). Сейчас: узкий.

Резюме

Кратко об адаптивности

Mobile first — базовые стили для мобильных, затем медиа-запросы для больших экранов. Медиа-запросы @media (min-width: ...) / max-width задают брейкпоинты. rem — от корня, em — от текущего шрифта; vh/vw — от окна. Container queries — стили от размера контейнера. Адаптивные картинки — srcset, sizes, picture. Не забудьте meta name="viewport" в <head>, иначе медиа-запросы на мобильных могут работать некорректно.

Александр
Готов к заданиям.
Задание 1

Сопоставьте единицу и описание

Выберите для каждой единицы подходящее описание.

rem
em
vh / vw
Задание 2

Mobile first

Подход Mobile first означает:

Задание 3

Медиа-запрос

Чтобы применить стили только когда ширина экрана не меньше 768px, пишут:

Финальный допуск

Краткий тест (8 вопросов)

Для доступа к практике нужно набрать не менее 80% (минимум 7 из 8 правильных ответов).

1. Mobile first — это…

2. Медиа-запрос @media (max-width: 600px) срабатывает когда…

3. rem зависит от…

4. 100vh — это…

5. Для адаптивных изображений используют…

6. Container queries позволяют применять стили в зависимости от…

7. Мета-тег viewport нужен чтобы…

8. em — это размер относительно…

Практика

Итоговое задание: Адаптивность

Сделайте одну HTML-страницу со стилями в <style> (или подключите .css и для проверки скопируйте стили в тот же файл). Выполните:

  • Три брейкпоинта — в CSS должны быть минимум три медиа-запроса с разными условиями по ширине (например max-width: 480px, min-width: 768px, min-width: 1024px или свои значения). В каждом брейкпоинте что-то должно меняться: размер шрифта, отступы, количество колонок, видимость блоков.
  • Меню-гамбургер — на узком экране навигация скрыта за кнопкой-гамбургером (три полоски или иконка); по клику меню показывается/скрывается. Реализация может быть на CSS (checkbox + :checked) или на JavaScript. На широком экране меню может быть видимым без гамбургера.
  • Viewport — в <head> должен быть meta name="viewport" content="width=device-width, initial-scale=1".

Проверьте вёрстку через DevTools: режим адаптивного дизайна (Toggle device toolbar), изменение ширины окна — убедитесь, что брейкпоинты и гамбургер работают. Порог зачёта: 70 баллов из 100. Загрузите index.html и нажмите «Проверить».