Media queries

@media — правило CSS, которое применяет стили только при выполнении указанных условий: ширина экрана, ориентация, тип устройства, предпочтения пользователя и другие характеристики.

Зачем нужно

Один сайт должен работать на экранах от 320px (телефон) до 2560px (4K-монитор). Media queries позволяют адаптировать layout, размеры шрифтов, отступы и даже показ/скрытие элементов в зависимости от устройства и предпочтений пользователя.

Где используется

  • Адаптивные layout-ы (мобильный → планшет → десктоп)
  • Изменение навигации для мобильных
  • Печатные стили (@media print)
  • Предпочтения пользователя (тёмная тема, анимации)
  • Feature queries (@supports)

Предпосылки

Синтаксис

/* Базовый синтаксис */
@media (условие) {
  /* CSS-правила */
}

/* Тип медиа + условие */
@media screen and (min-width: 768px) {
  .sidebar { display: block; }
}

/* Только тип медиа */
@media print {
  .no-print { display: none; }
}

Условия по ширине

min-width (Mobile First)

/* Базовые стили — для мобильных */
.container {
  padding: 16px;
}

/* Планшет и выше */
@media (min-width: 768px) {
  .container {
    padding: 24px;
    max-width: 720px;
    margin-inline: auto;
  }
}

/* Десктоп */
@media (min-width: 1024px) {
  .container {
    max-width: 960px;
  }
}

/* Большой десктоп */
@media (min-width: 1280px) {
  .container {
    max-width: 1200px;
  }
}

max-width (Desktop First)

/* Базовые стили — для десктопа */
.sidebar {
  width: 300px;
}

/* Планшет и ниже */
@media (max-width: 1023px) {
  .sidebar {
    width: 200px;
  }
}

/* Мобильные */
@media (max-width: 767px) {
  .sidebar {
    display: none;
  }
}

Диапазон (range syntax)

/* Только планшеты: 768px — 1023px */
@media (min-width: 768px) and (max-width: 1023px) {
  .layout { grid-template-columns: 1fr 1fr; }
}

/* Новый синтаксис (Level 4) — более читаемый */
@media (768px <= width < 1024px) {
  .layout { grid-template-columns: 1fr 1fr; }
}

/* Широкие экраны */
@media (width >= 1280px) {
  .container { max-width: 1200px; }
}

Популярные breakpoints

/* Мобильные */
/* < 576px — всё по умолчанию (Mobile First) */

/* Маленький планшет */
@media (min-width: 576px) { /* sm */ }

/* Планшет */
@media (min-width: 768px) { /* md */ }

/* Маленький десктоп / ландшафтный планшет */
@media (min-width: 1024px) { /* lg */ }

/* Десктоп */
@media (min-width: 1280px) { /* xl */ }

/* Большой десктоп */
@media (min-width: 1536px) { /* 2xl */ }

Не привязывайтесь к конкретным устройствам. Breakpoints должны определяться контентом — когда layout «ломается», добавляйте media query.

Комбинирование условий

/* AND — оба условия */
@media (min-width: 768px) and (orientation: landscape) {
  /* Планшет в ландшафтном режиме */
}

/* OR — через запятую */
@media (max-width: 600px), (orientation: portrait) {
  /* Узкий экран ИЛИ портретная ориентация */
}

/* NOT — отрицание */
@media not print {
  /* Не для печати */
}

/* ONLY — для старых браузеров */
@media only screen and (min-width: 768px) {
  /* Игнорируется старыми браузерами, которые не понимают media queries */
}

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

Тёмная тема

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1a2e;
    --text: #e9ecef;
    --surface: #16213e;
  }
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #ffffff;
    --text: #333333;
    --surface: #f8f9fa;
  }
}

Ограничение анимаций

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Контрастность

@media (prefers-contrast: high) {
  .button {
    border: 2px solid black;
  }
}

@media print

@media print {
  /* Скрыть навигацию, футер, кнопки */
  nav, footer, .no-print, button {
    display: none !important;
  }

  /* Чёрный текст на белом фоне */
  body {
    color: black;
    background: white;
    font-size: 12pt;
  }

  /* Показать URL ссылок */
  a[href]::after {
    content: " (" attr(href) ")";
    font-size: 0.8em;
  }

  /* Избегать разрывов внутри элементов */
  .card, img {
    break-inside: avoid;
  }
}

@supports — Feature queries

/* Проверить поддержку свойства */
@supports (display: grid) {
  .layout {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
  }
}

/* Fallback */
@supports not (display: grid) {
  .layout {
    display: flex;
    flex-wrap: wrap;
  }
}

/* Комбинация */
@supports (display: grid) and (gap: 20px) {
  .grid {
    display: grid;
    gap: 20px;
  }
}

/* Проверка селектора */
@supports selector(:has(*)) {
  .parent:has(.active) {
    background: #e6f0ff;
  }
}

Частые ошибки

  1. Breakpoints от устройств, а не от контента — iPhone 14 = 393px, но через год будут другие размеры
  2. Перекрывающиеся диапазоны:
    /* ОШИБКА — 768px попадает в оба */
    @media (max-width: 768px) { }
    @media (min-width: 768px) { }
    /* ПРАВИЛЬНО */
    @media (max-width: 767px) { }
    @media (min-width: 768px) { }
    
  3. Слишком много breakpoints — обычно достаточно 3–4
  4. Забыли <meta name="viewport"> — без него media queries не работают на мобильных:
    <meta name="viewport" content="width=device-width, initial-scale=1">
    

Практика

  • Создать Mobile First layout с 3 breakpoints
  • Добавить @media print стили
  • Реализовать тёмную тему через prefers-color-scheme
  • Использовать @supports для progressive enhancement
  • Применить range syntax (width >= 768px)

Связанные темы

Ресурсы