¿Por qué tendríamos que aplicar sombras a SVG?
- Las sombras son una característica de diseño común que puede ayudar a que los elementos, como los íconos, se destaquen. Pueden ser persistentes o aplicarse en diferentes estados (p. Ej.
:hover
,:focus
, o:active
) para indicar interacción a los usuarios. - Las sombras ocurren en la vida real, por lo que se pueden usar en las pantallas para dar algo de vida a tus elementos y agregar un toque de realismo a un diseño.
Dado que estamos haciendo listas, hay dos formas principales en las que podemos aplicar sombras a un SVG:
- Usando el CSS
filter()
propiedad - Usando un SVG
<filter>
Sí, ¡ambos involucran filtros! Y sí, tanto CSS como SVG tienen sus propios tipos de filtros. Pero también hay un cruce entre estos. Por ejemplo, un CSS filter
puede referirse a un SVG <filter>
; es decir, si estamos trabajando con un SVG en línea en lugar de, digamos, un SVG utilizado como imagen de fondo en CSS.
Qué no puedes usar: el CSS box-shadow
propiedad. Esto se usa comúnmente para sombras, pero sigue el borde exterior rectangular de los elementos, no los bordes de los elementos SVG como queremos. Aquí está Michelle Barker con una explicación clara:
Sin embargo, si está utilizando una fuente de icono SVG, siempre hay text-shadow
. Eso de hecho funcionará. Pero centrémonos en los dos primeros, ya que están en consonancia con la mayoría de los casos de uso.
Sombras con filtros CSS
El truco para aplicar una sombra directamente a SVG a través de filtros CSS es el drop-shadow()
función:
svg {
filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));
}
Eso aplicará una sombra que comienza en 3px horizontalmente, 5px hacia abajo, con 2px de desenfoque y es 40% negra. Aquí hay algunos ejemplos de eso:
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 posteriores.
Escritorio
Cromo | Firefox | ES DECIR | Borde | Safari |
---|---|---|---|---|
18 * | 35 | No | 79 | 6 * |
Móvil / Tableta
Android Chrome | Android Firefox | Androide | Safari de iOS |
---|---|---|---|
96 | 95 | 4,4 * | 6.0-6.1 * |
Llamar a un filtro SVG dentro de un filtro CSS
Digamos que tenemos un filtro SVG en el HTML:
<svg height="0" width="0">
<filter id='shadow' color-interpolation-filters="sRGB">
<feDropShadow dx="2" dy="2" stdDeviation="3" flood-opacity="0.5"/>
</filter>
</svg>
Podemos usar un filtro CSS para llamar a ese filtro SVG por ID en lugar de los valores que vimos anteriormente:
svg {
filter: url(#shadow);
}
Ahora ese filtro se toma del HTML y se hace referencia en el CSS, que lo aplica.
Usar primitivas de filtro SVG
Quizás se pregunte cómo obtuvimos ese SVG <filter>
trabajar. Para hacer una sombra paralela con un filtro SVG, usamos un filtro primitivo. Una primitiva de filtro en SVG es un elemento que toma algún tipo de imagen o gráfico como entrada y luego genera esa imagen o gráfico cuando se llama. Funcionan como filtros en una aplicación de edición gráfica, pero en código y solo se pueden usar dentro de un SVG <filter>
elemento.
Hay muchas primitivas de filtro diferentes en SVG. El que estamos buscando es <feDropShadow>
. Te dejaré adivinar qué hacer con solo mirar el nombre.
Entonces, de manera similar a cómo tuvimos algo como esto, hicimos esto con un filtro CSS:
svg {
filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));
}
… podemos lograr lo mismo con el <feDropShadow>
Primitiva de filtro SVG. Hay tres atributos clave que vale la pena mencionar, ya que ayudan a definir la apariencia de la sombra paralela:
dx
– Esto cambia la posición de la sombra a lo largo del eje x.dy
– Esto cambia la posición de la sombra a lo largo del eje y.stdDeviation
– Esto define la desviación estándar para la operación de desenfoque de la sombra paralela. Hay otros atributos que podemos usar, como elflood-color
para configurar el color de la sombra paralela, yflood-opacity
para configurar la opacidad de la sombra paralela.
Ese ejemplo incluye tres <filter>
elementos, cada uno con su propio <feDropShadow>
primitivas de filtrado.
Usar filtros SVG
Los filtros SVG son muy poderosos. Solo miramos <feDropShadow>
, lo cual es muy útil, por supuesto, pero hay mucho más que pueden hacer (incluidos efectos similares a Photoshop) y el subconjunto de cosas que obtenemos solo para las sombras es extenso. Veamos algunos, como sombras de colores y sombras insertadas.
Tomemos como ejemplo el marcado SVG para el logotipo de Twitter:
<svg class="svg-icon" viewBox="0 0 20 20">
<path fill="#4691f6" d="M18.258,3.266c-0.693,0.405-1.46,0.698-2.277,0.857c-0.653-0.686-1.586-1.115-2.618-1.115c-1.98,0-3.586,1.581-3.586,3.53c0,0.276,0.031,0.545,0.092,0.805C6.888,7.195,4.245,5.79,2.476,3.654C2.167,4.176,1.99,4.781,1.99,5.429c0,1.224,0.633,2.305,1.596,2.938C2.999,8.349,2.445,8.19,1.961,7.925C1.96,7.94,1.96,7.954,1.96,7.97c0,1.71,1.237,3.138,2.877,3.462c-0.301,0.08-0.617,0.123-0.945,0.123c-0.23,0-0.456-0.021-0.674-0.062c0.456,1.402,1.781,2.422,3.35,2.451c-1.228,0.947-2.773,1.512-4.454,1.512c-0.291,0-0.575-0.016-0.855-0.049c1.588,1,3.473,1.586,5.498,1.586c6.598,0,10.205-5.379,10.205-10.045c0-0.153-0.003-0.305-0.01-0.456c0.7-0.499,1.308-1.12,1.789-1.827c-0.644,0.28-1.334,0.469-2.06,0.555C17.422,4.782,17.99,4.091,18.258,3.266" ></path>
</svg>
Vamos a necesitar un <filter>
elemento para hacer estos efectos. Esto debe estar dentro de un <svg>
elemento en el HTML. A <filter>
El elemento nunca se representa directamente en el navegador, solo se usa como algo que se puede referenciar a través del filter
atributo en SVG, o el url()
función en CSS.
Aquí está la sintaxis que muestra un filtro SVG y lo aplica a una imagen de origen:
<svg width="300" height="300" viewBox="0 0 300 300">
<filter id="myfilters">
<!-- All filter effects/primitives go in here -->
</filter>
<g filter="url(#myfilters)">
<!-- Filter applies to everything in this group -->
<path fill="..." d="..." ></path>
</g>
</svg>
El filter
El elemento está destinado a contener primitivas de filtro como niños. Es un contenedor para una serie de operaciones de filtro que se combinan para crear efectos de filtro.
Estas primitivas de filtro realizan una única operación gráfica fundamental (por ejemplo, difuminar, mover, rellenar, combinar o distorsionar) en una o más entradas. Son como bloques de construcción en los que cada filtro SVG se puede utilizar junto con otros para crear un efecto. <feGaussianBlur>
es una primitiva de filtro popular que se utiliza para agregar un efecto de desenfoque.
Digamos que definimos el siguiente filtro SVG con <feGaussianBlur>
:
<svg version="1.1" width="0" height="0">
<filter id="gaussian-blur">
<feGaussianBlur stdDeviation="1 0" />
</filter>
</svg>
Cuando se aplica a un elemento, este filtro crea un desenfoque gaussiano que desenfoca el elemento en un 1px
radio en el eje x, pero sin desenfoque en el eje y. Aquí está el resultado, con y sin efecto:
Es posible utilizar múltiples primitivas dentro de un solo filtro. Esto creará efectos interesantes, sin embargo, es necesario que las diferentes primitivas se conozcan entre sí. Bence Szabó tiene un increíble conjunto de patrones geniales que creó de esta manera.
Cuando se combinan múltiples primitivas de filtro, la primera primitiva usa el gráfico original (SourceGraphic
) como entrada gráfica. Cualquier primitiva posterior usa el resultado del efecto de filtro anterior como entrada. Y así. Pero podemos obtener cierta flexibilidad al usar el in
, in2
y result
atributos en elementos primitivos. Steven Bradley tiene un excelente artículo sobre las primitivas de filtro que se remonta a 2016, pero que sigue siendo válido en la actualidad.
Hay 17 primitivas que podemos usar hoy:
<feGaussianBlur>
<feDropShadow>
<feMorphology>
<feDisplacementMap>
<feBlend>
<feColorMatrix>
<feConvolveMatrix>
<feComponentTransfer>
<feSpecularLighting>
<feDiffuseLighting>
<feFlood>
<feTurbulence>
<feImage>
<feTile>
<feOffset>
<feComposite>
<feMerge>
Observe la fe
prefijo en todos ellos. Eso significa efecto de filtro. Comprender los filtros SVG es un desafío. Un efecto como una sombra insertada requiere una sintaxis detallada que es difícil de comprender sin una comprensión profunda de las matemáticas y la teoría del color. (“Getting Deep Into Shadows” de Rob O’Leary es un buen lugar para comenzar).
En lugar de correr por la madriguera de todo eso, vamos a trabajar con algunos filtros prefabricados. Afortunadamente, hay muchos filtros SVG listos para usar.
Sombras insertadas
Para utilizar el efecto de filtro en el logotipo de Twitter, debemos declararlo en nuestro “documento fuente SVG” con una identificación única para hacer referencia en nuestro <filter>
etiqueta.
<filter id='inset-shadow'>
<!-- Shadow offset -->
<feOffset
dx='0'
dy='0'
/>
<!-- Shadow blur -->
<feGaussianBlur
stdDeviation='1'
result="offset-blur"
/>
<!-- Invert drop shadow to make an inset shadow -->
<feComposite
operator="out"
in='SourceGraphic'
in2='offset-blur'
result="inverse"
/>
<!-- Cut color inside shadow -->
<feFlood
flood-color="black"
flood-opacity='.95'
result="color"
/>
<feComposite
operator="in"
in='color'
in2='inverse'
result="shadow"
/>
<!-- Placing shadow over element -->
<feComposite
operator="over"
in='shadow'
in2='SourceGraphic'
/>
</filter>
Hay cuatro primitivas diferentes allí y cada una realiza una función diferente. Pero, en conjunto, logran una sombra insertada.
Ahora que hemos creado este filtro de sombra insertado, podemos aplicarlo a nuestro SVG. Ya hemos visto cómo aplicarlo a través de CSS. Algo como:
.filtered {
filter: url(#myfilters);
}
/* Or apply only in certain states, like: */
svg:hover, svg:focus {
filter: url(#myfilters);
}
También podemos aplicar un SVG <filter>
directamente dentro de la sintaxis SVG con el filter
atributo. Eso es como:
<svg>
<!-- Apply a single filter -->
<path d="..." filter="url(#myfilters)" />
<!-- Or apply to a whole group of elements -->
<g filter="url(#myfilters)">
<path d="..." />
<path d="..." />
</g>
</svg>
Más ejemplos
Aquí hay algunos ejemplos más de sombras de Oleg Solomka:
Tenga en cuenta que las sombras básicas aquí probablemente sean un poco más complicadas de lo necesario. Por ejemplo, una sombra de color todavía se puede hacer con <feDropShadow>
me gusta:
<feDropShadow dx="-0.8" dy="-0.8" stdDeviation="0"
flood-color="pink" flood-opacity="0.5"/>
¡Pero ese efecto de relieve es bastante bueno como filtro!
También tenga en cuenta que es posible que vea filtros SVG en la sintaxis SVG como esta:
<svg height="0" width="0" style="position: absolute; margin-left: -100%;">
<defs>
<filter id="my-filters">
<!-- ... -->
</filter>
<symbol id="my-icon">
<!-- ... -->
</symbol>
</defs>
</svg>
En la primera línea, eso dice: este SVG no debería renderizarse en absoluto, es solo algo que tenemos la intención de usar más adelante. El <defs>
La etiqueta dice algo similar: solo estamos definiendo estas cosas para usarlas más adelante. De esa manera, no tenemos que repetirnos escribiendo las cosas una y otra vez. Haremos referencia al filtro por ID y también a los símbolos, tal vez como:
<svg>
<use xlink:href="https://css-tricks.com/adding-shadows-to-svg-icons-with-css-and-svg-filters/#my-icon" />
</svg>
Los filtros SVG tienen un amplio soporte (¡incluso en Internet Explorer y Edge!) Con un rendimiento muy rápido.
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 posteriores.
Escritorio
Cromo | Firefox | ES DECIR | Borde | Safari |
---|---|---|---|---|
8 | 3 | 10 | 12 | 6 |
Móvil / Tableta
Android Chrome | Android Firefox | Androide | Safari de iOS |
---|---|---|---|
96 | 95 | 4.4 | 6.0-6.1 |
Terminando las cosas
Una comparación final:
- Los filtros CSS son más fáciles de usar, pero son mucho más limitados. No creo que sea posible agregar una sombra insertada con el
drop-shadow()
función, por ejemplo. - Los filtros SVG son mucho más robustos, pero también mucho más complicados, y requieren tener la
<filter>
en algún lugar del HTML. - Ambos tienen un excelente soporte de navegador y funcionan bien en todos los navegadores modernos, aunque los filtros SVG tienen (sorprendentemente) el soporte de navegador más profundo.
En este artículo, hemos visto por qué y cómo aplicar sombras a los iconos SVG con ejemplos en cada uno. ¿Ha hecho esto, pero lo hizo de una manera diferente a todo lo que vimos? ¿Ha intentado hacer un efecto de sombra que le resultó imposible de lograr? ¡Por favor comparte!