Адаптивный сайт — это сайт, у которого одна и та же HTML-страница перестраивает раскладку под ширину экрана: на телефоне блоки идут в одну колонку, на планшете в две, на компьютере в три-четыре, и нигде не появляется горизонтальная прокрутка. Делается это средствами HTML и CSS, без отдельной мобильной версии. Ниже — полный рабочий пример, разбор каждого приема, типовые ошибки и способ проверки.
Содержание
Примеры проверены в Google Chrome 153 (сентябрь 2026) с эмуляцией телефона 375 px, планшета 768 px и десктопа 1280 px. Результаты, приведенные ниже, взяты из этого прогона.
Мини-словарь: что означают термины
| Термин | Что это | Где встречается |
|---|---|---|
| Viewport | Область окна, в которой браузер раскладывает страницу, в CSS-пикселях | <meta name="viewport"> |
| CSS-пиксель | Единица верстки; на экране с плотностью 3x один CSS-пиксель = 3×3 физических точки | px, devicePixelRatio |
| Медиазапрос | Условие в CSS: «применить эти правила, если ширина >= N» | @media |
| Брейкпоинт | Ширина, на которой раскладка меняется | значение в медиазапросе |
| Резиновая сетка | Размеры в долях (%, fr) и с ограничением max-width вместо жестких пикселей |
Flexbox, Grid |
Термины «адаптивный» и «отзывчивый» (responsive) в русскоязычной практике обычно используют как синонимы. В строгом смысле adaptive design — это несколько заранее сверстанных фиксированных макетов, между которыми страница переключается, а responsive — плавная раскладка, которая тянется между брейкпоинтами. Пример ниже — второй вариант, его сейчас и называют адаптивной версткой.
Минимальный полный пример
Сохраните код в файл index.html и откройте в браузере. Затем включите режим устройства в DevTools (F12, значок телефона) и меняйте ширину.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Адаптивная страница</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-family: system-ui, sans-serif; line-height: 1.5; }
img { max-width: 100%; height: auto; display: block; }
.container { width: 100%; max-width: 1100px; margin: 0 auto; padding: 0 16px; }
.header { display: flex; flex-wrap: wrap; align-items: center;
justify-content: space-between; gap: 12px; padding: 12px 0; }
.nav { display: flex; flex-direction: column; gap: 8px; width: 100%; }
.cards { display: grid; gap: 16px;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.card { border: 1px solid #ddd; border-radius: 8px; padding: 16px; }
h1 { font-size: clamp(1.5rem, 1rem + 2.5vw, 2.5rem); }
@media (min-width: 768px) {
.nav { flex-direction: row; width: auto; }
}
</style>
</head>
<body>
<div class="container">
<header class="header">
<a href="/" class="logo">Логотип</a>
<nav class="nav">
<a href="#">Курсы</a><a href="#">Блог</a><a href="#">Контакты</a>
</nav>
</header>
<h1>Адаптивная страница</h1>
<section class="cards">
<article class="card">Карточка 1</article>
<article class="card">Карточка 2</article>
<article class="card">Карточка 3</article>
<article class="card">Карточка 4</article>
</section>
</div>
</body>
</html>
Что получится на трех ширинах (замер в Chrome 153):
ширина колонок карточек меню размер h1 ширина документа
375 1 столбиком 25.375px 375 (без прокрутки)
768 2 в строку 35.2px 768
1280 4 в строку 40px 1280
Медиазапрос в примере всего один — он переключает меню. Число колонок карточек меняется без медиазапросов: это делает Grid.
Разбор по приемам
1. Meta viewport
Строка <meta name="viewport" content="width=device-width, initial-scale=1"> говорит мобильному браузеру: «раскладывай страницу по реальной ширине экрана в CSS-пикселях». Без нее мобильный браузер считает, что перед ним сайт для компьютера, раскладывает его на виртуальной ширине около 980 px и уменьшает целиком.
Проверка: та же страница без meta viewport на эмуляции телефона 375 px дала ширину раскладки 981 px, масштаб 0.38, три колонки карточек и меню в строку. Медиазапросы при этом честно сработали — но для ширины 980, а не 375. Текст стал мелким, как на скриншоте десктопа.
Не добавляйте user-scalable=no и maximum-scale=1: они мешают пользователю увеличить текст, это проблема доступности.
2. Резиновый контейнер вместо фиксированной ширины
.container занимает 100% ширины, но не больше 1100 px, и центрируется margin: 0 auto. Отступ padding: 0 16px не дает тексту прилипнуть к краю телефона. box-sizing: border-box включает padding в ширину, иначе width: 100% плюс отступы вылезут за экран.
3. Flexbox для строк, Grid для сеток
Шапка сделана на Flexbox: justify-content: space-between разносит логотип и меню по краям, flex-wrap: wrap переносит меню на новую строку, если места мало. Карточки — на Grid: repeat(auto-fit, minmax(240px, 1fr)) означает «столько колонок, сколько влезет при минимальной ширине 240 px, остаток поделить поровну».
| Задача | Что взять | Почему |
|---|---|---|
| Элементы в одну линию с переносом (шапка, кнопки, теги) | Flexbox | Раскладка по одной оси, размеры от содержимого |
| Сетка карточек, галерея | Grid с auto-fit + minmax |
Колонки подстраиваются без медиазапросов |
| Макет страницы: шапка, сайдбар, контент, подвал | Grid с областями (grid-template-areas) |
Две оси сразу, перестановка блоков в медиазапросе |
| Компонент, который зависит от ширины своего блока, а не экрана | Container queries (@container) |
Один компонент ведет себя по-разному в узкой и широкой колонке |
4. Медиазапросы и брейкпоинты
/* по умолчанию - стили для узкого экрана */
.nav { flex-direction: column; }
/* от 768px и шире */
@media (min-width: 768px) {
.nav { flex-direction: row; }
}
Брейкпоинты выбирают по содержимому, а не по списку моделей телефонов: сужайте окно и ставьте брейкпоинт там, где раскладка начинает ломаться. Значения ниже — распространенный ориентир, а не стандарт.
| Диапазон ширины | Типичный класс устройства |
|---|---|
| до 767 px | телефоны |
| 768-1023 px | планшеты, узкие окна |
| от 1024 px | ноутбуки и мониторы |
Кроме min-width в современных браузерах работает запись диапазоном: @media (width >= 768px). Если нужно поддерживать старые браузеры, надежнее классическая форма.
5. Гибкий размер текста
font-size: clamp(1.5rem, 1rem + 2.5vw, 2.5rem) задает размер заголовка, который растет с шириной экрана, но не меньше 1.5rem и не больше 2.5rem. В прогоне это 25.375px на телефоне и 40px на десктопе. Основной текст оставляйте в rem, чтобы работала настройка размера шрифта в браузере.
6. Адаптивные изображения: srcset и sizes
max-width: 100%; height: auto не дает картинке вылезти за контейнер. Но телефону незачем скачивать файл шириной 1600 px — для этого есть srcset:
<img
src="photo-800.png"
srcset="photo-480.png 480w, photo-800.png 800w, photo-1200.png 1200w, photo-1600.png 1600w"
sizes="(min-width: 1100px) 1068px, calc(100vw - 32px)"
width="1600" height="900"
alt="Схема адаптивной сетки"
loading="lazy">
srcset перечисляет файлы и их реальную ширину (w), sizes сообщает браузеру, какой ширины картинка будет в верстке. Браузер сам выбирает файл с учетом плотности экрана. В прогоне Chrome 153: телефон 375 px с плотностью 3x взял photo-1200.png (картинка шириной 343 CSS px = около 1029 физических точек), десктоп 1280 px с плотностью 1x — тоже photo-1200.png (1068 px). Выбор — решение браузера, спецификация разрешает ему учитывать кеш и сеть, так что на других браузерах файл может отличаться.
Атрибуты width и height задают пропорцию, и браузер резервирует место до загрузки — текст не прыгает. loading="lazy" не ставьте на главную картинку первого экрана: она должна грузиться сразу. Если на телефоне нужна другая картинка по содержанию (кадрированная), используют <picture> с <source media="...">.
Типовая ошибка: фиксированная ширина
Неверно — контейнер с жесткой шириной, как в макете под десктоп:
.container { width: 960px; margin: 0 auto; padding: 0 16px; }
Результат на телефоне 375 px (замер в Chrome 153): ширина документа 960 px при видимой области 375 px — появилась горизонтальная прокрутка, карточки остались в три колонки. На планшете 768 px — та же прокрутка.
Исправление — ограничивать ширину сверху, а не фиксировать:
.container { width: 100%; max-width: 1100px; margin: 0 auto; padding: 0 16px; }
После замены ширина документа совпадает с экраном на всех трех ширинах.
Как проверить адаптивность
- DevTools в Chrome, Firefox или Safari: режим устройства, ширины 320, 375, 768, 1024, 1280 и плавное сужение окна.
- Реальный телефон: эмуляция не повторяет все особенности мобильных браузеров (панели, которые прячутся при прокрутке, клавиатура, касания).
- Lighthouse в DevTools: он отметит отсутствие viewport, мелкие области нажатия и сдвиги макета.
- Контрольный вопрос для каждой ширины: нет ли горизонтальной прокрутки, читается ли текст без увеличения, нажимаются ли ссылки пальцем.
Если не получилось
| Симптом | Вероятная причина | Что сделать |
|---|---|---|
| На телефоне сайт мелкий, как уменьшенный скриншот | Нет meta viewport | Добавить строку из примера в <head> |
| Горизонтальная прокрутка | Элемент с фиксированной шириной в px, длинное слово или URL, таблица | Найти в DevTools самый широкий элемент; max-width: 100%, overflow-wrap: anywhere, таблицу обернуть в блок с overflow-x: auto |
| Медиазапрос не срабатывает | Опечатка, правило ниже по коду перебивает, выше специфичность | Проверить во вкладке Styles, какое правило зачеркнуто |
| Картинка растянута или сплющена | Задана ширина и фиксированная высота | height: auto или aspect-ratio + object-fit: cover |
| Контент прыгает при загрузке | У изображений нет width и height |
Добавить атрибуты с реальными пропорциями |
Конструкторы вместо кода
Адаптивную страницу можно собрать без ручной верстки в конструкторах сайтов, например в Tilda: там готовые блоки уже адаптированы, а мобильную раскладку правят в редакторе. Adobe Muse из прежних подборок больше не развивается — Adobe прекратила его поддержку в 2020 году. Конструктор экономит время на типовом лендинге, но нестандартная раскладка, производительность и доработка кода там ограничены. Понимание viewport, Flexbox, Grid и медиазапросов нужно и в этом случае — чтобы понять, почему блок ломается на телефоне.
Выводы
- Адаптивная страница начинается с
<meta name="viewport" content="width=device-width, initial-scale=1">: без нее мобильный браузер раскладывает страницу примерно на 980 px и уменьшает. - Вместо фиксированной ширины —
width: 100%+max-width,box-sizing: border-box, отступы по краям. - Flexbox — для строк элементов, Grid с
auto-fitиminmax— для сеток, которые меняют число колонок без медиазапросов. - Брейкпоинты ставят там, где ломается содержимое; типичные 768 и 1024 px — ориентир, а не стандарт.
- Для изображений —
max-width: 100%,srcset+sizes, атрибутыwidthиheight; проверка — DevTools плюс реальный телефон.
Где применяется / связь с практикой
Адаптивная верстка — базовый навык верстальщика и фронтенд-разработчика: практически любой коммерческий макет сдается в вариантах для телефона и десктопа. Следующий шаг после этого примера — сверстать по реальному макету из Figma лендинг из 4-5 секций (шапка, первый экран, сетка карточек, форма, подвал) и проверить его на трех ширинах.
Освойте тему на практике
Системно HTML, CSS, Flexbox, Grid и адаптив с проверкой домашних заданий разбирают на курсе «HTML/CSS». Попробовать формат и задать вопросы практикующим разработчикам можно на бесплатных открытых уроках Otus.
FAQ
Нужен ли JavaScript для адаптивного сайта?
Для раскладки нет: viewport, медиазапросы, Flexbox и Grid — это HTML и CSS. JavaScript нужен для поведения, например чтобы открывать и закрывать мобильное меню по кнопке.
Чем адаптивный сайт отличается от отдельной мобильной версии?
Отдельная мобильная версия — это другой набор страниц, часто на поддомене вида m.example.com, который приходится поддерживать параллельно. Адаптивный сайт — одни и те же адреса и HTML, меняется только CSS-раскладка.
Что лучше для адаптива: Bootstrap или чистый CSS?
Bootstrap дает готовую сетку и компоненты, это ускоряет типовые интерфейсы. Чистый Flexbox и Grid дают полный контроль и меньший объем CSS; понимать их полезно в любом случае, потому что сетка Bootstrap построена на тех же механизмах.



