Які правила накладання медіа-запитів CSS накладаються?


88

Як ми точно розподіляємо медіа-запити, щоб уникнути дублювання?

Наприклад, якщо ми розглянемо код:

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

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

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

Що станеться з усіма підтримуючими браузерами рівно 20em і 45em?

Я бачив, як люди використовують такі речі, як 799px, а потім 800px, а як щодо ширини екрану 799.5 px? (Очевидно, не на звичайному дисплеї, а на сітківці?)


Мені найбільше цікаво відповісти тут, враховуючи специфікацію.


1
Здається, поточна назва вашого запитання не відповідає тому, що ви задаєте. Здається, перший рядок вмісту вашого запитання краще підходив би як заголовок :)
BoltClock

@BoltClock, дякую як завжди - я перемикав їх між собою; але як ви інтерпретували "розставлення медіа-запитів"?
Баумр

1
@Baumr: Гарне запитання - насправді я не зовсім розумію, що ви маєте на увазі під цим. Решту запитань я розумію і пишу відповідь.
BoltClock

1
Я б припустив, що якби у вас була ширина рівно 20em, то спочатку застосовуватимуться max-width: 20emвизначення, а потім застосовуватимуться і min-width: 20emвизначення.
користувач

1
@Baumr, я вважаю, що це просто так само, як і загальні декларації CSS. Оскільки ширина 20em задовольняє обом запитам, обидва визначення запиту будуть застосовані.
користувач

Відповіді:


108

Які правила накладання медіа-запитів CSS накладаються?

Каскад.

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

Що станеться з усіма підтримуючими браузерами рівно 20em і 45em?

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

Розглядаючи ваш приклад коду, додавши деякі фактичні правила стилю:

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

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

Коли область перегляду браузера має рівно 20em ширини, обидва ці медіа-запити повернуть істину. Каскадом, 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.

Схоже, у вас вже є приклад, який підводить нас до вашого останнього питання:

Я бачив, як люди використовують такі речі, як 799px, а потім 800px, а як щодо ширини екрану 799.5 px? (Очевидно, не на звичайному дисплеї, а на сітківці?)

Це я не зовсім впевнений; всі значення пікселів у CSS - це логічні пікселі, і мені було важко знайти браузер, який би повідомляв дробове значення пікселів для ширини області перегляду. Я пробував експериментувати з деякими фреймами, але нічого не міг придумати.

З моїх експериментів здається, що Safari на iOS округляє всі дробові значення пікселів, щоб переконатися, що одне з max-width: 799pxі min-width: 800pxзбігатиметься, навіть якщо область перегляду справді 799,5 пікселів (що, мабуть, відповідає попередньому).


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


2
@Baumr: Немає проблем, хоча я ще не зовсім закінчив - я пропустив ваше запитання щодо дублюючих медіа-запитів. Я оновив свою відповідь, і з цим я називаю це ніч. Ну і просто для ударів: медіа-запити - одна з моїх улюблених тем у CSS, але я не терплю терміна RWD;)
BoltClock

Болтлок, можливо, це був перший раз, коли я використав "RWD" насправді - ваш холодний прийом був відзначений, ха-ха! На добраніч, але коли ви повернетесь, перевірте оновлення, яке я вніс до початкового питання. Тепер подивимось на ваше оновлення ...
Баумр

BoltClock, чи варто виймати це оновлення та перетворювати його на власне запитання? Я відчуваю, що роблю це заплутаним
Баумр

@Baumr: Так, так набагато краще.
BoltClock

BoltClock: Я вийняв його і поставив у, сподіваюся, більш лаконічне запитання: Як уникнути перекриття запитів медіа? - якщо у вас є пропозиції щодо редагування, щоб зробити його більш застосовним для інших людей, будь ласка, поділіться. PS Це не дозволяє мені @ вас у коментарях.
Баумр,

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()не є частиною специфікації медіа-запиту і не буде працювати.
Jason T Featheringham
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.