Uso de Feature Queries en CSS

26 octubre, 2016 2:36 por

Esta es una traducción del artículo original publicado en el blog de Mozilla Hacks.

Hay una herramienta en CSS de la que es posible que no hayas oído hablar todavía. Es de gran alcance. Existe desde hace algún tiempo. Y probablemente va a convertirse en una de tus cosas preferidas del CSS.

Observa, la regla @supports. También conocida como Feature Queries (consulta de característica).

Con @supports, puedes hacer una pequeña prueba en tu CSS para ver si una particular “característica” (propiedad o valor CSS) es soportada, y aplicar un bloque de código (o no) basándote en la respuesta. Como ésta:

@supports (display: grid) {
   // código que funcionará solo si la cuadrícula CSS es soportada por el navegador
 }

Si el navegador soporta display: grid, todo el estilo dentro de los corchetes será aplicado. De otro modo todo ese estilo se omitirá.

Ahora, parece haber un poco de confusión sobre lo que es Feature Queries. Esto no es algún tipo de verificación externa que analiza si un navegador tiene correctamente implementada una propiedad CSS. Si estás buscando eso, búscalo aquí. Feature Queries pregunta al navegador si una determinada propiedad/valor CSS es soportada, y utiliza la respuesta para decidir si aplicar o no un bloque de CSS. Si un navegador ha implementado una función de manera impropia o incompleta, @supports no te ayudará. Si el navegador informa erróneamente de que el CSS es soportado, @supports no te ayudará. No es una varita mágica para hacer que desaparezcan los errores del navegador.

Dicho esto, encontré increíblemente útil @supports. La regla @supports me ha permitido en varias ocasiones utilizar un nuevo CSS mucho mas rápido que antes de usarla.

Durante años, los desarrolladores han utilizado Modernizr para hacer lo que hace Feature Queries — pero Modernizr necesita JavaScript. Mientras que los scripts pueden ser pequeños, la arquitectura CSS con Modernizr necesita descargar un archivo de JavaScript, ejecutarlo, y completarlo antes de que el CSS sea aplicado. Añadir JavaScript siempre será más lento que emplear solamente CSS. Requerir JavaScript abre la posibilidad de fallos — ¿qué ocurre si no se ejecuta el JavaScript ? Además, Modernizr requiere una capa adicional de complejidad que algunos proyectos simplemente no pueden manejar. Feature Queries es más rápido, más robusto, y mucho más fácil de utilizar.

Puedes observar que la síntasix de Feature Queries es muy parecida a Media Query (consulta de medios). Pienso en ellos como si fueran primos.

@supports (display: grid) {
  main {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  }
}

Ahora, la mayoría de las veces no necesitas hacer una prueba en tu CSS. Por ejemplo, puedes escribir este código sin probar el soporte:

aside {
  border: 1px solid black;
  border-radius: 1em;
}

Si un navegador soporta border-radius, pondrá las esquinas redondeadas en el aside. Si no lo hace, saltará la linea de código y continuará, dejando los lados de la caja cuadrados. No hay ninguna razón para realizar una prueba o utilizar Feature Query. Simplemente, el CSS funciona así. Es un principio fundamental en diseñar CSS sólido, que mejora progresivamente. Los navegadores simplemente saltan el código que no entienden, sin mostrar un error.

border-radius

La mayoría de los navegadores interpretarán border-radius: 1em como el resultado de la derecha. Internet Explorer 6, 7 y 8, sin embargo no redondearán las esquinas, y verás el resultado de la izquierda. Mira este ejemplo en codepen.io/jensimmons/pen/EydmkK

No necesitas Feature Query para esto.

Entonces, ¿cuándo utilizas @supports? Feature Queries es una herramienta para agrupar varias declaraciones CSS, para que funcionen como un grupo bajo ciertas condiciones. Utiliza Feature Queries cuando quieras aplicar una mezcla de CSS viejo y nuevo, pero únicamente cuando el CSS nuevo sea soportado.

Veamos un ejemplo utilizando la propiedad de letra inicial. Esta nueva propiedad initial-letter dice al navegador que haga un elemento en cuestión más grande — como una letra capital. Aquí, a la primera letra de la primera palabra en un párrafo se le dice que sea del tamaño de cuatro líneas de texto. Fabuloso. Oh, pero también me gustaría hacer esa letra más gruesa, poner un poco de margen en su lado derecho, y hey, vamos a hacerla de un bonito color naranja. Genial.

  p::first-letter {
     -webkit-initial-letter: 4;
     initial-letter: 4;
     color: #FE742F;
     font-weight: bold;
     margin-right: 0.5em;
  }
