
Cómo funciona @supports

- Un caso de uso clásico
- Hay una lógica de “no” en los bloques @supports, pero eso no significa que deba usarse siempre
- Es probable que @supports sea más útil con el tiempo.
- Cuando @supports no hace nada útil
- Hay extensiones de navegador para jugar con @supports
- Más casos de uso del mundo real para @supports
- Lógica en @supports
- Variante de JavaScript
- Prueba de selectores
- ¿Tu?
CSS tiene una característica interesante que nos permite probar si el navegador admite una propiedad particular o una combinación de propiedad:valor antes de aplicar un bloque de estilos, como cómo @media
coincide una consulta cuando, por ejemplo, el ancho de la ventana del navegador es más estrecho que un tamaño especificado. y luego el CSS que contiene entra en vigor. Del mismo modo, el CSS dentro de esta característica entrará en vigor cuando el valor por propiedad se esté probando sea compatible con el navegador actual. Esa característica se llama @supports
y se ve así:
@supports (display: grid) { .main { display: grid; }}
¿Por qué? Bueno, eso es un poco complicado. Personalmente, creo que no lo necesito con tanta regularidad. CSS tiene mecanismos de respaldo naturales, de modo que si el navegador no comprende una combinación de propiedad: valor, la ignorará y usará algo declarado antes si hay algo, gracias a la cascada. A veces, esto se puede utilizar para solucionar problemas y el resultado final es un poco menos detallado. Ciertamente no soy del tipo que tiene que ser lo mismo en todos los navegadores, pero tampoco soy del tipo que escribe elaboradas alternativas para acercarse. Generalmente prefiero una situación en la que una falla natural de una propiedad: el valor no hace nada drástico para destruir la funcionalidad.
Dicho esto, @supports
sin duda tiene casos de uso. Y, como descubrí mientras escribía esta publicación, muchas personas lo usan en muchas situaciones interesantes.
Un caso de uso clásico
El ejemplo que utilicé en la introducción es un ejemplo clásico que verás utilizado en muchos escritos sobre este tema. Aquí está un poco más desarrollado:
/* We're gonna write a fallback up here in a minute */@supports (display: grid) { .photo-layout { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-gap: 2rem; }}
¡Buena cuadrícula! La repetición y el autocompletado de columnas es una característica interesante de la cuadrícula CSS. Pero, por supuesto, hay navegadores que no soportan grid, o no soportan todas las características específicas que estoy usando arriba.
Por ejemplo, iOS incluyó compatibilidad con CSS Grid en la versión 10.2, pero iOS tiene compatibilidad con FlexBox desde la versión 7. Hay una brecha considerable de personas con dispositivos iOS más antiguos que admiten FlexBox pero no Grid. Estoy seguro de que hay más brechas de ejemplo como esa, pero probablemente entiendas la idea.
Estaba ejecutando una versión anterior de Mobile Safari y muchos, muchos, muchos, muchos sitios estaban completamente rotos y usaban grid.
Estoy esperando un año más o menos antes de meterme con eso.
– David Wells (@DavidWells) 6 de febrero de 2019
Puede ser aceptable dejar que la alternativa sea nada, dependiendo de los requisitos. Por ejemplo, elementos a nivel de bloque apilados verticalmente en lugar de un diseño de cuadrícula de varias columnas. Eso suele estar bien para mí. Pero digamos que no está bien, como una galería de fotos o algo que absolutamente necesita tener una estructura básica similar a una cuadrícula. En ese caso, comenzar con flexbox como predeterminado y usarlo @supports
para aplicar funciones de cuadrícula donde sean compatibles puede funcionar mejor…
.photo-layout { display: flex; flex-wrap: wrap; div { flex: 200px; margin: 1rem; }}@supports (display: grid) { .photo-layout { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-gap: 2rem; div { margin: 0; } }}
El “retroceso” es el código fuera del @supports
bloque (las propiedades encima del bloque en el ejemplo anterior), y el código de la cuadrícula está dentro o después. El @supports
bloqueo no cambia ninguna especificidad, por lo que necesitamos el orden de origen para ayudar a garantizar que las anulaciones funcionen.
Observe que tuve que restablecer el margen de los divs dentro del @supports
bloque. Ese es el tipo de cosas que encuentro un poco molestas. Hay suficientes cruces entre los dos escenarios que requieren ser muy conscientes de cómo se impactan entre sí.
¿Eso no te hace desear que se pudiera separar de manera completamente lógica?
Hay una lógica de “no” en los bloques @supports, pero eso no significa que deba usarse siempre
Jen Simmons puso este ejemplo en un artículo llamado Uso de consultas de funciones en CSS hace unos años:
/* Considered a BAD PRACTICE, at least if you're supporting IE 11 and iOS 8 and older */@supports not (display: grid) { /* Isolated code for non-support of grid */}@supports (display: grid) { /* Isolated code for support of grid */}
Observar al not
operador en el primer bloque. Se trata de buscar navegadores que no admiten grid para poder aplicar ciertos estilos a esos navegadores. La razón por la que este enfoque se considera una mala práctica es que se debe considerar la compatibilidad del navegador con @supports. . Eso es lo que hace que esto sea tan complicado.
Es muy atractivo escribir código en @supports
bloques lógicamente separados como ese porque entonces se comienza desde cero cada vez y no es necesario anular valores anteriores y lidiar con esos cambios de mentalidad lógicos. Pero volvamos a la misma situación de iOS que consideramos antes… @supports
enviado en iOS en la versión 9 (justo entre el momento en que flexbox se envió en iOS 7 y el grid en iOS 10.2). Eso significa que cualquier código de reserva de Flexbox en un @supports
bloque que use el not
operador para verificar la (display: grid) {}
compatibilidad no funcionará ni en iOS 7 ni en 8, lo que significa que la reserva ahora necesita una reserva para que no funcione en navegadores que de otro modo tendría. ¡Uf!
La razón principal para hacerlo @supports
es tener en cuenta implementaciones muy diferentes de algo dependiendo del soporte de características, donde resulta más fácil razonar y distinguir entre esas implementaciones si los bloques de código están separados.
Probablemente lleguemos a un punto en el que podamos usar bloques mutuamente excluyentes como ese sin preocupaciones. Hablando de que...
Es probable que @supports sea más útil con el tiempo.
Una vez que @supports
sea compatible con todos los navegadores que necesita, entonces es bueno comenzar a usarlo de manera más agresiva y sin tener que tener en cuenta la complicación de considerar si @supports
es compatible. Aquí está la tabla de soporte al respecto:
Estos datos de soporte del navegador son de Caniuse, que tiene más detalles. Un número indica que el navegador admite la función en esa versión y superiores.
Escritorio
Cromo | Firefox | ES DECIR | Borde | Safari |
---|---|---|---|---|
28 | 22 | No | 12 | 9 |
Móvil/Tableta
Android Cromo | Android Firefox | Androide | Safari en iOS |
---|---|---|---|
125 | 126 | 4.4 | 9.0-9.2 |
Básicamente, IE 11 y cualquier dispositivo iOS atascado en iOS 8 son los puntos débiles. Si sus requisitos ya los han superado, entonces puede usarlos @supports
más libremente.
La ironía es que no se han enviado muchas funciones CSS que tengan @supports
casos de uso grandes y claros, ¡pero hay algunas! Aparentemente, es posible probar cosas nuevas y sofisticadas como Houdini:
Utilizándolo en el sitio web de mi boda para comprobar el soporte de Houdini
– Sam Richard (@Snugug) 6 de febrero de 2019
(No estoy completamente seguro de qué pondrías en el @supports
bloque para hacer eso. ¿Alguien más ha hecho esto?)
Cuando @supports no hace nada útil
He visto una buena cantidad de @supports
usos en la naturaleza donde el resultado final es exactamente como sería sin usar. Por ejemplo…
@supports (transform: rotate(5deg)) { .avatar { transform: rotate(5deg); }}
En cierto nivel, eso tiene perfecto sentido lógico. Si se admiten transformaciones, úselas. Pero es innecesario si no sucede nada diferente en un escenario sin soporte. En este caso, la transformación puede fallar sin el @supports
bloque y el resultado es el mismo.
Aquí hay otro ejemplo de esa sacudida.
¡Hay dos de ellos!
- Administrador de consultas de funciones por Ire Aderinokun
- Extensión de alternancia de funciones CSS de Keith Clark
Ambos se centran en la idea de que podemos escribir @supports
bloques en CSS y luego activarlos y desactivarlos como si estuviéramos viendo una representación del código en un navegador que admite o no esa característica.
Aquí hay un video de la herramienta de Keith aplicada al escenario usando una cuadrícula con un respaldo de flexbox:
La herramienta de Ire, sobre la que escribió en el artículo Creación de la extensión DevTools del Administrador de consultas de funciones, tiene un enfoque ligeramente diferente en el sentido de que muestra las consultas de funciones que realmente escribieron en su CSS y proporciona opciones para activarlas. y desactivarlas. Sin embargo, no creo que funcione a través de iframes, así que abre el modo de depuración para usarlo en CodePen.
Más casos de uso del mundo real para @supports
Aquí hay uno de Erik Vorhes. Aquí estamos diseñando algunas casillas de verificación y botones de opción personalizados, pero los envuelve todo en un @supports
bloque. Ninguno de los estilos se aplica a menos que el bloque pase la verificación de soporte.
@supports (transform: rotate(1turn)) and (opacity: 0) { /* all the styling for Erik's custom checkboxes and radio buttons */}
Aquí hay varios más con los que me encontró:
- Joe Wright y Tiago Nunes mencionaron que lo usan para
position: sticky;
. ¡Me encantaría ver una demostración aquí! Es decir, cuando buscasposition: sticky;
, pero luego tienes que hacer algo diferente además de dejar que falle en un navegador que no lo soporta. - Keith Grant y Matthias Ott mencionan su uso para
object-fit: contain;
. Matthias tiene una demostración en la que se utilizan trucos de posicionamiento para hacer que una imagen llene un contenedor, lo que luego se hace más fácil y mejor a través de esa propiedad cuando está disponible. - Ryan Filler menciona usarlo para
mix-blend-mode
. Su ejemplo establece más opacidad en un elemento, pero simix-blend-mode
es compatible, usa un poco menos y esa propiedad que puede tener el efecto de ver a través de un elemento por sí sola.
.thing { opacity: 0.5;}@supports (mix-blend-mode: multiply) { .thing { mix-blend-mode: multiply; opacity: 0.75; }}
backdrop-filter
propiedad. Dice que “cuando es compatible, la opacidad del color de fondo a menudo necesita algunos ajustes”.@supports (-ms-ime-align:auto) { }
.clip-path
porque ajustar el tamaño o el relleno de un elemento se adaptará cuando el recorte no esté disponible.initial-letter
propiedad CSS que es bastante fantástica para las mayúsculas, pero se usa junto con otras propiedades que quizás no quieras aplicar en absoluto si initial-letter
no son compatibles (o si hay un escenario alternativo totalmente diferente).Aquí hay un bono de Nick Colley que no es @supports
, ¡ @media
sino! El espíritu es el mismo. Puede evitar ese estado de “ataque” en dispositivos táctiles como este:
@media (hover: hover) { a:hover { background: yellow; }}
Lógica en @supports
Básico:
@supports (initial-letter: 4) {}
No:
@supports not (initial-letter: 4) {}
Y:
@supports (initial-letter: 4) and (transform: scale(2)) {}
O:
@supports (initial-letter: 4) or (-webkit-initial-letter: 4) {}
Combinaciones:
@supports ((display: -webkit-flex) or (display: -moz-flex) or (display: flex)) and (-webkit-appearance: caret) {}
Variante de JavaScript
JavaScript tiene una API para esto. Para probar si existe…
if (window.CSS window.CSS.supports) { // Apparently old Opera had a weird implementation, so you could also do: // !!((window.CSS window.CSS.supports) || window.supportsCSS || false)}
Para usarlo, pásele la propiedad en un parámetro y el valor en otro:
const supportsGrid = CSS.supports("display", "grid");
…o ponerlo todo en una cadena reflejando la sintaxis CSS:
const supportsGrid = CSS.supports("(display: grid)");
Prueba de selectores
Al momento de escribir este artículo, solo Firefox admite este tipo de pruebas (detrás de un indicador experimental), pero hay una manera de probar la compatibilidad de selectores con @supports
. Demostración de MDN:
@supports selector(A B) {}
¿Tu?
Por supuesto, nos encantaría ver bolígrafos de @supports
casos de uso en los comentarios. ¡Así que compártelos!
Deja una respuesta