Logo de Mosaic
Temas de CSS
Detecció—n nativa de caracter’ísticas CSS a travéŽs de la regla @supports

Detecció—n nativa de caracter’ísticas CSS a travéŽs de la regla @supports

Chris David Mills. 21 de noviembre de 2012. Artículo original en inglés

Introducci—ón

Mientras sigue habiendo navegadores de diferentes grados de soporte a los est‡ándares para navegar por la web (desde navegadores modernos decentes a antiguas tartanas como IE6), nos sentimos bastante c—ómodos con la idea de enviar c—ódigo diferente a diferentes navegadores para proporcionar experiencias de usuario diferentes pero siempre aceptables. Esto se hace de formas diversas, pero en general se basa bien en la detecció—n del navegador, algo bastante propenso a errores, o en la detecci—n de caracterí’sticas, que resulta m‡ás inteligente y robusta.

La detecci—ón de caracter’ísticas normalmente se hace escribiendo tu propio JavaScript para comprobar si una propiedad fundamental, mŽétodo, etc de la funci—ón que est‡ás detectando existe o puede ser utilizada, o mediante el uso de una biblioteca ya existente de detecció—n de caracter’sticas, como el excelente Modernizr. Modernizr ofrece pruebas de caracter’ísticas y mecanismos para aplicar selectivamente CSS y JavaScript bas‡ándose en los resultados de dichas pruebas, para toda una serie de caracterí’sticas diferentes de HTML5 y CSS3.

Esto es realmente úœtil, pero mucha gente se pregunta si veremos mecanismos nativos para hacer estas pruebas de funciones. La buena noticia es que ya estamos empezando a hacerlo. En este art’ículo se analiza la regla CSS @supports, parte del Mó—dulo de Reglas Condicionales de CSS3 Nivel 3, que proporciona un mecanismo perfecto para aplicar selectivamente CSS bas‡ándose en el soporte de caracterí’sticas. Aqu’í veremos la sintaxis bá‡sica, junto con un ejemplo de aplicació—n.

Nota

@supports actualmente funciona en Opera 12.10 y Firefox Aurora, y los navegadores que no admiten @supports sencillamente pasan por alto completamente el có—digo dentro de esos bloques. Esto significa que ya tiene algunas aplicaciones œútiles, pero que si no se ajusta a tu situació—n, puedes seguir usando Modernizr.

Sintaxis de @supports

@supports toma la forma de un bloque que realiza una prueba y luego ejecuta reglas CSS normales dentro del bloque en funció—n de si la prueba devuelve un valor de verdadero o falso. En este caso, la prueba es siempre una o m‡ás declaraciones de CSS, y el navegador devuelve el valor 'true' si es compatible con la declaraci—ón o declaraciones indicada. Por ejemplo:

@supports (display:flex) {
  section { display: flex }
  ...
}

Las reglas dentro de este bloque se aplicar‡ si el navegador soporta display: flex.

@supports tambiŽn proporciona una palabra clave not para la aplicació—n de estilos cuando las caracter’sticas no está‡n soportadas. Podr’ás dar algœún estilo alternativo especí’fico para los navegadores que no admitan display: flex de la siguiente manera:

@supports not (display: flex) {
  // dar layout de forma alternativa
  // tal vez con floats
}