Letra inicial 1

Aquí tenemos nuestro ejemplo de letra inicial tal y como se ve en Safari 9.

Ahora veamos lo que ocurrirá en todos los demás navegadores…

Letra inicial 2

Oh, no. Esto se ve horrible en todos los demás navegadores.

Bueno, eso no es aceptable. No queremos cambiar el color de la letra, o añadir un margen, o hacerla más gruesa a no ser que que también vaya a ser hecha más grande por la propiedad initial-letter. Necesitamos una manera de probar y ver si el navegador soporta initial-letter, y únicamente aplicar el cambio de color color, grosor, y margen si lo hace. Entra Feature Queries.

@supports (initial-letter: 4) or (-webkit-initial-letter: 4) {
  p::first-letter {
     -webkit-initial-letter: 4;
     initial-letter: 4;
     color: #FE742F;
     font-weight: bold;
     margin-right: 0.5em;
  }
}

Nota que necesitas probar una cadena completa de propiedades y valores. Esto me confundió al principio. ¿Por qué estoy probando initial-letter: 4? ¿Es el valor 4 importante? ¿Y si pongo 17? ¿Es necesario que coincida con el valor que está más abajo en mi código ?

La regla @supports prueba una cadena que contiene propiedad y valor porque algunas veces es la propiedad la que necesita ser probada, y otras veces es el valor. Para el ejemplo con initial-letter, no importa lo que pongas para el valor. Pero considera @supports (display: grid) y verás que se necesita para ambos. Todos los navegadores soportan display. Únicamente los navegadores experimentales soportan display: grid (por el momento).

Volviendo a nuestro ejemplo: actualmente initial-letter solamente es soportado en Safari 9, y se requiere un prefijo. Por lo que he escrito el prefijo, asegurándome también de incluir la versión sin prefijo, y he escrito la prueba para buscar el uno o el otro. Si, puedes tener or, and, y en Feature Queries.

Aquí está el nuevo resultado. Los navegadores que soportan initial-letter muestran una letra capital gruesa y gigante. Los otros navegadores actúan como si la letra capital no existiera — de la misma manera que lo harían si hubiese esperado para utilizar esta característica hasta que más navegadores la soportaran. (Por cierto, actualmente lo estamos implementando en Firefox.)

Letra inicial, con y sin

La captura de pantalla de la izquierda procede de Safari 9. Todos los demás navegadores muestran el resultado de la derecha. Puedes ver este código en acción en codepen.io/jensimmons/pen/ONvdYL

Organiza tu código

Ahora puedes estar tentado a utilizar esta herramienta para bifurcar limpiamente tu código en dos ramas. “Hey navegador, si entiendes Viewport Units, haz esto, y si no lo entiendes, haz esta otra cosa.” Eso parece bueno y ordenado.

@supports (height: 100vh) {
  // mi diseño que utiliza viewport height
}
@supports not (height: 100vh) {
  // el diseño alternativo para navegadores antiguos
}
// PODRÍAMOS QUERER ESTO. PERO ES MAL CÓDIGO.

Esto no es una buena idea, al menos por el momento. ¿Ves el problema?

Bueno, no todos los navegadores soportan Feature Queries. Y los navegadores que no interpretan @supports saltarán sobre ambos bloques de código. Eso será probablemente malo.

¿Significa eso que no podemos utilizar Feature Queries hasta que el 100% de los navegadores lo soporten? No. Podemos, y deberíamos utilizar Feature Queries en la actualidad. Simplemente no escribas tu código como el último ejemplo.

¿Como lo hacemos correctamente? Bien, pues de la misma manera que utilizábamos Media Queries antes de que fuera soportado al 100% . En la actualidad es más fácil utilizar Feature Queries en este período de transición de lo que fue utilizar Media Queries. Simplemente tienes que ser inteligente al respecto.

Vas a querer estructurar tu código sabiendo que los viejos navegadores no soportarán Feature Queries o la característica que vas a probar. Te mostraré cómo.

(Por supuesto, en algún momento de un futuro lejano, una vez que el 100% de los navegadores tengan Feature Queries, podremos hacer un uso más intenso de @supports not y organizar nuestro código de esaa manera. Pero pasarán muchos años hasta que llegue ese momento.)

