Каковы правила перекрытия медиа-запросов CSS?

89

Как точно распределить медиа-запросы, чтобы избежать дублирования?

Например, если мы рассмотрим код:

@media (max-width: 20em) {
    /* for narrow viewport */
}

@media (min-width: 20em) and (max-width: 45em) {
    /* slightly wider viewport */
}

@media (min-width: 45em) {
    /* everything else */
}

Что будет происходить во всех поддерживающих браузерах ровно при 20 и 45 em?

Я видел, как люди использовали: 799 пикселей, а затем 800 пикселей, но как насчет ширины экрана 799,5 пикселей? (Явно не на обычном дисплее, а на сетчатке?)


Меня больше всего интересует ответ, учитывая спецификацию.

Баумр
источник
1
Ваш текущий заголовок вопроса не соответствует тому, что вы задаете. Похоже, что первая строка вашего вопроса больше подходит под заголовок :)
BoltClock
@BoltClock, спасибо как всегда - я их поменял; но как вы интерпретировали «разнесение медиа-запросов»?
Baumr
1
@Baumr: Хороший вопрос - на самом деле я не совсем понимаю, что вы имеете в виду. В остальном вопрос разбираюсь и пишу ответ.
BoltClock
1
Я бы предположил, что если бы у вас была ширина ровно 20em, тогда он сначала применил бы max-width: 20emопределения, а затем также применил бы min-width: 20emопределения.
пользователь
1
@Baumr, я считаю, что это просто каскадирование, как и общие объявления CSS. Поскольку ширина 20em удовлетворяет оба запроса, будут применяться оба определения запроса.
пользователь

Ответы:

109

Каковы правила перекрытия медиа-запросов CSS?

Каскад.

@mediaправила прозрачны для каскада, поэтому, когда два или более @mediaправила совпадают одновременно, браузер должен применить стили во всех правилах, которые соответствуют, и соответствующим образом разрешить каскад. 1

Что будет происходить во всех поддерживающих браузерах ровно при 20 и 45 em?

При ширине ровно 20em ваш первый и второй медиа-запросы будут совпадать. Браузеры будут применять стили как в @mediaправилах, так и в каскаде соответственно, поэтому, если есть какие-либо конфликтующие правила, которые необходимо переопределить, побеждает последнее объявленное (с учетом определенных селекторов !importantи т. Д.). То же самое для второго и третьего медиа-запроса, когда ширина области просмотра составляет точно 45 мкм.

Учитывая ваш пример кода, с добавлением некоторых фактических правил стиля:

@media (max-width: 20em) {
    .sidebar { display: none; }
}

@media (min-width: 20em) and (max-width: 45em) {
    .sidebar { display: block; float: left; }
}

Когда окно просмотра браузера имеет ширину ровно 20 мкм, оба эти медиа-запроса вернут true. Каскадом display: blockотменяетdisplay: none и float: leftбудет применяться к любому элементу с классом .sidebar.

Вы можете думать об этом как о применении правил, как если бы медиа-запросов не было с самого начала:

.sidebar { display: none; }
.sidebar { display: block; float: left; }

Другой пример того, как происходит каскад, когда браузер соответствует двум или более медиа-запросам, можно найти в этом другом ответе .

Однако имейте в виду, что если у вас есть объявления, которые не перекрываются в обоих @mediaправилах, тогда будут применяться все эти правила. Здесь происходит объединение деклараций в обоих @mediaправилах, а не только последнее полностью отменяет первое ... что подводит нас к вашему предыдущему вопросу:

Как точно распределить медиа-запросы, чтобы избежать дублирования?

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

Помните , что min-и max-префиксы означает «минимальный включено» и «максимально включено»; это означает (min-width: 20em)и(max-width: 20em) оба соответствуют окно просмотра, которое точно 20em в ширину.

Похоже, у вас уже есть пример, который подводит нас к вашему последнему вопросу:

Я видел, как люди использовали: 799 пикселей, а затем 800 пикселей, но как насчет ширины экрана 799,5 пикселей? (Явно не на обычном дисплее, а на сетчатке?)

В этом я не совсем уверен; все значения пикселей в CSS являются логическими пикселями, и мне было трудно найти браузер, который сообщал бы дробное значение пикселя для ширины области просмотра. Я пробовал поэкспериментировать с некоторыми фреймами, но ничего не смог придумать.

Судя по моим экспериментам, Safari на iOS округляет все дробные значения пикселей, чтобы гарантировать совпадение одного из max-width: 799pxи min-width: 800px, даже если область просмотра действительно составляет 799,5 пикселей (что, очевидно, соответствует первому).


1 Хотя ничего из этого явно не указано ни в модуле Conditional Rules, ни в модуле Cascade (последний из которых в настоящее время планируется переписать), предполагается, что каскад будет происходить нормально, поскольку в спецификации просто говорится о применении стилей в любых и все @mediaправила, соответствующие браузеру или носителю.

BoltClock
источник
2
@Baumr: Нет проблем, хотя я еще не закончил - я пропустил ваш вопрос о наложении медиа-запросов. Я обновил свой ответ, и на этом я заканчиваю ночь. Да и просто для удовольствия: медиа-запросы - одна из моих любимых тем в CSS, но я терпеть не могу термин RWD;)
BoltClock
BoltClock, возможно, я впервые использовал "RWD" на самом деле - ваш холодный прием был отмечен, ха-ха! Спокойной ночи, но когда вы вернетесь, ознакомьтесь с обновлением исходного вопроса, которое я внес. Теперь посмотрим на ваше обновление ...
Баумр
BoltClock, я должен взять это обновление и сделать его отдельным вопросом? Я чувствую, что делаю это запутанным
Баумр
@Baumr: Ага, так намного лучше.
BoltClock
BoltClock: Я вынул его и задал, надеюсь, более лаконичный вопрос: как избежать наложения медиа-запросов? - если у вас есть предложения по редактированию, чтобы сделать его более применимым к другим людям, поделитесь. PS Это не пускает меня @ вас в комментарии.
Baumr
6

Я пробовал, как рекомендовано здесь:

@media screen and (max-width: calc(48em - 1px)) {
    /*mobile styles*/
}
@media screen and (min-width: 48em) {
    /*desktop styles*/
}

но обнаружил, что это не очень хорошая идея, потому что сейчас он не работает в Chrome ни на моем рабочем столе Ubuntu, ни на моем телефоне Android. (как объясняется здесь: calc () не работает в медиа-запросах ) Но я нашел способ получше ...

@media screen and (max-width: 47.9999em) {
    /*mobile styles*/
}
@media screen and (min-width: 48em) {
    /*desktop styles*/
}

и бац!

Пьер-Вертюм Ларивьер
источник
Это должен быть принятый ответ. BoltClock дал педантичный ответ, но это самый полезный ответ!
Джон Хенкель
2

calc()можно использовать, чтобы обойти это (min-width: 50em and max-width: calc(50em - 1px)будет правильно сложено), но плохая поддержка браузера, и я бы не рекомендовал это.

@media (min-width: 20em) and (max-width: calc(45em - 1px)) {
    /* slightly wider viewport */
}

Информация:

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

Милче Патерн
источник
4
calc()не является частью спецификации медиа-запроса и не будет работать.
Джейсон Т. Фезерингем