Схема-дерево с примерами для печати, для мобильных и для всех остальных устройств
Иллюстрация: Кира Кустова

@media

Сайт может подстраиваться под обстоятельства благодаря этой директиве.

Время чтения: 13 мин

Кратко

Скопировано

Директива, которая позволяет задавать разные стили для разных параметров экрана — ширины, высоты, ориентации и даже типа устройства.

Пример

Скопировано

Сделаем элемент с классом block флекс-контейнером, когда ширина экрана 900 пикселей или больше:

        
          
          @media (min-width: 900px) {  .block {    display: flex;  }}
          @media (min-width: 900px) {
  .block {
    display: flex;
  }
}

        
        
          
        
      

Как понять

Скопировано

При вёрстке адаптивных сайтов часто нужно, чтобы какой-то набор стилей применился только при соблюдении определённых условий. Например, текст должен стать зелёным только при горизонтальной ориентации смартфона. Или блок займёт всю ширину родителя, если ширина экрана больше или равна 1500 пикселям. Для подобных случаев и существуют медиавыражения. Они помогают адаптировать вёрстку под разные экраны и устройства и при этом не писать лишний код.

Как пишется

Скопировано

В общем виде синтаксис выглядит так:

        
          
          @media [тип устройства] [характеристика устройства] {  /* CSS-правила */}
          @media [тип устройства] [характеристика устройства] {
  /* CSS-правила */
}

        
        
          
        
      

Например:

        
          
          @media print and (orientation: landscape) {  .block {    font-size: 25pt;  }}
          @media print and (orientation: landscape) {
  .block {
    font-size: 25pt;
  }
}

        
        
          
        
      

Здесь тип устройства — print (принтер), а характеристика устройства — orientation: landscape (альбомная ориентация). То есть при печати на листе в альбомной ориентации размер шрифта в блоке будет 25 пунктов.

Типы устройств

Скопировано

Есть три типа устройств, которые мы можем указать:

  • all — медиавыражение применится ко всем устройствам. Если не задать никакой тип, по умолчанию применится этот;
  • print — стили внутри такого медиавыражения применятся при печати на принтерах или экспорте в PDF, в том числе в режиме предпросмотра документа;
  • screen — для устройств с экранами.

В большинстве случаев, когда вы пишете стили только для экрана, указывать типы screen или all не нужно. Реальное практическое использование есть только у типа print.

Характеристики

Скопировано

Возможные характеристики устройства можно разделить на несколько категорий.

Характеристики устройства

Скопировано

Экран современных устройств может быть разделён на несколько частей при помощи складки или шарнира между экранами. Отдельные области экрана называют сегментами.

horizontal-viewport-segments — проверка на сколько сегментов по горизонтали разделён экран.

vertical-viewport-segments — проверка на сколько сегментов по вертикали разделён экран.

Значение в обоих случаях: положительное целое число.

        
          
          @media (horizontal-viewport-segments: 1) { … }
          @media (horizontal-viewport-segments: 1) {}

        
        
          
        
      

overflow-block — проверяет, как устройство поступает с контентом, непоместившимся в экран по блочной оси.

Значения:

  • none — контент обрезается, всё, что за пределами страницы, недоступно;
  • scroll — контент можно прокрутить;
  • optional-paged — контент можно прокрутить, но при необходимости он может быть разбит на страницы. Например, при помощи свойства break-inside;
  • paged — контент разбит на страницы. Как в случае с печатью на принтере.
        
          
          @media (overflow-block: paged) { … }
          @media (overflow-block: paged) {}

        
        
          
        
      

overflow-inline — проверяет, можно ли прокручивать содержимое, выходящее за пределы области просмотра по строчной оси.

Значения:

  • none — контент обрезается, всё, что за пределами страницы, недоступно;
  • scroll — контент можно прокрутить.
        
          
          @media (overflow-inline: scroll) { … }
          @media (overflow-inline: scroll) {}

        
        
          
        
      

grid — проверяет, является ли экран растровым (все современные экраны) или сеточным (старые телефоны или текстовые терминалы).

Значения: 0 для растровых экранов и 1 для сеточных экранов.

        
          
          @media (grid: 1) { … }
          @media (grid: 1) {}

        
        
          
        
      

