Qué produce Figma e Illustrator
Anatomía de un SVG recién exportado: el prólogo inútil, los identificadores que colisionan, las clases globales, el fill none del contenedor, y por qué currentColor no funciona de fábrica.
El fichero típico de Figma
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <g id="Frame 27" clip-path="url(#clip0_1_43)"> <path id="Vector" d="M12.0000 2.00000L15.0900 8.26000L22.0000 9.27000L17.0000 14.1400" stroke="#1E1E1E" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> </g> <defs> <clipPath id="clip0_1_43"> <rect width="24" height="24" fill="white"/> </clipPath> </defs></svg>Cinco rasgos en ocho líneas.
width y height fijos junto al viewBox. No hacen daño y limitan: el icono toma ese tamaño si el CSS no dice otra cosa. Para un icono que se dimensiona desde CSS, sobran; para uno que se usa suelto, ayudan a que no colapse. La decisión depende de tu sistema.
fill="none" en el elemento raíz. Este sí hace daño. Como fill se hereda, ese none baja a todo el contenido. Si más tarde pones una regla .icono { fill: currentColor }, gana el CSS y funciona; pero si intentas que el icono herede el color por la vía de poner color en el contenedor sin tocar el fill, no pasa nada, porque el none del raíz gana a la herencia.
Nombres de capa como id. id="Frame 27", id="Vector". Son ruido, y con espacios. Peor: si el mismo fichero se exporta dos veces, esos identificadores se repiten en el documento.
El clipPath con identificador de forma clip0_1_43. Figma añade un recorte cuando el marco recorta contenido, aunque el contenido no se salga. Los números vienen del identificador interno del nodo, así que dos exportaciones distintas pueden generar el mismo, y ese es el origen de la colisión que se explicó en el nivel 20.
Colores literales en cada trazo. stroke="#1E1E1E". El icono está atado a un color, y ese color es el del tema de la herramienta, no el de tu producto.
A eso se añaden, según la exportación: coordenadas con seis decimales, grupos anidados sin función, atributos fill-rule="evenodd" clip-rule="evenodd" repetidos en cada ruta, y transformaciones que se podrían haber aplicado a la geometría.
El fichero típico de Illustrator
<?xml version="1.0" encoding="utf-8"?><!-- Generator: Adobe Illustrator 28.0.0, SVG Export Plug-In --><svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"><style type="text/css"> .st0{fill:#1E1E1E;} .st1{fill:none;stroke:#1E1E1E;stroke-width:2;}</style><g id="Capa_2_00000123456789"> <path class="st0" d="M12,2L15.09,8.26L22,9.27"/></g></svg>Y aquí el problema es de otra categoría.
El prólogo XML, el comentario del generador y version="1.1" son bytes muertos. Inofensivos y prescindibles.
x="0px" y="0px", enable-background y xml:space="preserve" son atributos obsoletos o sin efecto. enable-background fue una propiedad de la especificación de filtros que ningún motor implementó.
El bloque <style> con clases st0, st1. Este es el peligroso, y no por colisión de identificadores sino por algo peor: son selectores globales de CSS. Si inlinas ese SVG en una página, esas reglas se aplican a cualquier elemento del documento que tenga la clase st0. Dos iconos de Illustrator en la misma página se pisan las reglas mutuamente, porque los dos definen .st0 y gana el último. Y si por casualidad tu propio CSS usa una clase con ese nombre, el icono la repinta.
Es la diferencia de gravedad entre los dos exportadores: Figma produce colisiones de identificadores dentro del SVG; Illustrator produce colisiones de CSS en toda la página.
La opción de exportación de Illustrator que lo evita se llama, según la versión, «Atributos de presentación» en el desplegable de estilo. Elegirla resuelve el problema en el origen.
Por qué currentColor no funciona de fábrica
Ninguna herramienta de diseño tiene el concepto de «color heredado del contexto», porque en un lienzo de diseño no hay contexto. Todo color es un valor concreto.
De modo que la sustitución de los colores por currentColor es un paso que siempre hay que hacer en el pipeline o a mano. No existe una opción de exportación que lo haga.
// Sustitucion basica para un icono monocromofunction aCurrentColor(svg, colorOriginal = '#1E1E1E') { const re = new RegExp(colorOriginal.replace('#', '#'), 'gi'); return svg .replace(re, 'currentColor') .replace(/\sfill="none"(?=[^>]*<svg)/, ''); // el fill del raiz}Ese código es un punto de partida y no una solución general, porque los iconos multicolor necesitan un mapeo de varios colores a varias variables. El enfoque robusto es acordar con el equipo de diseño una paleta cerrada de tokens que se usa en los iconos, y mapear cada uno a su variable CSS. Entonces la sustitución es determinista.
Qué se corrige dónde
| Rasgo | Se corrige en |
|---|---|
Prólogo XML, comentarios, version |
Pipeline |
Bloque <style> con clases |
Herramienta, cambiando la opción de exportación |
id de capas |
Pipeline |
clipPath innecesario |
Herramienta, quitando el recorte del marco |
| Colores literales | Pipeline, sustituyendo por currentColor o variables |
| Decimales excesivos | Pipeline |
| Grupos vacíos y transformaciones | Pipeline |
| Trazos expandidos | Herramienta, no expandiendo |
| Efectos y filtros | Herramienta, quitándolos |
La columna de la derecha reparte el trabajo, y el reparto no es negociable: lo que se pierde en la exportación no se puede recuperar en el pipeline. Un trazo expandido no se puede desexpandir.