¿Cuáles son las reglas para la superposición de consultas de medios CSS?

88

¿Cómo espaciamos las consultas de medios con precisión para evitar superposiciones?

Por ejemplo, si consideramos el código:

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

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

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

¿Qué pasará, en todos los navegadores compatibles, exactamente a 20em y 45em?

He visto a gente usar: cosas como 799px y luego 800px, pero ¿qué pasa con un ancho de pantalla de 799.5 px? (Obviamente no en una pantalla normal, sino en una retina)


Tengo más curiosidad por la respuesta aquí considerando la especificación.

Baumr
fuente
1
El título de su pregunta actual no parece coincidir con lo que está preguntando. Parece que la primera línea del contenido de su pregunta encajaría mejor como título :)
BoltClock
@BoltClock, gracias como siempre - los cambié; pero, ¿cómo interpretó "espaciar las consultas de los medios"?
Baumr
1
@Baumr: Buena pregunta. En realidad, no entiendo del todo lo que quieres decir con eso. El resto de la pregunta lo entiendo y estoy escribiendo una respuesta.
BoltClock
1
Asumiría que si tuviera un ancho de exactamente 20 em, entonces primero aplicaría las max-width: 20emdefiniciones, luego también aplicaría las min-width: 20emdefiniciones.
usuario
1
@Baumr, creo que está en cascada igual que las declaraciones generales de CSS. Dado que un ancho de 20em satisface ambas consultas, se aplicarán ambas definiciones de consulta.
usuario

Respuestas:

108

¿Cuáles son las reglas para la superposición de consultas de medios CSS?

Cascada.

@mediaLas reglas son transparentes para la cascada, por lo que cuando dos o más @mediareglas coinciden al mismo tiempo, el navegador debe aplicar los estilos en todas las reglas que coincidan y resolver la cascada en consecuencia. 1

¿Qué pasará, en todos los navegadores compatibles, exactamente a 20em y 45em?

Con exactamente 20 em de ancho, su primera y segunda consulta de medios coincidirán. Los navegadores aplicarán estilos en ambas @mediareglas y en cascada en consecuencia, por lo que si hay reglas en conflicto que deben anularse, gana la última declarada (teniendo en cuenta selectores específicos !important, etc.). Lo mismo ocurre con la segunda y tercera consulta de medios cuando la ventana gráfica tiene exactamente 45 em de ancho.

Teniendo en cuenta su código de ejemplo, con algunas reglas de estilo reales agregadas:

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

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

Cuando la ventana del navegador tiene exactamente 20 em de ancho, ambas consultas de medios volverán verdaderas. Por la cascada, display: blockanula display: noney float: leftse aplicará a cualquier elemento de la clase .sidebar.

Puede pensar en ello como una aplicación de reglas como si las consultas de medios no estuvieran allí para empezar:

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

Otro ejemplo de cómo ocurre la cascada cuando un navegador coincide con dos o más consultas de medios se puede encontrar en esta otra respuesta .

Sin embargo, tenga en cuenta que si tiene declaraciones que no se superponen en ambas @mediareglas, se aplicarán todas esas reglas. Lo que sucede aquí es una unión de las declaraciones en ambas @mediareglas, no solo la última anula por completo la primera ... lo que nos lleva a su pregunta anterior:

¿Cómo espaciamos las consultas de medios con precisión para evitar superposiciones?

Si desea evitar la superposición, simplemente debe escribir consultas de medios que sean mutuamente excluyentes.

Recuerde que los prefijos min-y max-significan "mínimo inclusivo" y "máximo inclusivo"; este medio (min-width: 20em)y (max-width: 20em)coincidirá tanto una ventana que es exactamente 20em amplia.

Parece que ya tienes un ejemplo, lo que nos lleva a tu última pregunta:

He visto a gente usar: cosas como 799px y luego 800px, pero ¿qué pasa con un ancho de pantalla de 799.5 px? (Obviamente no en una pantalla normal, sino en una retina)

De esto no estoy del todo seguro; todos los valores de píxeles en CSS son píxeles lógicos, y me ha costado mucho encontrar un navegador que informe un valor de píxel fraccionario para un ancho de ventana gráfica. He intentado experimentar con algunos iframes pero no he podido encontrar nada.

Según mis experimentos, parecería que Safari en iOS redondea todos los valores de píxeles fraccionarios para garantizar que cualquiera de max-width: 799pxy min-width: 800pxcoincida, incluso si la ventana gráfica es realmente 799.5px (que aparentemente coincide con el primero).


1 Aunque nada de esto se indica explícitamente ni en el módulo de Reglas condicionales ni en el módulo Cascade (el último de los cuales está actualmente programado para una reescritura), se da a entender que la cascada tiene lugar normalmente, ya que la especificación simplemente dice que se apliquen estilos en cualquier y todas las @mediareglas que coincidan con el navegador o el medio.

BoltClock
fuente
2
@Baumr: No hay problema, aunque todavía no había terminado, me había perdido su pregunta sobre consultas de medios superpuestas. Actualicé mi respuesta, y con eso lo llamo una noche. Ah, y solo por diversión: las consultas de medios son uno de mis temas favoritos en CSS, pero no soporto el término RWD;)
BoltClock
BoltClock, puede que haya sido la primera vez que usé "RWD" en realidad - ¡se ha notado su recepción fría, jaja! Buenas noches, pero cuando regreses, mira la actualización que hice a la pregunta original. Ahora para ver su actualización ...
Baumr
BoltClock, ¿debería sacar esa actualización y convertirla en su propia pregunta? Siento que estoy haciendo esto complicado
Baumr
@Baumr: Sí, es mucho mejor así.
BoltClock
BoltClock: Lo saqué y lo puse en una pregunta, con suerte, más concisa: ¿Cómo evitar la superposición de consultas de medios? - Si tiene alguna sugerencia de edición para que sea más aplicable a otras personas, compártala. PD: No me deja @ usted en los comentarios.
Baumr
6

He intentado como se recomienda aquí:

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

pero descubrí que esta no era una buena idea porque no funciona en Chrome en este momento ni en mi escritorio Ubuntu ni en mi teléfono Android. (como se explica aquí: calc () no funciona dentro de las consultas de medios ) Pero encontré una mejor manera ...

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

y bam!

Pierre-Verthume Larivière
fuente
Esta debería ser la respuesta aceptada. BoltClock proporcionó la respuesta pedante, ¡pero esta respuesta es la más útil!
John Henckel
2

calc()se puede utilizar para solucionar esto (min-width: 50em and max-width: calc(50em - 1px)se apilará correctamente), pero la compatibilidad con el navegador es deficiente y no lo recomendaría.

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

Infos:

Algunos otros mencionaron que no usar la emunidad ayudaría en el apilamiento de sus consultas.

Milche Patern
fuente
4
calc()no forma parte de la especificación de consulta de medios y no funcionará.
Jason T Featheringham