Soporte para Feature Queries

¿Desde cuándo funciona Feature Queries?

Bueno @supports ha funcionado en Firefox, Chrome, y Ópera desde mediados del 2013. También funciona en todas las versiones de Edge. Safari lo incorporó en otoño del 2015, en Safari 9. Feature Queries no es soportado en ninguna versión de Internet Explorer, Opera Mini, Blackberry Browser, o UC Browser.

Puedes creer que el hecho de que Internet Explorer no tenga soporte para Feature Queries es un gran problema. Actualmente, por lo general, no lo es. Te voy a mostrar en un momento por qué. Creo que el mayor obstáculo es Safari 8. Tenemos que mantenernos atentos para ver lo que sucede allí.

Veamos otro ejemplo. Digamos que tenemos algo de código de diseño que queremos aplicar que requiere el uso de object-fit: cover para funcionar correctamente. Para los navegadores que no entienden object-fit, queremos aplicar diferente diseño CSS.

Así que vamos a escribir:

div {
  width: 300px;
  background: yellow;
  // algo de código complejo para un diseño de respaldo
}
@supports (object-fit: cover) {
  img {
    object-fit: cover;
  }
  div {
    width: auto;
    background: green;
    // otro código complejo para el nuevo diseño como nos gusta
  }
}

Entonces, ¿qué es lo que ocurre? Feature Queries puede ser soportado o no, y la nueva característica object-fit: cover también puede ser soportada o no. Combinando obtendremos cuatro posibilidades:

¿Soporta Feature Query? ¿Soporta la característica? ¿Qué ocurre? ¿Es esto lo que queremos?
Soporta Feature Queries Soporta la característica en cuestión
Soporta Feature Queries No soporta la característica
No soporta Feature Queries No soporta la característica
No soporta Feature Queries Soporta la característica en cuestión

Situación 1: Navegadores que soportan Feature Queries, y soportan la característica en cuestión

Firefox, Chrome, Opera, y Safari 9 soportan object-fit y soportan @supports, por lo que esta prueba funcionará bien, y el código dentro de este bloque será aplicado. Nuestra imagen será recortada utilizando object-fit: cover, y el fondo de nuestro div será verde.

Situación 2: Navegadores que soportan Feature Queries, y no soportan la característica en cuestión

Edge no soporta object-fit, pero soporta @supports, por lo que esta prueba se ejecutará y fallará, evitando que el bloque de código sea aplicado. La imagen no tendrá object-fit aplicado, y el div tendrá un fondo amarillo.

Esto es lo que queremos.

Situación 3: Navegadores que no soportan Feature Queries, y no soportan la característica en cuestión

Aquí es donde aparece nuestro clásico némesis, Internet Explorer . IE no entiende @supports y tampoco entiende object-fit. Se podría pensar que no se puede utilizar Feature Query — pero no es cierto.

Piensa en el resultado que queremos. Queremos que IE salte el bloque entero de código. Y eso es exactamente lo que ocurrirá. ¿Por qué? Porque cuando éste alcance @supports, no reconocerá la sintaxis, y saltará al final.

Puede saltar el código “por razones equivocadas” — salta el código porque no entiende @supports, en lugar de no entiender object-fit — ¡pero a quién le importa! Todavía recibimos exactamente el resultado que queríamos.

Esto mismo ocurre con el navegador Blackberry y el navegador UC para Android. No entienden object-fit, ni @supports, así que estamos bien. Funciona de maravilla.

A fin de cuentas, en cualquier ocasión que utilicemos una Feature Query en un navegador que no soporta Feature Queries, estará bien siempre y cuando el navegador tampoco soporte la función que estamos probando.

Piensa a través de la lógica de tu código. Pregúntate, ¿qué ocurre cuando el navegador salta sobre este código? Si eso es lo que quieres, ya lo tienes.

Situación 4: Navegadores que no soportan Feature Queries, pero soportan la función en cuestión

El problema es esta cuarta combinación — cuando la prueba propuesta por un Feature Query no se ejecuta, pero el navegador soporta la función y debería interpretar ese código.

Por ejemplo, object-fit es soportado por Safari 7.1 (en Mac) y 8 (en Mac e iOS) — pero ninguno de ellos soporta Feature Queries. Del mismo modo para Opera Mini —soportará object-fit pero no @supports.

