Дайджесты новостей
Инженерный чертеж адаптивной верстки с модульной шкалой брейкпоинтов и семантическими медиавыражениями custom-media.

Именованные медиавыражения в CSS: пресеты @custom-media для адаптивного дизайна

Открой любой старый фронтенд-репозиторий и загляни в таблицы стилей. С вероятностью 99% ты увидишь там классическую «россыпь магических чисел»: десятки разбросанных условий @media (max-width: 768px), где-то затесалось @media (min-width: 1024px), а в паре компонентов верстальщик ошибся на один пиксель и написал max-width: 767px, сломав сетку карточек на стыке разрешений.

Эта проблема преследует веб-индустрию более пятнадцати лет. Мы научились выносить цвета, отступы и шрифты в CSS Custom Properties (переменные вида --primary-color), но сами медиавыражения до сих пор копипастим вручную.

Спецификация CSS Media Queries Level 5 закрывает эту историческую несправедливость директивой @custom-media.

Давай разберем, как устроена эта директива и как практические пресеты из блога Master.dev помогают навести идеальный порядок в адаптивной верстке.

Проклятие магических пикселей: почему старые брейкпоинты устарели

Традиционный подход к адаптивности страдает от трех фундаментальных пороков:

  1. Дублирование и ад поддержки: если дизайн-команда решает сдвинуть границу мобильного лейаута с 768px на 800px, инженеры вынуждены запускать глобальный автопоиск и замену по сотням CSS-модулей. Обязательно что-то пропустишь, и в продакшене появится нестыковка стилей.
  2. Ложные эвристики устройств: исторически мы привыкли считать: «если экран уже 768px — это мобильный тач-экран, если шире — это десктоп с мышью». Сегодня эта логика полностью сломалась. Современный планшет iPad Pro с экраном 13 дюймов и внешней клавиатурой с трекпадом может быть шире офисного ноутбука, но пользователь в любой момент может коснуться экрана пальцем. А компактный нетбук с экраном 11 дюймов управляется высокоточной мышью. Ориентироваться только на ширину окна в пикселях — тупиковый путь.
  3. Отсутствие семантики: абстрактная конструкция @media (hover: none) and (pointer: coarse) заставляет разработчика вспоминать спецификации, вместо того чтобы сразу понять суть намерения автора: «здесь мы увеличиваем хитбокс кнопки под палец на сенсорном экране».

Синтаксис @custom-media: переменные для логических медиавыражений

Директива @custom-media работает как объявление глобальной переменной для правил @media. Она связывает идентификатор с двумя дефисами (--name) с любым допустимым медиавыражением или логической комбинацией:

/* Базовые определения именованных выражений */
@custom-media --narrow-window (max-width: 600px);
@custom-media --mouse (hover: hover) and (pointer: fine);
@custom-media --touch (hover: none) and (pointer: coarse);

/* Комбинирование ранее созданных пресетов */
@custom-media --mobile-touch (--narrow-window) and (--touch);

/* Использование в компонентах интерфейса */
@media (--mouse) {
  .interactive-card:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
  }
}

@media (--touch) {
  .interactive-card {
    min-height: 48px; /* Увеличенная зона клика под палец */
  }
}

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

Пресеты Даниэля Шварца: модульная сетка, типы ввода и True HDR

Фронтенд-архитектор Даниэль Шварц сформулировал готовую систему именованных медиавыражений, разделенную на три прикладных блока:

  1. Типы ввода (Input Modalities): Вместо угадывания типа гаджета по ширине стекла пресеты проверяют реальный физический способ манипуляции:
    • --mouse: (hover: hover) and (pointer: fine) — мышь или трекпад с курсором;
    • --touch: (hover: none) and (pointer: coarse) — палец на смартфоне или планшете;
    • --stylus: (hover: none) and (pointer: fine) — высокоточный стилус на графическом планшете;
    • --air: (hover: hover) and (pointer: coarse) — жестовое управление в пространстве (Apple Vision Pro, Meta Quest);
    • --dpad: (hover: none) and (pointer: none) — кнопочный пульт телевизора Smart TV или геймпад.
  2. Модульная линейка брейкпоинтов с шагом 100px: Шварц предлагает отказаться от субъективных названий --mobile, --tablet и --desktop, которые у каждого дизайнера означают разные цифры, в пользу строгой числовой сетки:
    @custom-media --from-360 (min-width: 360px);
    @custom-media --from-480 (min-width: 480px);
    @custom-media --from-720 (min-width: 720px);
    @custom-media --from-1080 (min-width: 1080px);
    @custom-media --from-1440 (min-width: 1440px);
    
  3. Расширенный динамический диапазон (True HDR):
    @custom-media --true-hdr (dynamic-range: high) and (color-gamut: p3);
    

    Этот пресет позволяет активировать сверхъяркие цвета палитры Display P3 только на экранах, аппаратно поддерживающих HDR (OLED, mini-LED), предотвращая искажения на дешевых офисных мониторах.

Статус в браузерах и фоллбеки: PostCSS против container style()

На текущий момент нативная поддержка директивы @custom-media уже реализована в движке Gecko (Firefox 148+), однако пока скрыта за экспериментальным системным флагом layout.css.custom-media.enabled.

Как использовать этот синтаксис в продакшене прямо сейчас?

Основной проверенный путь — плагин postcss-custom-media. На этапе сборки утилита компилирует именованные пресеты в стандартный CSS:

// postcss.config.js
module.exports = {
  plugins: [
    require('postcss-custom-media')({
      importFrom: 'src/styles/custom-media.css'
    })
  ]
};

Второй современный путь без препроцессоров — использование стилистических контейнерных запросов @container style():

:root {
  @media (dynamic-range: high) and (color-gamut: p3) {
    --is-hdr: true;
  }
}

@container style(--is-hdr: true) {
  .hero-glow-badge {
    background: color(display-p3 1 0.1 0.2);
  }
}

Как мы отмечали в разборе 12 возможностей современного CSS, нативная платформа шаг за шагом забирает себе функционал, ради которого раньше приходилось подключать тяжелые препроцессоры Sass и Less.

Внедрение пресетов @custom-media на уровне дизайн-системы избавляет команду от путаницы в пикселях и закладывает надежный фундамент под любые устройства будущего.