Cómo hice un sistema de iconos a partir de propiedades personalizadas de CSS | trucos CSS
SVG es el mejor formato para iconos de sitios web, sin duda. Le permite tener íconos nítidos independientemente de la densidad de píxeles de la pantalla, puede cambiar los estilos SVG en espera e incluso puede animar íconos con CSS o JavaScript.
Hay muchas formas de incluir SVG en una página, y cada técnica tiene sus ventajas y desventajas. Durante los últimos años, he estado usando una función de Sass para importar directamente mis íconos a mi CSS y evitar tener que alterar mi marcado HTML.
Tengo una lista de Sass con todos los códigos fuente de mis íconos. Luego, cada ícono se codifica en un URI de datos con una función Sass y se almacena en el propiedad personalizada al final de la página.
TL; Dr
Lo que tengo para ti aquí es una función de Sass que crea una biblioteca de iconos SVG directamente en tu CSS.
El código fuente SVG se compila con la función Sass, que los codifica en URI de datos y luego almacena los íconos en propiedades CSS personalizadas. Luego puede usar cualquier icono en cualquier lugar de su CSS como si fuera una imagen externa.
Este es un ejemplo tomado directamente del código de mi sitio personal:
.c-filters__summary h2:after {
content: var(--svg-down-arrow);
position: relative;
top: 2px;
margin-left: auto;
animation: closeSummary .25s ease-out;
}
Demostración
Estructura descarada
/* All the icons source codes */
$svg-icons: (
burger: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0...'
);
/* Sass function to encode the icons */
@function svg($name) {
@return url('data:image/svg+xml, #{$encodedSVG} ');
}
/* Store each icon into a custom property */
:root {
@each $name, $code in $svg-icons {
--svg-#{$name}: #{svg($name)};
}
}
/* Append a burger icon in my button */
.menu::after {
content: var(--svg-burger);
}
Esta técnica tiene ventajas y desventajas, así que considérelas antes de implementar esta solución en su proyecto:
Profesionales
- No hay solicitudes HTTP para los archivos SVG.
- Todos los iconos se almacenan en un solo lugar.
- Si necesita actualizar un ícono, no necesita pasar por todos los archivos de plantilla HTML.
- Los iconos se almacenan en caché junto con su CSS.
- Puede editar manualmente el código fuente de los iconos.
- No contamina su HTML al agregar marcas adicionales.
- Aún puede cambiar el color o algún aspecto del icono con CSS.
Contras
- No puede animar o actualizar una parte específica de un SVG con CSS.
- Cuantos más íconos tenga, más pesado será su archivo compilado CSS.
Principalmente uso esta técnica para íconos, no para logotipos o ilustraciones. Un SVG codificado siempre será más pesado que su archivo original, por lo que sigo cargando mi SVG complejo con un archivo externo o con <img>
o en mi css con url(path/to/file.svg)
.
Codificación de SVG en URI de datos
Codificar su SVG como un URI de datos no es nada nuevo. De hecho, Chris Coyer escribió una publicación sobre esto hace más de 10 años para explicar cómo usar esta técnica y por qué deberías (o no deberías) usarla.
Hay dos formas de usar SVG en su CSS con datos URI:
- Como una imagen externa (usando
background-image,
imagen de borde,
imagen-estilo-lista,...) - Como el contenido de un pseudo elemento (p. ej.
::before
o::after
)
Aquí hay un ejemplo básico que muestra cómo usar estos dos métodos:
El principal problema con esta implementación en particular es que tienes que convertir el SVG manualmente cada vez que necesitas un nuevo ícono, y no es muy bueno tener esa larga cadena de código ilegible en tu CSS.
¡Aquí es donde Sass viene al rescate!
Usando una función Sass
Usando Sass, podemos hacernos la vida más fácil copiando el código fuente de nuestro SVG directamente en nuestra base de código, dejando que Sass los codifique correctamente para evitar cualquier error en el navegador.
Esta solución está inspirada principalmente en una característica existente desarrollada por Threespot Media y disponible en el su repositorio.
Estos son los cuatro pasos de esta técnica:
- Cree una variable con todos los iconos SVG enumerados.
- Enumere todos los caracteres que se omitirán para los URI de datos.
- Implemente una función para codificar SVG en formato URI de datos.
- Usa tu función en tu código.
1. Lista de iconos
/**
* Add all the icons of your project in this Sass list
*/
$svg-icons: (
burger: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24.8 18.92" width="24.8" height="18.92"><path d="M23.8,9.46H1m22.8,8.46H1M23.8,1H1" fill="none" stroke="#000" stroke-linecap="round" stroke-width="2"/></svg>'
);
2. Lista de caracteres escapados
/**
* Characters to escape from SVGs
* This list allows you to have inline CSS in your SVG code as well
*/
$fs-escape-chars: (
' ': '%20',
''': '%22',
'"': '%27',
'#': '%23',
"https://css-tricks.com/": '%2F',
':': '%3A',
'(': '%28',
')': '%29',
'%': '%25',
'<': '%3C',
'>': '%3E',
'\': '%5C',
'^': '%5E',
'{': '%7B',
'|': '%7C',
'}': '%7D',
);
3. Función de codificación
/**
* You can call this function by using `svg(nameOfTheSVG)`
*/
@function svg($name) {
// Check if icon exists
@if not map-has-key($svg-icons, $name) {
@error 'icon “#{$name}” does not exists in $svg-icons map';
@return false;
}
// Get icon data
$icon-map: map-get($svg-icons, $name);
$escaped-string: '';
$unquote-icon: unquote($icon-map);
// Loop through each character in string
@for $i from 1 through str-length($unquote-icon) {
$char: str-slice($unquote-icon, $i, $i);
// Check if character is in symbol map
$char-lookup: map-get($fs-escape-chars, $char);
// If it is, use escaped version
@if $char-lookup != null {
$char: $char-lookup;
}
// Append character to escaped string
$escaped-string: $escaped-string + $char;
}
// Return inline SVG data
@return url('data:image/svg+xml, #{$escaped-string} ');
}
4. Agrega el SVG a tu página
button {
&::after {
/* Import inline SVG */
content: svg(burger);
}
}
Si siguió estos pasos, Sass debería compilar su código correctamente y generar lo siguiente:
button::after {
content: url("data:image/svg+xml, %3Csvg%20xmlns=%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox=%270%200%2024.8%2018.92%27%20width=%2724.8%27%20height=%2718.92%27%3E%3Cpath%20d=%27M23.8,9.46H1m22.8,8.46H1M23.8,1H1%27%20fill=%27none%27%20stroke=%27%23000%27%20stroke-linecap=%27round%27%20stroke-width=%272%27%2F%3E%3C%2Fsvg%3E ");
}
Propiedades personalizadas
El Sass ahora implementado svg()
La característica funciona muy bien. ¡Pero su mayor desventaja es que un ícono que se necesita en muchos lugares de su código se duplicará y puede aumentar mucho el peso de su archivo CSS compilado!
Para evitar esto, podemos almacenar todos nuestros íconos en variables CSS y usar una referencia a la variable en lugar de generar el URI codificado cada vez.
Mantendremos el mismo código que teníamos antes, pero esta vez primero mostraremos todos los íconos de la lista de Sass en la raíz de nuestra página web:
/**
* Convert all icons into custom properties
* They will be available to any HTML tag since they are attached to the :root
*/
:root {
@each $name, $code in $svg-icons {
--svg-#{$name}: #{svg($name)};
}
}
Ahora, en lugar de llamar al svg()
cada vez que necesitamos un icono, necesitamos usar la variable que se crea con --svg
prefijo.
button::after {
/* Import inline SVG */
content: var(--svg-burger);
}
Optimizando sus SVG
Esta técnica no proporciona ninguna optimización al código fuente SVG que está utilizando. Asegúrate de no dejar ningún código innecesario; de lo contrario, también se codificarán y aumentarán el tamaño de su archivo CSS.
Puede consultar esta gran lista de herramientas e información sobre cómo optimizar correctamente su SVG. Mi instrumento favorito es el de Jake Archibald. SVGOMG – simplemente arrastre su archivo allí y copie el código extraído.
Bonificación: actualización de íconos en espera
Con esta técnica, no podemos CSS seleccionar partes específicas del SVG. Por ejemplo, no hay manera de cambiar fill
color del icono cuando el usuario mantiene presionado el botón. Pero hay algunos trucos que podemos usar con CSS para poder cambiar la apariencia de nuestro icono.
Por ejemplo, si tiene un ícono negro y desea que sea blanco en espera, puede usar invert()
filtro CSS. También podemos jugar con hue-rotate()
filtrar.
¡Está!
Espero que encuentre útil este pequeño ayudante en sus propios proyectos. Déjame saber lo que piensas del enfoque. ¡Me interesaría saber cómo mejorarías esto o cómo lo harías de manera diferente!
Deja una respuesta