@supports tambiŽén da palabras clave or y and, para la aplicaci—ón de estilos s—ólo si el navegador pasa dos o m‡ás pruebas espec’ficas de apoyo, o si el navegador pasa alguna de entre un nœúmero de pruebas de soporte diferentes.<(/p>

Por ejemplo, Flexbox só—lo funciona sin prefijos en Opera (Mobile y Next) y en la 'preview' de IE10. Para comprobar si el navegador es compatible con cualquiera de las versiones con prefijo o la versió—n sin prefijo, podr’ía hacerse lo siguiente:

@supports (display: -webkit-flex) or
          (display: -moz-flex) or
          (display: flex) {
  section {
    display: -webkit-flex;
    display: -moz-flex;
    display: flex;
    ...
  }           
}

Para ver un ejemplo de and, es posible que queramos aplicar un diseñ–o de varias columnas y las reglas asociadas œúnicamente cuando haya soporte para la versió—n sin prefijo de las propiedades column-width y column-span, puesto que los navegadores que soportan multi-col con prefijos actualmente no son compatibles con column-span, lo que limita su utilidad:

@supports (column-width: 20rem) and (column-span: all) {
  div { column-width: 20rem }    
  div h2 { column-span: all }
  div h2 + p { margin-top: 0; }
  ...
}

La úœltima cosa a tener en cuenta sobre la sintaxis de @supports es que no se permite mezclar and, or y not sin el uso de una capa de paréŽntesis para dejar clara la prioridad. As’í, por ejemplo, podr’ías querer aplicar una animaci—ón con una transformació—n 3D a un elemento só—lo si el navegador soporta tanto la animació—n 3D como la transformació—n:

@supports ((-webkit-animation-name: my-animation) and (-webkit-transform: rotate3D(1,2,4,90deg))) or
          ((-moz-animation-name: my-animation) and (-moz-transform: rotate3D(1,2,4,90deg))) or
          ((-ms-animation-name: my-animation) and (-ms-transform: rotate3D(1,2,4,90deg))) or
          ((-o-animation-name: my-animation) and (-o-transform: rotate3D(1,2,4,90deg))) or
          ((animation-name: my-animation) and (transform: rotate3D(1,2,4,90deg))) {
  // añadir aquí la animación
}

Un ejemplo de @supports

Para demostrar el uso real de @supports, reescribirŽ un ejemplo que escrib’ por primera vez para mi libro (Practical CSS3: develop and design) — un ejemplo simple de tarjeta con rotación 3D que utiliza Modernizr para proporcionar una experiencia alternativa a los navegadores que no soportan transformaciones 3D (como Opera, en el momento de la escritura: lo tenemos en preparación) o transformaciones 2D (sencillamente aplico un montó—n de padding por la izquierda en la parte delantera de la tarjeta cuando pasamos por encima para mostrar el reverso). Puedes ver el ejemplo de la tarjeta Modernizr en funcionamiento, y ver la diferencia entre la experiencia de los diferentes niveles de soporte en las figuras 1 a 3.

Una tarjeta de visita creada usando CSS3. En los navegadores compatibles con transformaciones 3D la tarjeta gira con una bonita animaci—ón

Figura 1: En los navegadores con soporte para transformaciones 3D la tarjeta gira con una bonita animaci—ón.

Una tarjeta de visita creada usando CSS3. En los navegadores que no soportan transformaciones 3D pero sí transformaciones 2D, el anverso de la tarjeta se desplaza con una bonita animació—n para revelar la parte de atrá‡s

Figura 2: En los navegadores que no soportan transformaciones 3D pero que sí soportan transformaciones 2D, el anverso de la tarjeta se mueve con una bonita animaci—ón para revelar la parte posterior.

Una tarjeta de visita creada usando CSS3. En los navegadores que no soportan transformaciones 3D ni 2D el anverso de la tarjeta sencillamente se mueve para mostrar la parte de atrá‡s sin animaci—ón

Figura 3: En los navegadores que no soportan transformaciones 3D ni 2D, la parte delantera de la tarjeta sencillamente se mueve para mostrar la parte de atr‡ás sin animaci—ón.

En mi ejemplo con Modernizr trabajo de adelante hacia atrá‡s, proporcionando el có—digo de reserva para los navegadores que no soportan transformaciones 3D, a continuaci—ón proporcionando una experiencia realmente bá‡sico para los navegadores que tampoco admitan transformaciones 2D. En el ejemplo con @supports trabajo al revŽés, con un enfoque más en la línea de la mejora progresiva: en primer lugar proporcionamos una experiencia realmente b‡ásica para mostrar ambos lados de la tarjeta de visita que funciona en casi todos los navegadores:

/* || Para los navegadores que no soportan transformaciones 2D ni 3D */

#wrapper:hover #inner-wrapper #front, #wrapper:focus #inner-wrapper #front {
  margin-left: -350px;
}

Los navegadores m‡ás antiguos s—ólo llegarán hasta aquí’, y luego harán caso omiso de todo lo que hay dentro de la regla @supports.

A continuación tenemos un conjunto de reglas para los navegadores que soportan transformaciones 2D:

/* || Para navegadores con soporte para transformaciones 2D */
      
