Когда media queries — это только начало

Большинство разработчиков, услышав «адаптивный дизайн», сразу думают о трёх-четырёх breakpoints: 320px, 768px, 1024px, 1440px. Поставил media queries на каждый — готово, адаптив есть. На деле это работает примерно как поставить охрану только у входной двери и считать здание защищённым.

Адаптивность — это система. Media queries — один инструмент в этой системе, и далеко не самый интересный. За последние три года CSS получил столько мощных возможностей, что многие вещи, которые раньше требовали десятков строк с breakpoints, теперь решаются одной строкой.

Mobile-first: это философия, а не порядок CSS

Подход «сначала мобильный» — не просто договорённость «пишем стили для маленьких экранов первыми». Это про приоритеты.

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

Mobile-first заставляет думать о главном: что здесь самое важное? Если на экране 375px должна быть одна кнопка CTA и минимум лишнего — значит, именно это и есть суть страницы. На десктопе потом добавляется второстепенное.

Около 62% мирового трафика в 2025 году идёт с мобильных устройств. В России этот показатель чуть ниже, но устойчиво растёт. Думать в первую очередь о мобильных пользователях — это уже не «хорошая практика», а необходимость.

На уровне CSS это выглядит так: базовые стили — для маленьких экранов, а min-width в media queries добавляет возможности по мере увеличения экрана. Не убирает лишнее, а добавляет нужное.

Fluid typography: clamp() вместо четырёх breakpoints

Типичная проблема: на мобильном нужен заголовок 24px, на десктопе — 48px. Классическое решение — два media query. Но что происходит между 480px и 1200px? Текст резко прыгает в одной точке.

Функция clamp() решает это элегантно:

font-size: clamp(1.5rem, 4vw, 3rem);

Три параметра: минимум, предпочтительное значение (масштабируется с viewport), максимум. Шрифт плавно растёт от 24px на маленьких экранах до 48px на больших — без единого media query.

То же работает для отступов, ширины элементов, высоты блоков. clamp() поддерживается во всех современных браузерах с 2020 года.

Практический пример: у лендинга с секцией hero, где заголовок и подзаголовок — ключевые элементы, clamp() убирает необходимость в отдельных стилях для трёх точек перехода. Меньше кода, меньше мест для ошибок.

CSS Grid и Flexbox: макеты без media queries

Grid с auto-fill и minmax() может адаптироваться сам:

display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 1.5rem;

Этот код создаёт сетку, которая сама решает, сколько колонок поместится. На мобильном — одна, на планшете — две-три, на десктопе — четыре. Ноль media queries.

Для карточек товаров, портфолио, блога — это стандартное решение. Flexbox с flex-wrap: wrap и правильно выставленными flex-basis даёт похожий эффект для горизонтальных списков. Элементы сами переносятся на следующую строку, когда не помещаются.

Чем меньше media queries — тем меньше состояний, которые нужно проверять при тестировании. Это реально экономит время разработки и снижает число багов.

Container queries: революция для компонентного подхода

Долгие годы media queries были завязаны на ширину viewport — всего окна браузера. Это создавало странные ситуации: компонент карточки должен перестраиваться не тогда, когда уменьшается экран, а когда уменьшается его контейнер. Раньше это решалось JavaScript или дублированием стилей.

Container queries появились в 2023 году и поддерживаются в Chrome, Firefox и Safari. Теперь компонент может реагировать на размер своего родителя:

.card-container {
  container-type: inline-size;
}

@container (min-width: 400px) {
  .card {
    display: flex;
    flex-direction: row;
  }
}

Карточка вертикальная в узком сайдбаре и горизонтальная в широкой основной колонке — без JavaScript, без дополнительных классов.

Для дизайн-систем и компонентных библиотек это меняет всё. Компонент становится по-настоящему переиспользуемым: он адаптируется к своему контексту, а не к глобальному viewport.

Адаптивные изображения: не просто max-width: 100%

max-width: 100% на изображениях — это базовый минимум, который не решает главное: браузер всё равно загружает полноразмерное изображение на мобильном. Если у вас фото 2400×1600px, оно загрузится даже на телефоне с экраном 390px.

Правильное решение — атрибуты srcset и sizes:

<img
  src="photo-800.jpg"
  srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
  sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
  alt="..."
>

Браузер выберет подходящую версию сам, учитывая и ширину экрана, и плотность пикселей. iPhone с Retina-экраном загрузит изображение вдвое больше, чем нужно для стандартного экрана — но ровно столько, чтобы картинка выглядела чётко.

Для изображений с принципиально разными кадрировками — тег <picture> с source и media. Портрет крупным планом на телефоне, широкий пейзаж на десктопе — из одного HTML-элемента.

Правильно настроенные адаптивные изображения могут уменьшить вес страницы на 40–60% для мобильных пользователей. Это напрямую влияет на Core Web Vitals и позиции в поиске.

