Dlaczego kolejność zapytań o media ma znaczenie w CSS?

80

Ostatnio projektuję witryny, które są bardziej responsywne i często korzystam z zapytań o media CSS. Zauważyłem, że kolejność definiowania zapytań o media ma znaczenie. Nie testowałem tego w każdej przeglądarce, ale tylko w Chrome. Czy istnieje wytłumaczenie tego zachowania? Czasami jest to frustrujące, gdy witryna nie działa tak, jak powinna i nie masz pewności, czy jest to zapytanie, czy kolejność, w jakiej zostało napisane.

Oto przykład:

HTML

<body>
    <div class="one"><h1>Welcome to my website</h1></div>
    <div class="two"><a href="#">Contact us</a></div>
</body>

CSS:

body{
font-size:1em; /* 16px */
}

.two{margin-top:2em;}



/* Media Queries */

@media (max-width: 480px) {
    .body{font-size: 0.938em;}

}
/* iphone */
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
    body {font-size: 0.938em;}
}
/*if greater than 1280x800*/
@media (min-width: 1200px) {
       .two{margin-top:8em;}
            }
/*1024x600*/
@media (max-height: 600px) {
       .two{margin-top:4em;}
}
/*1920x1024*/
@media (min-height: 1020px) {
       .two{margin-top:9em;}
}
/*1366x768*/
@media (min-height: 750px) and (max-height: 770px) {
       .two{margin-top:7em;}
}

Jednak gdybym napisał zapytanie o 1024x600 w ostatnim, przeglądarka zignorowałaby ją i zastosowała wartość marginesu określoną na początku CSS (margin-top: 2em).

/* Media Queries - Re-arranged version */

@media (max-width: 480px) {
    .body{font-size: 0.938em;}
}
/* iphone */
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
    body {font-size: 0.938em;}
}
/*if greater than 1280x800*/
@media (min-width: 1200px) {
       .two{margin-top:8em;}
}
/*1920x1024*/
@media (min-height: 1020px) {
       .two{margin-top:9em;}
}
/*1366x768*/
@media (min-height: 750px) and (max-height: 770px) {
       .two{margin-top:7em;}
}
 /*1024x600*/
@media (max-height: 600px) {
       .two{margin-top:4em;}
}

Jeśli moje rozumienie zapytań o media jest prawidłowe, kolejność nie powinna mieć znaczenia, ale wydaje się, że tak. Jaki może być tego powód?

dsignr
źródło

Odpowiedzi:

139

To jest zgodne z projektem CSS - Cascading Style Sheet.

Oznacza to, że jeśli zastosujesz dwie reguły, które kolidują z tymi samymi elementami, wybierze ostatnią zadeklarowaną, chyba że pierwsza ma !importantznacznik lub jest bardziej szczegółowa (np. html > bodyVs just body, ta druga jest mniej szczegółowa).

Tak więc, biorąc pod uwagę ten CSS

@media (max-width: 600px) {
  body {
    background: red;
  }
}

@media (max-width: 400px) {
  body {
    background: blue;
  }
}

jeśli okno przeglądarki ma szerokość 350 pikseli, tło będzie niebieskie, podczas gdy w tym CSS

@media (max-width: 400px) {
  body {
    background: blue;
  }
}

@media (max-width: 600px) {
  body {
    background: red;
  }
}

i przy tej samej szerokości okna tło będzie czerwone. Obie reguły są rzeczywiście dopasowane, ale druga to ta, która jest stosowana, ponieważ jest ostatnią regułą.

Wreszcie z

@media (max-width: 400px) {
  body {
    background: blue !important;
  }
}

@media (max-width: 600px) {
  body {
    background: red;
  }
}

lub

@media (max-width: 400px) {
  html > body {
    background: blue;
  }
}

@media (max-width: 600px) {
  body {
    background: red;
  }
}

tło będzie niebieskie (z oknem o szerokości 350 pikseli).

Alessandro Vendruscolo
źródło
12
Dziękuję Ci. Nigdy nie przypuszczałem, że taka prosta logika zrujnowałaby mi sen podczas wspólnych nocy. Dzięki.
dsignr
W arkuszu stylów, jeśli zastosowano te same reguły bez zapytania o media, a następnie w zapytaniu o media dla urządzeń mobilnych z małym ekranem i jest kilka obrazów do pobrania. Więc co by się stało, czy przeglądarka zignoruje reguły bez zapytania o media i zastosuje tylko określone reguły zapytania o media?
20

Lub możesz po prostu dodać min-width do większego zapytania / ych mediów i nie mieć żadnych problemów, niezależnie od kolejności.

@media (min-width: 400.1px) and (max-width: 600px) {
  body {
    background: red;
  }
}

@media (max-width: 400px) {
  body {
    background: blue;
  }
}

Używając tego kodu, w dowolnej kolejności, kolor tła będzie zawsze czerwony dla rozdzielczości o szerokości 400,1-600 pikseli i zawsze niebieski dla rozdzielczości o szerokości 400 pikseli lub mniej.

Liran H.
źródło
9
Wzdrygam się na widok wartości takiej jak 400,1px w CSS. Lub 1023px, 1025px itd.
Monstieur