resolution, min-resolution, max-resolution — проверяет разрешение устройства в dpi или dpcm.

Значение: число с нужными единицами измерения. Единицы измерения для разрешения устройства.

        
          
          @media (max-resolution: 300dpi) { … }
          @media (max-resolution: 300dpi) {}

        
        
          
        
      

Характеристики страницы и окна браузера

Скопировано

width, min-width, max-width — проверка ширины окна браузера, минимальной или максимальной ширин. Значение: положительное целое или дробное число с любыми доступными единицами измерения.

        
          
          @media (max-width: 1280px) { … }
          @media (max-width: 1280px) {}

        
        
          
        
      

height, min-height, max-height — проверка высоты окна браузера, минимальной или максимальной высот. Значение: положительное целое или дробное число с любыми доступными единицами измерения.

        
          
          @media (min-height: 30rem) { … }
          @media (min-height: 30rem) {}

        
        
          
        
      

orientation — ориентация окна браузера. Если высота окна браузера больше его ширины, то это портретная ориентация. Если наоборот, ширина больше высоты, то это альбомная ориентация.

Значения:

  • landscape — альбомная, горизонтальная ориентация;
  • portrait — портретная, вертикальная ориентация.
        
          
          @media (orientation: landscape) { … }
          @media (orientation: landscape) {}

        
        
          
        
      

aspect-ratio, min-aspect-ratio, max-aspect-ratio — соотношение между шириной и высотой окна, минимальное и максимальное соотношение. Значение: два целых положительных числа, разделённых слэшем.

        
          
          @media (aspect-ratio: 16 / 9) { … }
          @media (aspect-ratio: 16 / 9) {}

        
        
          
        
      

Качество отображения

Скопировано

display-mode — проверяет, в каком режиме сайт или приложение запущено.

Значения:

  • browser — сайт или приложение запущено во вкладке браузера;
  • fullscreen — сайт или приложение открыто в полноэкранном режиме;
  • minimal-ui — приложение запущено как отдельная программа, с минимальными элементами навигации;
  • picture-in-picture — приложение запущено в режиме «картинка в картинке», является отдельным окном поверх всех остальных программ, его можно передвинуть;
  • standalone — приложение запущено как нативная программа, не имеет элементов навигации браузера.

Не все эти режимы поддерживаются браузерами в данный момент. Проверяйте поддержку на Can I Use.

        
          
          @media (display-mode: fullscreen) { … }
          @media (display-mode: fullscreen) {}

        
        
          
        
      

scan — проверяет процесс отрисовки на девайсе.

Значения:

  • interlace — черезстрочная развёртка, при которой кадры делятся на строки и эти строки выводятся поочерёдно, чётные и нечётные;
  • progressive — прогрессивная развёртка, без особого порядка в кадрах.
        
          
          @media (scan: interlace) { … }
          @media (scan: interlace) {}

        
        
          
        
      

update — скорость обновления экрана.

Значения:

  • none — не обновляется;
  • slow — медленно;
  • fast — быстро.
        
          
          @media (update: slow) { … }
          @media (update: slow) {}

        
        
          
        
      

Цвет

Скопировано

color-gamut — примерный диапазон цветов, поддерживаемый браузером и устройством вывода.

Значения:

  • srgb — устройство поддерживает цветовое пространство sRGB;
  • p3 — устройство поддерживает цвета из пространства Display P3;
  • rec2020 — устройство поддерживает цветовое пространство REC. 2020.
        
          
          @media (color-gamut: p3) { … }
          @media (color-gamut: p3) {}

        
        
          
        
      

color, min-color, max-color — количество бит на цвет на устройстве вывода.

Значение: ноль или целое положительное число. Если ноль, то устройство чёрно-белое.

        
          
          @media (0 < color >= 8) { … }
          @media (0 < color >= 8) {}

        
        
          
        
      

color-index, min-color-index, max-color-index — количество цветов, которое может отображаться устройством.

Значение: ноль или целое положительное число. Если ноль, то у устройства нет таблицы цветов. Как правило, это значит, что устройство чёрно-белое.

        
          
          @media (min-color-index: 1200) { … }
          @media (min-color-index: 1200) {}

        
        
          
        
      