¿Que ocurre? Estos navegadores llegan a este bloque de código, y en lugar de utilizarlo y aplicar object-fit: cover a la imagen y volver el color de fondo del div verde, saltan todo el bloque de código dejando el amarillo como color de fondo.

Y esto realmente no es lo que queremos.

¿Soporta Feature Query? ¿Soporta la característica? ¿Qué ocurre? ¿Es esto lo que queremos?
Soporta Feature Queries Soporta la característica en cuestión El CSS es aplicado
Soporta Feature Queries No soporta la característica El CSS no es aplicado
No soporta Feature Queries No soporta la característica El CSS no es aplicado
No soporta Feature Queries Soporta la característica en cuestión El CSS no es aplicado No, probablemente no.

Por supuesto, esto depende del particular caso de uso. Quizás este sea un resultado que podamos aceptar. El viejo navegador obtiene una experiencia prevista para navegadores antiguos. La página web continua funcionando.

Pero la mayor parte del tiempo, desearemos que el navegador sea capaz de utilizar cualquier función que soporte. Esta es la razón por la que Safari 8 es probablemente el mayor problema con Feature Queries, no Internet Explorer. Hay muchas nuevas propiedades que Safari 8 soporta — como Flexbox. Probablemente no querrás bloquear a Safari 8 de estas propiedades. Por eso raramente utilizo @supports con Flexbox, o cuando lo hago, he escrito al menos tres bifurcaciones en mi código, una con un not. (Lo cual se complica rápido, por lo que no voy a intentar explicarlo aquí.)

Si estás utilizando una función que tiene un mejor soporte en los navegadores antiguos que Feature Queries, piensa todas las combinaciones a medida que vas escribiendo el código. Asegurate de no excluir a los navegadores de obtener algo que quieres que obtengan.

Mientras tanto, es fácil utilizar @supports con las nuevas características CSS — por ejemplo CSS Grid , y letra inicial. Ningún navegador soportará CSS Grid sin soportar Feature Queries. No tendremos que preocuparnos por nuestra problemática cuarta combinación con las nuevas funciones, lo que hace a Feature Queries increíblemente útil a medida que avanzamos.

Todo esto significa que aunque IE11 seguirá existiendo por muchos años, podemos utilizar libremente Feature Queries con los nuevos avances CSS.

Mejores prácticas

Ahora sabemos por qué no podemos escribir nuestro código como este:

@supports not (display: grid) {
    // código para navegadores antiguos
    // NO COPIAR ESTE EJEMPLO
}
@supports (display: grid) {
    // código para nuevos navegadores
    // ¿YA DIJE QUE ESTO ES REALMENTE MALO?
}

Si lo hacemos, impediremos que los antiguos navegadores obtengan el código que necesitan.

En su lugar, estructura tu código como el siguiente:

// código de respaldo para navegadores antiguos

@supports (display: grid) {
    // código para nuevos navegadores
    // incluyendo overrides de código anterior, si es necesario
}

Esta es exactamente la estrategia que aplicamos al utilizar Media Queries para soportar versiones antiguas de IE. Esta estrategia es la que dio lugar a la frase “móvil primero”.

Espero que CSS Grid llegue a los navegadores en 2017, y apuesto que vamos a utilizar bastante Feature Queries cuando implementemos futuros diseños. Va a ser mucho menos molesto, y mucho más rápido, que emplear JavaScript. Y @supports nos permitirá hacer cosas interesantes y complejas para los navegadores que soportan CSS Grid, mientras proporciona opciones de diseño para los navegadores que no lo soportan.

Feature Queries ha existido desde mediados del 2013. Con el inminente lanzamiento de Safari 10, creo que ha llegado el momento de añadir @supports a nuestras herramientas de trabajo.

The following two tabs change content below.

Compartir artículo:

Empezar la discusión en foro.mozilla-hispano.org

  • ¡Participa!

    Firefox Friends »
    Agrega botones de Firefox en tu sitio web y comparte tu amor por Mozilla Firefox.
    Ayuda a otros usuarios en Twitter.
    Colabora con la comunidad »
    En Mozilla lo importante son las personas. Descubre cómo puedes colaborar.

    Boletín Firefox

    Suscríbete al boletín de novedades de Firefox.

  • Descargas

    Descarga los programas de Mozilla.

    Lo más visto

    cc-by-sa