
Las muchas formas de cambiar un relleno SVG al pasar el mouse (y cuándo usarlas)

SVG es un gran formato para iconos. Los formatos vectoriales se ven nítidos y nítidos, sin importar el tamaño del dispositivo, y obtenemos mucho control de diseño cuando los usamos en línea.
SVG también nos brinda otra característica poderosa: la capacidad de manipular sus propiedades con CSS. Como resultado, podemos realizar interacciones rápidas y sencillas donde antes se necesitaban ingeniosos trucos de CSS o intercambiar archivos de imagen completos.
Esas interacciones incluyen el cambio de color en los estados de desplazamiento. Parece algo muy sencillo aquí en 2019, pero en realidad hay algunas formas totalmente válidas de hacerlo, lo que solo demuestra aún más los increíbles poderes de SVG.
En primer lugar, comenzamos con un marcado SVG un poco abreviado:
svg path ...//svg
Apunte a la .icon
clase en CSS y establezca la fill
propiedad SVG en el estado de desplazamiento para intercambiar colores.
.icon:hover { fill: #DA4567;}
Esta es, con diferencia, la forma más sencilla de aplicar un estado de desplazamiento coloreado a un SVG. ¡Tres líneas de código!
También se puede hacer referencia a los SVG mediante una img
etiqueta o como imagen de fondo. Esto permite que las imágenes se almacenen en caché y podemos evitar inflar su HTML con fragmentos de código SVG. Pero la desventaja es grande: ya no tenemos la capacidad de manipular esas propiedades usando CSS. Siempre que me encuentro con íconos que no están en línea, lo primero que hago es colocarlos en línea, pero a veces esa no es una opción.
Recientemente estuve trabajando en un proyecto en el que los íconos sociales eran un componente de una biblioteca de patrones con la que todos estaban contentos. En este caso, se hacía referencia a los iconos desde un img
elemento. Me encargaron aplicar colores :focus
y :hover
estilos, sin ajustar el marcado.
Entonces, ¿cómo se hace para agregar un efecto de desplazamiento de color a un ícono si no es un SVG en línea?
Filtros CSS
Los filtros CSS nos permiten aplicar una gran cantidad de efectos geniales, similares a los de Photoshop, directamente en el navegador. Los filtros se aplican al elemento después de que el navegador muestra el diseño y la pintura inicial, lo que significa que retroceden con elegancia. Se aplica a todo el elemento, incluidos los niños. Piense en un filtro como una lente colocada sobre la parte superior del elemento al que se aplica.
Estos son los filtros CSS de los que disponemos:
brightness(number-percentage);
contrast(number-percentage);
grayscale(number-percentage);
invert(number-percentage);
opacity(number-percentage);
saturate(number-percentage);
sepia(number-percentage);
hue-rotate(angle);
blur(length);
drop-shadow(lengthcolor);
Todos los filtros tienen un valor que se puede modificar para ajustar el efecto. En la mayoría de los casos, este valor se puede expresar en unidades decimales o porcentuales (por ejemplo, brightness(0.5)
o brightness(50%)
).
Nada más sacarlo de la caja, no hay ningún filtro CSS que nos permita agregar nuestro propio color específico.
Tenemos hue-rotate()
, pero eso solo ajusta un color existente; no agrega color, lo cual no es bueno ya que comenzamos con un ícono monocromático.
Lo que cambia las reglas del juego acerca de los filtros CSS es que no tenemos que usarlos de forma aislada. Se pueden aplicar varios filtros a un elemento separando con espacios las funciones de filtro de esta manera:
.icon:hover { filter: grayscale(100%) sepia(100%);}
Si una de las funciones de filtro no existe o tiene un valor incorrecto, se ignora toda la lista y no se aplica ningún filtro al elemento.
Al aplicar múltiples funciones de filtro a un elemento, su orden es importante y afectará el resultado final. Cada función de filtro se aplica al resultado de la operación anterior.
Entonces, para colorear nuestros íconos, tenemos que encontrar la combinación correcta.
Para utilizarlo hue-rotate()
, debemos comenzar con un ícono de color. El sepia()
filtro es la única función de filtro que nos permite agregar un color, dándole al elemento filtrado un tinte amarillo-marrón, como una foto antigua.
El color de salida depende del valor tonal inicial:
Para agregar suficiente color con sepia()
, primero debemos usar invert()
para convertir nuestro ícono a un gris medio:
.icon:hover { filter: invert(0.5)}
Luego podemos agregar el tono amarillo/marrón con sepia()
:
.icon:hover { filter: invert(0.5) sepia(1);}
…luego cambia el tono con hue-rotate()
:
.icon:hover { filter: invert(0.5) sepia(1) hue-rotate(200deg); }
Una vez que tengamos el color rugoso que queremos, podemos modificarlo con saturation()
y brightness()
:
.icon:hover { filter: invert(0.5) sepia(1) hue-rotate(200deg) saturate(4) brightness(1);}
He creado una pequeña herramienta para hacer tu vida un poco más fácil, ya que es un proceso bastante confuso de estimar.
Incluso con la herramienta, sigue siendo un poco complicado, no es compatible con Internet Explorer y, lo más importante, no puedes especificar un color preciso.
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 |
---|---|---|---|---|
18* | 35 | No | 79 | 6* |
Móvil/Tableta
androidcromo | Firefox para Android | androide | Safari en iOS |
---|---|---|---|
125 | 126 | 4.4* | 6,0-6,1* |
Entonces, ¿qué hacemos si necesitamos un código hexadecimal específico?
Filtros SVG
Si necesitamos un control más preciso (y una mejor compatibilidad con el navegador) que el que pueden ofrecer los filtros CSS, entonces es hora de recurrir a SVG.
Los filtros provienen originalmente de SVG. De hecho, en el fondo, los filtros CSS solo se unen a los filtros SVG con un conjunto particular de valores integrados.
A diferencia de CSS, el filtro no está predefinido para nosotros, por lo que tenemos que crearlo. ¿Cómo hacemos esto?
Esta es la sintaxis para definir un filtro:
svg version="1.1" defs filter ... ... /filter ... /defs/svg
Los filtros están definidos por un filter
elemento, que va dentro de la defs
sección de un SVG.
Los filtros SVG se pueden aplicar al contenido SVG dentro del mismo documento SVG. O bien, se puede hacer referencia al filtro y aplicarlo al contenido HTML en otro lugar.
Para aplicar un filtro SVG al contenido HTML, lo referenciamos de la misma manera que un filtro CSS: usando la url()
función de filtro. La URL apunta al ID del filtro SVG.
.icon:hover { filter: url('#id-of-your-filter');}
El filtro SVG se puede colocar en línea en el documento o la función de filtro puede hacer referencia a un SVG externo. Prefiero la última opción, ya que me permite mantener mis filtros SVG ordenados en una carpeta de recursos.
.icon:hover { filter: url('assets/your-SVG.svg#id-of-your-filter');}
Volvamos al filter
elemento en sí.
filter ... .../filter
En este momento, este filtro está vacío y no hará nada, ya que no hemos definido un filtro primitivo. Los filtros primitivos son los que crean los efectos del filtro. Hay una serie de filtros primitivos disponibles, entre los que se incluyen:
[feBlend]
[feColorMatrix]
[feComponentTransfer]
[feComposite]
[feConvolveMatrix]
[feDiffuseLighting]
[feDisplacementMap]
[feDropShadow]
[feFlood]
[feGaussianBlur]
[feImage]
[feMerge]
[feMorphology]
[feOffset]
[feSpecularLighting]
[feTile]
[feTurbulence]
Al igual que con los filtros CSS, podemos usarlos por sí solos o incluir múltiples primitivos de filtro en la filter
etiqueta para lograr efectos más interesantes. Si se usa más de un primitivo de filtro, cada operación se basará en la anterior.
Para nuestros propósitos, solo vamos a utilizar feColorMatrix
, pero si quieres saber más sobre los filtros SVG, puedes consultar las especificaciones en MDN o esta serie de artículos (en progreso, al momento de escribir esto) que Sara Soueidan ha iniciado.
feColourMatrix
nos permite cambiar los valores de color por canal, muy parecido a la mezcla de canales en Photoshop.
Así es como se ve la sintaxis:
svg version="1.1" defs filter feColorMatrix color-interpolation-filters="sRGB" type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 "/ /filter ... /defs/svg
El color-interpolation-filters
atributo especifica nuestro espacio de color. El espacio de color predeterminado para los efectos de filtro es linearRGB, mientras que en CSS, los colores RGB se especifican en el espacio de color sRGB. Es importante que establezcamos el valor en sRGB para que nuestros colores coincidan.
Echemos un vistazo más de cerca a los valores de la matriz de color.
Las primeras cuatro columnas representan los canales de color rojo, verde y azul y el valor alfa (opacidad). Las filas contienen los valores rojo, verde, azul y alfa en esos canales.
La columna M es un multiplicador; no necesitamos cambiar ninguno de estos valores para nuestros propósitos aquí. Los valores de cada canal de color se representan como números de punto flotante en el rango de 0 a 1.
Podríamos escribir estos valores como una declaración de color CSS RGBA de la siguiente manera:
Los valores de cada canal de color (rojo, verde y azul) se almacenan como números enteros en el rango de 0 a 255. En las computadoras, este es el rango que puede ofrecer un byte de 8 bits.
Al dividir estos valores de canal de color por 255, los valores se pueden representar como un número de punto flotante que podemos usar en el archivo feColorMatrix
.
¡Y, al hacer esto, podemos crear un filtro de color para cualquier color con un valor RGB!
Como el verde azulado, por ejemplo:
Este filtro SVG solo impartirá color a los íconos con relleno blanco, por lo que si tenemos un ícono con relleno negro, podemos usarlo invert()
para convertirlo a blanco antes de aplicar el filtro SVG.
.icon:hover { filter: invert(100%) url('assets/your-SVG.svg#id-of-your-filter');}
Si solo tenemos un código hexadecimal, el cálculo es un poco más complicado, aunque existen muchos conversores de hexadecimal a RGBA. Para ayudar, he creado un conversor de HEX a feColorMatrix.
¡Juega y feliz filtrado!
Deja una respuesta