¿Cómo aplicar un estilo a un SVG incrustado?

107

Cuando un SVG se incluye directamente en un documento mediante la <svg>etiqueta, puede aplicar estilos CSS al SVG a través de la hoja de estilo del documento. Sin embargo, estoy tratando de aplicar un estilo a un SVG que está incrustado (usando la <object>etiqueta).

¿Es posible utilizar algo como el siguiente código?

object svg { 
    fill: #fff; 
}
Joshua Sortino
fuente
1
Se me ocurrió una forma liviana de hacer esto que funcionaría muy bien para lo que estás tratando de hacer. Vea estas preguntas y respuestas: stackoverflow.com/questions/11978995/…
Drew Baker
Aquí hay una respuesta que realmente hace el trabajo (de Manipulación de propiedades de estilo de archivo svg externo con CSS )
Fabien Snauwaert

Respuestas:

108

Respuesta corta: no, ya que los estilos no se aplican a través de los límites del documento.

Sin embargo, dado que tiene una <object>etiqueta, puede insertar la hoja de estilo en el documento svg usando script.

Algo como esto, y tenga en cuenta que este código asume que se <object>ha cargado completamente:

var svgDoc = yourObjectElement.contentDocument;
var styleElement = svgDoc.createElementNS("http://www.w3.org/2000/svg", "style");
styleElement.textContent = "svg { fill: #fff }"; // add whatever you need here
svgDoc.getElementById("where-to-insert").appendChild(styleElement);

También es posible insertar un <link>elemento para hacer referencia a una hoja de estilo externa:

var svgDoc = yourObjectElement.contentDocument;
var linkElm = svgDoc.createElementNS("http://www.w3.org/1999/xhtml", "link");
linkElm.setAttribute("href", "my-style.css");
linkElm.setAttribute("type", "text/css");
linkElm.setAttribute("rel", "stylesheet");
svgDoc.getElementById("where-to-insert").appendChild(linkElm);

Otra opción más es usar el primer método para insertar un elemento de estilo y luego agregar una regla @import, por ejemplo styleElement.textContent = "@import url(my-style.css)".

Por supuesto, también puede vincular directamente a la hoja de estilo desde el archivo svg, sin hacer ningún script. Cualquiera de los siguientes debería funcionar:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="my-style.css" type="text/css"?>
<svg xmlns="http://www.w3.org/2000/svg">
  ... rest of document here ...
</svg>

o:

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <link href="my-style.css" type="text/css" rel="stylesheet" 
          xmlns="http://www.w3.org/1999/xhtml"/>
  </defs>
  ... rest of document here ...
</svg>

Actualización 2015: puede usar el complemento jquery-svg para aplicar scripts js y estilos css a un SVG incrustado.

Erik Dahlström
fuente
¿Es este un método para vincular una hoja de estilo externa? Si no es así, ¿es posible?
Joshua Sortino
Lo anterior inserta un elemento de estilo en el archivo svg. Sí, también es posible insertar un elemento de enlace xhtml para vincular a una hoja de estilo externa, o posiblemente una instrucción de procesamiento de hoja de estilo xml (consulte w3.org/Style/styling-XML.html ).
Erik Dahlström
¡Esto es bastante asombroso Erik! Sin embargo, no pude lograr que este truco funcionara en Chrome sin incluir svgweb: code.google.com/p/svgweb ... ¿Alguna idea de lo que estoy haciendo mal?
Matt WD
1
@ MattW-D: probablemente debería abrir una nueva pregunta para eso. Svgweb no es necesario en Chrome.
Erik Dahlström
Gracias Erik, estaba realmente luchando para que font-face funcionara en svg a través de css, ¡vincular el css con el svg funcionó al primer intento y milagrosamente cruzar el navegador!
Dave
10

Puede hacer esto sin javsscrpt colocando un bloque de estilo con sus estilos dentro del archivo SVG.

<style type="text/css">
 path,
 circle,
 polygon { 
    fill: #fff; 
  }
</style>
R Reveley
fuente
3

Si la única razón para usar la etiqueta para incluir el SVG es que no desea saturar su código fuente con el marcado del SVG, debe echar un vistazo a los inyectores SVG como SVGInject .

La inyección SVG usa Javascript para inyectar un archivo SVG en línea en su documento HTML. Esto permite un código fuente HTML limpio al tiempo que hace que los SVG sean completamente estilizados con CSS. Un ejemplo básico se ve así:

<html>
<head>
  <script src="svg-inject.min.js"></script>
</head>
<body>
  <img src="image.svg" onload="SVGInject(this)" />
</body>
</html>
Waruyama
fuente
¡Increíble! Gracias por la ingeniosa herramienta.
Deleplace el