Filtros CSS para todos: La propiedad filter con keywords y sus filtros SVG equivalentes 21.4.16
La propiedad Css filter y las dos formas de uso: mediante palabra clave y usando rutas a filtros SVG equivalentes a las keywords. Las diferencias y posibilidades de ambas.
Filtros CSS para todos: La propiedad filter con keywords y sus filtros SVG equivalentes
La especificación Css que desarrolla los conocidos como filtros Css
es el documento Filter Effects Module Level 1. Sobre el mismo ya hay varios post en este blog, entre otros el que publiqué allá por Mayo de 2012 "Photoshop en los estilos: Introducción a los Filtros Css. Css filter y animation".
En él tienes una introducción a cada uno de los filtros Css y as palabras claves y valores que admite cada uno de ellos.
Esta forma de uso (palabras clave o keywords
) es quizás la forma más sencilla de uso. Pero no es la única. Tampoco la más soportada por los navegadores ni la que más juego da (potencia y diversidad de resultados).
Junto a ella, la documentación recoge la posibilidad de aplicar filtros SVG. Y sobre esta forma (y sus equivalentes a las keywords) es sobre lo que va el artículo.
Más concretamente, el filtro SVG equivalente a cada una de las palabras clave utilizadas. Pero de entrada recordemos la forma de declarar los filtros en Css, ya sea de una forma u otra.
Filtros Css con palabra clave
Es la forma más "sencilla". Sólo hay que recordar su nombre en inglés y elegir un valor entre el rango admitido para dicho filtro:
.elemento {
filter: blur(3px);
}
Su soporte, como puedes ver en canIuse no es casi total. Y aquellos que lo hacen requieren de prefijos privativos. Nota que el soporte parcial que le asigna a Firefox no es a esta forma, sino mediante rutas a SVG´s que vemos a continuación.
Filtros Css con ruta a filtro SVG
La otra forma de aplicar filtros mediante Css es utilizar en su valor, en vez de la palabra, una ruta al SVG correspondiente.
No tan directo y sencillo como el método anterior (en el que navegador ya "tiene" en su programación los valores). Ahora somos nosotros quienes debemos haber "creado" el filtro SVG correspondiente.
El equivalente al código anterior sería el siguiente:
.elemento {
filter: url(RUTA#svg-blur);
}
Y como ocurre con cualquier recurso utilizado en Css que se incluyen indicando una ruta, como las imágenes o archivos tipográficos, debe existir dicho recurso en la ruta indicada. En este caso, el valor de url()
debe ser un SVG declarado y que realice la función deseada para el filtro.
<svg class='hide' xmlns="http://www.w3.org/2000/svg">
<filter id='svg-blur'>
<feGaussianBlur stdDeviation='3' />
</filter>
</svg>
Donde el valor de stdDeviation
será el aplicado al elemento. Nota: no todos los filtros SVG son tan sencillos y a ellos iré a continuación.
Pese a ello, merece la pena tomarse el trabajo porque su soporte es mucho mayor. Ramén de la versatilidad de esta forma en alguno de los filtros y de la diferencia en el resultado final.
Y ahora sí, vamos con cada uno de los filtros Css. En cada uno de ellos tendrás la imagen original y a su lado la misma con uno y otro filtro aplicado para que veas (en función de tu navegador) su efecto. Bajo ellas el código usado y el filtro SVG correspondiente.
Filtro Blur
See the Pen Filtro Blur by Kseso (@Kseso) on CodePen.
En el caso del filtro Blur
todo se reduce al valor declarado en stdDeviation
. Es sencillo en su uso y manejo.
.blur {filter: blur(3px);}
.svg-blur {filter: url(#svg-blur);}
<!--SVG BLUR-->
<svg class='hide' xmlns="http://www.w3.org/2000/svg">
<filter id='svg-blur'>
<feGaussianBlur stdDeviation='3' />
</filter>
</svg>
En puridad el atributo stdDeviation
admite dos valores separados por comas. El primero para el desfase horizontal y el segundo para el vertical. En caso de declararse sólo uno, como en el código anterior, lo aplica a ambos.
See the Pen Filtro SVG Blur 2 valores by Kseso (@Kseso) on CodePen.
Filtro: Grayscale
See the Pen Filtro: Grayscale by Kseso (@Kseso) on CodePen.
.grayscale {filter: grayscale(1);}
.grayscale {filter: url(#svg-grayscale);}
<!--SVG escala grises al 100%-->
<filter id="svg-grayscale">
<feColorMatrix values="
0.2126 0.7152 0.0722 0 0
0.2126 0.7152 0.0722 0 0
0.2126 0.7152 0.0722 0 0
0 0 0 1 0"
type="matrix"/>
</filter>
Este filtro podría englobarse entre los complejos
ya que hace uso de una matriz de colores, feColorMatrix
. Esto lo hace muy potente y versátil, pues dependiendo de los valores de la matriz el resultado final variará. Mira la relación de enlaces del final del artículo.
Filtro: Sepia
See the Pen Filtro: Sepia by Kseso (@Kseso) on CodePen.
.sepia {filter: sepia(1);}
.sepia {filter: url(#svg-sepia);}
<!--SVG SEPIA-->
<filter id="svg-sepia">
<feColorMatrix values="
0.343 0.669 0.119 0 0
0.249 0.626 0.130 0 0
0.172 0.334 0.111 0 0
0 0 0 1 0"
type="matrix"/>
</filter>
Para el filtro Svg sepia
aplica lo mismo que para el de escala de grises al basarse también en una matriz de color.
Filtro: Saturate
See the Pen Filtro: Saturate by Kseso (@Kseso) on CodePen.
.saturate {filter: saturate(2);}
.saturate {filter: url(#svg-saturate);}
<!--SVG SATURATE-->
<filter id="svg-saturate">
<feColorMatrix type="saturate" values="2">
</filter>
Sencillo y simple. Todo se reduce al valor declarado en el atributo values
Filtro: hue-rotate
See the Pen Filtro: hue-rotate by Kseso (@Kseso) on CodePen.
.hue-rotate {filter: hue-rotate(90deg);}
.hue-rotate {filter: url(#svg-hue-rotate);}
<!--SVG HUE-ROTATE-->
<filter id="svg-saturate">
<feColorMatrix type="hueRotate" values="90>
</filter>
La variación del tono (hue-rotate) se expresa en grados en el valor del atributo values
del filtro SVG. El resultado final depende tanto de dicho valor como del color al que aplica.
Filtro: Invert
See the Pen Filtro: invert by Kseso (@Kseso) on CodePen.
.invert {filter: invert(100%);}
.hue-rotate {filter: url(#svg-invert);}
<!--SVG INVERT-->
<filter id="svg-invert">
<feComponentTransfer>
<feFuncR tableValues="1 -1" type="table"/>
<feFuncG tableValues="1 -1" type="table"/>
<feFuncB tableValues="1 -1" type="table"/>
</feComponentTransfer>
</filter>
Con el filtro SVG invert
se actúa sobre cada uno de los tres canales RGB mediante el doble valor de tableValues
.
Filtro Opacity
<!--SVG OPACITY-->
<svg class='hide' xmlns="http://www.w3.org/2000/svg">
<filter id="svg-opacity">
<feComponentTransfer>
<feFuncA type="table" tableValues="0 0.5" />
</feComponentTransfer>
</filter>
</svg>
El grado de transparencia está definido por el segundo valor de tableValues="0 0.5"
. En este ejemplo es el equivalente a opacity: .5
Filtro: brightness
See the Pen Filtro: brightness by Kseso (@Kseso) on CodePen.
El atributo en el SVG a modificar para variar el brillo es slope
. Nota que mientras que el filtro Css actúa en los 3 canales simultáneamente (rojo, verde y azul) y con el mismo valor, el filtro SVG permite hacerlo sobre cada uno de ellos independientemente:
.brightness {filter: brightness(2);}
.brightness {filter: url(#svg-brightness);}
<!--SVG brightness-->
<filter id="svg-brightness">
<feComponentTransfer>
<feFuncR type="linear" slope="2"></feFuncR>
<feFuncG type="linear" slope="2"></feFuncG>
<feFuncB type="linear" slope="2"></feFuncB>
</feComponentTransfer>
</filter>
Filtro: contrast
See the Pen Filtro: contrast by Kseso (@Kseso) on CodePen.
En el caso del filtro contrast
tienes dos valores por canal RGB para lograr el contraste deseado: slope
y intercept
:
.contrast {filter: contrast(2);}
.contrast {filter: url(#svg-contrast);}
<!--SVG contrast-->
<filter id="svg-contrast">
<feComponentTransfer>
<feFuncR type="linear" slope="2" intercept="-0.1"></feFuncR>
<feFuncG type="linear" slope="2" intercept="-0.1"></feFuncG>
<feFuncB type="linear" slope="2" intercept="-0.1"></feFuncB>
</feComponentTransfer>
</filter>
Filtro: drop-shadow
See the Pen Filtro: drop-shadow by Kseso (@Kseso) on CodePen.
.drop-shadow {filter: drop-shadow(0px 0px 10px #000);}
.drop-shadow {filter: url(#svg-drop-shadow);}
<!--SVG drop-shadow-->
<filter id="svg-drop-shadow">
<feGaussianBlur in="SourceAlpha" stdDeviation="10" />
<feOffset dx="0" dy="0" result="offsetblur" />
<feFlood flood-color="#000" />
<feMerge>
<feMergeNode></feMergeNode>
<feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
Este es un filtro bastante complejo, es decir, permite mucho y muy variado juego. Una característica de las sombras mediante filtros frente a la propiedad box-shadow
es que la segunda crea sombra a todos y cada uno de los elementos, mientras que si se declara vía filtros a un grupo de elementos la sombra es la silueta formada por todos ellos, no son sombras individuales de cada uno. Ver demo Diferencias entre Box-shadow y drop-shadow
.
Filtros personalizados
Son los marcados por la especificación como custom filters
. Es el resultado de aplicar varios de los posibles, ya sea utilizando la vía Css o mediante filtros SVG.
A modo de ejemplo esta demo. No he buscado lograr el mismo resultado final. Aprovecho la posibilidad que ofrece el filtro invert
en cada canal.
See the Pen Filtro: personalizado by Kseso (@Kseso) on CodePen.
Muy importante: cuando se usan varios filtros simultáneamente el resultado final obtenido es función del orden en que se declaran. No es lo mismo convertir primero a escalas de grises 100% y después aplicar un filtro sepia que filtro sepia más escala grises. En el segundo caso el resultado será un elemento sólo en grises y en el primero un monotono en sepia.
Los filtros nativos de SVG
La especificación sobre SVG define, además de los filtros incluidos en este artículo, otros cuantos más.
Una buena fuente para iniciarse en ellos es el libro Scalable
de Jorge Aznar. En su página 49 y siguientes le dedica todo un capítulo a explicarlos, ejemplos en codepen incluidos. Como esta demo:
See the Pen Capitulo 7 - varios efectos de filtro by Jorge Aznar (@jorgeatgu) on CodePen.
Lecturas para ampliar información
- Artículoe en este Blog dedicados a `filter´
- Filter Effects Module Level 1
- Filters Efects en SVG 1.1
- feColorMatrix en Scalable [pág. 52] libro de @jorgeATGU y mucho más
- feColorMatrix en SVG 1.1
- feColorMatrix en MDN.
- feColorMatrix en MSDN.
- Filters en MDN
Kseso
the obCSServer ᛯ Ramajero Argonauta, Enredique Amanuense de CSS.#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Kseso
La sintaxis de Css3 es más cómoda para aplicar filtros, pero SVG quizás tenga más opciones de personalización de imágenes.
ResponderEliminarHay un efecto parecido que se usa mucho ahora. Al pasar el ratón por encima de una imagen, ésta pasa de escala de grises a color, seguro que lo has visto en alguna web. Aunque este efecto se hace jugando con opacidad de capas y js, no con filtros css3.
Gracias por el artículo.
Gracias a tí, Sergio
EliminarEstá bien tu apunte para que conste ;-)
A modo de disclaimer no mencioné que los filtros Css aceptan tanto animaciones como transiciones Css según qué propiedades y valores se vean afectadas (ver spec) porque creí que ya era conocido y como bien indicas, hay demos al respecto.
SVG Animation
Tampoco entré en este aspecto porque no era ese el objeto del post (bastante tocho me salió ya xD
Un saludo
OK. Ya entendimos que el artículo no cubre las animaciones, pero ahora que lo mencionaron ... el efecto de pasar una imagen de B&N a color también se puede hacer con 'grayscale'.
EliminarSe aplica el filtro a una imagen en color y se le quita al pasar el puntero.
Con SVG+SMIL y muy pocas líneas de código se puede animar cualquier propiedad de los filtros de SVG.
ResponderEliminarAlgunos experimentos que he hecho con feTurbulence:
http://codepen.io/jorgeatgu/pen/Ayevf/
http://codepen.io/jorgeatgu/pen/npsAq/