Новые viewport units: dvh, svh, lvh

Долгое время 100vh был источником боли на мобильных. Проблема: браузер на телефоне меняет высоту viewport в зависимости от того, видна ли адресная строка. 100vh вычислялся на момент загрузки — и hero-секция либо обрезалась, либо имела лишний скролл.

В 2023–2024 годах появились новые единицы:

  • dvh (dynamic viewport height) — меняется вместе с viewport, учитывает появление и скрытие UI браузера
  • svh (small viewport height) — минимальный viewport, браузер с видимой адресной строкой
  • lvh (large viewport height) — максимальный viewport, адресная строка скрыта

Для полноэкранных секций правило простое: min-height: 100dvh вместо 100vh. Это решает проблему «прыгающего» экрана на iOS без JavaScript-хаков.

Touch targets и интерактивность

Адаптивность — это не только визуальная часть. Нажимаемые элементы на мобильном должны быть достаточного размера. Google рекомендует минимум 48×48px для touch target, Apple — 44×44pt.

На практике: кнопка может выглядеть небольшой, но область нажатия должна быть больше. Делается через padding:

.small-button {
  padding: 12px 20px;
}

Ещё один аспект — hover-состояния. На десктопе :hover — привычная вещь. На тачскрине её нет, или она ведёт себя странно. Элементы, у которых вся информация спрятана за hover, на мобильном просто не работают. Используйте @media (hover: hover), чтобы hover-эффекты применялись только на устройствах с курсором:

@media (hover: hover) {
  .card:hover {
    transform: translateY(-4px);
  }
}

Производительность как часть адаптивности

Медленный сайт — неадаптивный сайт. 53% мобильных пользователей уходят, если страница грузится больше 3 секунд. Мобильные сети нестабильнее Wi-Fi, процессоры слабее десктопных.

Несколько вещей, которые влияют на скорость на мобильных:

Анимации только через transform и opacity: они обрабатываются на GPU и не вызывают перерисовку страницы. Анимировать width, height, top, left — значит нагружать CPU, что на мобильных ощущается как тормоза.

Ленивая загрузка изображений: loading="lazy" на <img> — один атрибут, который откладывает загрузку изображений вне viewport. Нативно, без JavaScript.

will-change с умом: подсказывает браузеру заранее оптимизировать элемент. Но ставить везде — значит тратить память впустую. Только там, где реально нужна анимация.

Тестирование адаптивности

DevTools браузера — не достаточный инструмент. Эмуляция мобильных устройств в Chrome полезна, но не показывает реальную производительность и не воспроизводит особенности Safari на iOS.

Что реально стоит проверять:

  • Реальные устройства: хотя бы один Android и один iPhone разных годов
  • BrowserStack или аналоги для проверки специфичных моделей и версий ОС
  • Медленное соединение: в DevTools → Network → Slow 3G
  • Landscape-ориентация: многие забывают, что телефон можно повернуть
  • Zoom до 200%: требование доступности, и часто выявляет проблемы с адаптивом

Отдельно — Safari на iOS. Этот браузер имеет свои особенности с viewport units, position: fixed и некоторыми CSS-функциями. Если сайт тестируется только в Chrome на Windows — неприятные сюрпризы гарантированы.

Как это влияет на стоимость разработки

Правильный адаптивный дизайн — это не дополнительный этап после вёрстки. Это подход с самого начала: mobile-first проектирование, компонентная архитектура с container queries, продуманная работа с изображениями.

Когда адаптивность заложена в основу, она стоит меньше — нет правок после «а почему на телефоне всё едет». Когда её прикручивают потом — часто дешевле переделать заново.

В REEXY мы закладываем полноценную адаптивность в каждый проект: лендинг от 3 500 ₽, корпоративный сайт от 15 000 ₽ — в эту цену уже входит полная кроссбраузерная и кросс-девайс адаптация, а не «смотрите на мобильном, там примерно нормально».

Если сайт уже есть и плохо работает на мобильных, иногда разумнее сделать аудит и точечные правки, чем переделывать целиком. Это зависит от того, насколько глубоко проблема в архитектуре.

Что проверить прямо сейчас

Возьмите телефон и откройте свой сайт. Проверьте:

  • Текст читается без зума?
  • Кнопки легко нажимать пальцем?
  • Изображения не размытые и не обрезанные в неудачном месте?
  • Формы заполнять удобно? Клавиатура не перекрывает поля?
  • Сайт грузится за разумное время на мобильном интернете?

Если хотя бы на один вопрос ответ «нет» — это точка роста. И, скорее всего, это влияет на конверсию: пользователи просто уходят, не дождавшись загрузки или не сумев нажать нужную кнопку.

Адаптивность измеряется не наличием media queries в коде. Она измеряется тем, насколько удобно пользователю на его конкретном устройстве.