monochrome, min-monochrome, max-monochrome — количество бит на цвет на монохромном устройстве вывода.

Значение: ноль или целое положительное число. Если ноль, то устройство не монохромное.

        
          
          @media (monochrome: 0) { … }
          @media (monochrome: 0) {}

        
        
          
        
      

dynamic-range — комбинация уровня яркости, глубины цвета и контрастного соотношения для видео в браузере или устройстве вывода.

Значения:

  • standard — если у устройства есть экран;
  • high — устройство поддерживает высокую яркость, глубину и контраст.
        
          
          @media (dynamic-range: high) { … }
          @media (dynamic-range: high) {}

        
        
          
        
      

Взаимодействие

Скопировано

hover — проверка, позволяет ли основное устройство наводить указатель на элементы.

Значения:

  • none — нет устройства для наведения курсора (например, мышки) или девайс не может эмулировать ховер. Многие мобильные устройства эмулируют ховер при взаимодействии пальцами;
  • hover — есть устройство наведения курсора.
        
          
          @media (hover: hover) { … }
          @media (hover: hover) {}

        
        
          
        
      

any-hover — проверка, позволяет ли любое из устройств ввода наводить указатель на элементы.

Значения:

  • none — нет ни одного устройства ввода с указателем;
  • hover — хотя бы одно устройство ввода может управлять указателем. На устройствах с тач-скрином всегда будет как минимум возможность управлять курсором при помощи пальца или стилуса.
        
          
          @media (any-hover: hover) { … }
          @media (any-hover: hover) {}

        
        
          
        
      

pointer — проверка, является ли основное устройство ввода указателем, и насколько оно точное.

Значения:

  • none — основное устройство ввода не является указателем;
  • coarse — основное устройство ввода является указателем с ограниченной точностью. Как палец в случае с тач-скрином;
  • fine — основное устройство ввода — указатель с высокой точностью. Как курсор мыши.
        
          
          @media (pointer: coarse) { … }
          @media (pointer: coarse) {}

        
        
          
        
      

any-pointer — проверка, является ли любое из устройств ввода указателем, и насколько оно точное.

Значения:

  • none — как минимум одно устройство ввода не является указателем;
  • coarse — как минимум одно устройство ввода является указателем с ограниченной точностью. Как палец в случае с тач-скрином;
  • fine — как минимум одно устройство ввода — указатель с высокой точностью. Как курсор мыши.
        
          
          @media (any-pointer: fine) { … }
          @media (any-pointer: fine) {}

        
        
          
        
      

Характеристики с префиксом video-

Скопировано

video-dynamic-range — комбинация уровня яркости, глубины цвета и контрастного соотношения для видео в браузере или устройстве вывода.

Значения:

  • standard — если у устройства есть экран;
  • high — устройство поддерживает высокую яркость, глубину и контраст.
        
          
          @media (video-dynamic-range: high) { … }
          @media (video-dynamic-range: high) {}

        
        
          
        
      

Скрипты

Скопировано

scripting — проверяет, включены ли скрипты.

Значения:

  • none — скрипты отключены, недоступны;
  • initial-only — скрипты доступны только в момент загрузки документа. После загрузки скрипты не работают;
  • enabled — скрипты поддерживаются и доступны.
        
          
          @media (scripting: initial-only) { … }
          @media (scripting: initial-only) {}

        
        
          
        
      

Пользовательские настройки

Скопировано

prefers-color-scheme — определяет, какую тему предпочитает пользователь — светлую или тёмную.

Значения:

  • light — пользователь предпочитает светлую тему;
  • dark — пользователь предпочитает тёмную тему.
        
          
          @media (prefers-color-scheme: dark) { … }
          @media (prefers-color-scheme: dark) {}

        
        
          
        
      

prefers-reduced-motion — определяет, отключены ли анимации в системных настройках пользователя.

Значения:

  • no-preference — пользователь не отключил анимации в операционной системе (ОС);
  • reduce — пользователь отключил анимации в ОС.
        
          
          @media (prefers-reduced-motion: reduce) { … }
          @media (prefers-reduced-motion: reduce) {}

        
        
          
        
      