@supports (-webkit-transform: rotate(-30deg)) or
          (-moz-transform: rotate(-30deg)) or
          (-ms-transform: rotate(-30deg)) or
          (-o-transform: rotate(-30deg)) or
          (transform: rotate(-30deg)) {
                               
                
  #inner-wrapper #front {
    -webkit-transition: 0.8s all ease-in;
    -moz-transition: 0.8s all ease-in;
    -ms-transition: 0.8s all ease-in;
    -o-transition: 0.8s all ease-in;
    transition: 0.8s all ease-in;
  }
      
  #wrapper:hover #inner-wrapper #front, #wrapper:focus #inner-wrapper #front {
    margin-left: 0;
          
    -webkit-transform: rotate(-30deg) translate(-50%,-100%);
    -moz-transform: rotate(-30deg) translate(-50%,-100%);
    -ms-transform: rotate(-30deg) translate(-50%,-100%);
    -o-transform: rotate(-30deg) translate(-50%,-100%);
    transform: rotate(-30deg) translate(-50%,-100%);
  }
  
}

Y, finalmente, un conjunto de reglas para navegadores con soporte para transformaciones 3D:

/* || Para navegadores con soporte para transformaciones 3D */
      
@supports (-webkit-transform: rotateX(0deg)) or
          (-moz-transform: rotateX(0deg)) or
          (-ms-transform: rotateX(0deg)) or
          (-o-transform: rotateX(0deg)) or
          (transform: rotateX(0deg)) {
      
  #front, #back {        
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -ms-backface-visibility: hidden;
    -o-backface-visibility: hidden;
    backface-visibility: hidden;
  }
      
  #front {
    -webkit-transform: rotateX(0deg);
    -moz-transform: rotateX(0deg);
    -ms-transform: rotateX(0deg);
    -o-transform: rotateX(0deg);
    transform: rotateX(0deg);        
  }
      
  #back {
    -webkit-transform: rotateX(180deg);
    -moz-transform: rotateX(180deg);
    -ms-transform: rotateX(180deg);
    -o-transform: rotateX(180deg);
    transform: rotateX(180deg);
  }
      
  #wrapper:hover #inner-wrapper, #wrapper:focus #inner-wrapper {
    -webkit-transform: rotateX(180deg);
    -moz-transform: rotateX(180deg);
    -ms-transform: rotateX(180deg);
    -o-transform: rotateX(180deg);
    transform: rotateX(180deg);
  }
  
  #wrapper:hover #inner-wrapper #front, #wrapper:focus #inner-wrapper #front {
    -webkit-transform: none;
    -moz-transform: none;
    -ms-transform: none;
    -o-transform: none;
    transform: none;
  }
      
}

Ejemplo de funcionamiento en vivo

window.supportsCSS();

Opera 12.10 es actualmente el œúnico navegador con soporte para la correspondiente API JavaScript de @supports, que permite ejecutar c—ódigo de forma condicional dependiendo de si el navegador soporta o no una determinada caracter’ística CSS. Por ejemplo, aqu’ estᇠmi ejemplo inicial simple reescrito en JavaScript:

var flexy = window.supportsCSS('display:flex');

if(flexy) {
  alert('¡Soporto Flexbox!');
}

Nota

En la especificaci—ón veréi‡s que la sintaxis aparece como CSS.supports, no window.supportsCSS. Esto se debe a que implementamos una versió—n un poco m‡ás antigua de la especificaci—n, ademá‡s de que nos preocupaban las implicaciones para la compatibilidad de un objeto llamado CSS en el espacio de nombres global. Lo que finalmente se establezca— está aúœn por verse.

Resumen

Y así’ llega a su fin nuestro estudio de @supports. Esta caracter’ística es muy interesante, ya que puedes ser muy preciso con la detección de caracterí’sticas y entrega de CSS a implementar. Un problema es, por supuesto, el hecho de que los navegadores antiguos a los que se quiere dar estilos alternativos no soportan @supports, pero aún así resulta útil hoy en día. En cualquier caso, esperamos que la la característica se vuelva más úœtil en el futuro.

Logo Creative Commons
Los contenidos recogidos en este artículo están sujetos a una licencia Creative Commons
Reconocimiento, No comercial - Compartir bajo la misma licencia 3.0 No adaptada
.
: Ir al índice :