forced-colors — проверка на то, ограничивает ли браузер количество цветов в интерфейсе.

Значения:

  • none — специальная палитра цветов не выбрана;
  • active — включена специальная палитра цветов.
        
          
          @media (forced-colors: active) { … }
          @media (forced-colors: active) {}

        
        
          
        
      

inverted-colors — проверка, инвертируются ли цвета браузером или ОС.

Значения:

  • none — не включен режим инвертирования цветов в браузере или в ОС;
  • inverted — включен режим инвертирования цветов в браузере или в ОС.
        
          
          @media (inverted-colors: inverted) { … }
          @media (inverted-colors: inverted) {}

        
        
          
        
      

prefers-contrast — определяет, установлены ли настройки для увеличения или уменьшения контраста между цветом фона и текста.

Значения:

  • no-preference — настройка изменения контраста не включена;
  • less — включена настройка уменьшенного контраста;
  • more — включена настройка увеличенного контраста;
  • custom — включена настройка изменения контраста, при этом выбраны пользовательские настройки, определённые цвета. Аналогично forced-colors: active.
        
          
          @media (prefers-contrast: custom) { … }
          @media (prefers-contrast: custom) {}

        
        
          
        
      

Устаревшие

Скопировано

device-aspect-ratio — соотношение между шириной и высотой устройства вывода. Используйте aspect-ratio.

device-width — ширина дисплея устройства. Используйте width.

device-height — высота дисплея устройства. Используйте height.

Логические операторы

Скопировано

В медиавыражении может быть перечислено несколько условий через запятую. В таком случае стили применятся для любого из указанных условий. Например:

        
          
          @media (orientation: landscape), (max-width: 960px) {  .text {    color: tomato;  }}
          @media (orientation: landscape), (max-width: 960px) {
  .text {
    color: tomato;
  }
}

        
        
          
        
      

Такой код применится на всех устройствах с альбомной ориентацией экрана или на всех устройствах с шириной экрана менее 960 пикселей.

Часто в медиавыражениях может использоваться ключевое слово and, реже встречаются ключевые слова not и only.

Если мы пишем и тип устройства, и указываем характеристики, то после типа обязательно пишется and.

        
          
          @media print and (min-width: 320px) {  .link {    text-decoration: underline;  }}
          @media print and (min-width: 320px) {
  .link {
    text-decoration: underline;
  }
}

        
        
          
        
      

Также and пишется между характеристиками.

        
          
          @media (min-width: 320px) and (max-width: 640px) {  .link {    text-decoration: underline;  }}
          @media (min-width: 320px) and (max-width: 640px) {
  .link {
    text-decoration: underline;
  }
}

        
        
          
        
      

Ключевое слово not используется для отрицания выражения. Оно имеет низкий приоритет и применяется в последнюю очередь. Например:

        
          
          @media not screen and (min-width: 380px) {  .block {    display: flex;  }}
          @media not screen and (min-width: 380px) {
  .block {
    display: flex;
  }
}

        
        
          
        
      

Здесь сначала вычислится выражение «для всех экранов с минимальной шириной 380 пикселей», а потом оно инвертируется — «для всех устройств, кроме устройств с экранами с минимальной шириной 380 пикселей». То есть будет читаться браузером как:

        
          
          @media not (screen and (min-width: 380px)) {  .block {    display: flex;  }}
          @media not (screen and (min-width: 380px)) {
  .block {
    display: flex;
  }
}

        
        
          
        
      

При использовании not в медиавыражениях с запятой инвертируется только та часть выражения, где указан not. Например:

        
          
          @media not screen and (height: 500px), print and (height: 700px) {  .text {    color: tomato;  }}
          @media not screen and (height: 500px), print and (height: 700px) {
  .text {
    color: tomato;
  }
}

        
        
          
        
      

Чтобы лучше понять, как выполнится этот пример, можно добавить дополнительные группирующие скобки:

        
          
          @media (not (screen and (height: 500px))), print and (height: 700px) {  .text {    color: tomato;  }}
          @media (not (screen and (height: 500px))), print and (height: 700px) {
  .text {
    color: tomato;
  }
}

        
        
          
        
      

Поскольку запятая в медиавыражении означает лишь перечисление, то not в первой части выражения не будет распространяться на вторую, и инвертируется только часть «для всех экранов с высотой окна браузера 500 пикселей».

Ключевое слово only иногда встречается перед указанием типа устройства — оно используется для того, чтобы старые браузеры, которые не поддерживают медиавыражения, не применяли указанные стили. Современные браузеры никак не реагируют на only.

        
          
          @media only screen and (max-width: 600px) {  body {    background-color: cornflowerblue;  }}
          @media only screen and (max-width: 600px) {
  body {
    background-color: cornflowerblue;
  }
}

        
        
          
        
      

Синтаксис диапазонов

Скопировано

В современных браузерах можно использовать синтаксис диапазонов для всех условий, где значение — число. Новые операторы <, >, >= и <= более интуитивно указывают, например, для каких размеров экрана применять правила из медиавыражения. На самом деле операторы не новые, каждый знаком с ними из курса школьной математики, но в медиавыражениях это новинка.

Предположим, что цвет должен стать красным на ширине больше 680 пикселей и меньше 1280 пикселей.

Со старым синтаксисом пишете два правила, объединённых логическим оператором:

        
          
          @media (min-width: 680px) and (max-width: 1280px) {  p {    color: red;  }}
          @media (min-width: 680px) and (max-width: 1280px) {
  p {
    color: red;
  }
}

        
        
          
        
      

В новом синтаксисе используете одно правило, где указываете крайние точки и применяете новые операторы.

        
          
          @media (680px <= width >= 1280px) {  p {    color: red;  }}
          @media (680px <= width >= 1280px) {
  p {
    color: red;
  }
}

        
        
          
        
      

Подсказки

Скопировано

💡 Для вёрстки от мобильных (mobile first) лучше использовать медиавыражения с min-width и располагать их в порядке увеличения ширины экрана; для вёрстки от десктопа (desktop first) — max-width, и располагать выражения в обратном порядке.

💡 К сожалению, внутри медиавыражений пока нельзя использовать кастомные свойства. А это было бы очень удобно. Тогда мы бы вынесли брейкпоинты в переменные и не вспоминали бы о них каждый раз. Ещё не искали бы ширину, на которой должен быть переход между мобильным и планшетом.

На практике

Скопировано

Лена Райан советует

Скопировано

🛠 медиавыражения можно вкладывать в медиавыражения и другие директивы:

        
          
          @media (min-width: 520px) {  @media (max-width: 1080px) {    .cell {      background: peachpuff;    }  }}
          @media (min-width: 520px) {
  @media (max-width: 1080px) {
    .cell {
      background: peachpuff;
    }
  }
}

        
        
          
        
      
        
          
          @supports (position: sticky) {  @media (min-width: 1080px) {    .block {      position: sticky;    }  }}
          @supports (position: sticky) {
  @media (min-width: 1080px) {
    .block {
      position: sticky;
    }
  }
}

        
        
          
        
      

Сергей Зубов советует

Скопировано

🛠 Если на проекте используются препроцессоры — удобно использовать миксины для часто употребляемых медиавыражений.

Например код на SCSS:

        
          
          $tablet-min: 768px;@mixin tablet {  @media (min-width: $tablet-min) {    @content;  }}
          $tablet-min: 768px;

@mixin tablet {
  @media (min-width: $tablet-min) {
    @content;
  }
}

        
        
          
        
      

Использование миксина:

        
          
          .header {  color: red;  @include tablet {    color: white;  }}
          .header {
  color: red;

  @include tablet {
    color: white;
  }
}

        
        
          
        
      

Или с помощью LESS:

        
          
          @tablet: 768px;.tablet(@rules) {  @media (min-width: @tablet) {    @rules();  }}
          @tablet: 768px;

.tablet(@rules) {
  @media (min-width: @tablet) {
    @rules();
  }
}

        
        
          
        
      

Использование:

        
          
          .header {  color: red;  .tablet({    color: white;  });}
          .header {
  color: red;

  .tablet({
    color: white;
  });
}

        
        
          
        
      

На собеседовании

Скопировано
Задать вопрос в рубрику
🤚 Я знаю ответ

Это вопрос без ответа. Вы можете помочь! Почитайте о том, как контрибьютить в Доку.