简体   繁体   English

如何将样式应用于嵌入式 SVG?

[英]How to apply a style to an embedded SVG?

When an SVG is directly included in a document using the <svg> tag, you can apply CSS styles to the SVG via the document's stylesheet.当使用<svg>标签将 SVG 直接包含在文档中时,您可以通过文档的样式表将 CSS 样式应用于 SVG。 However, I am trying to apply a style to an SVG which is embedded (using the <object> tag).但是,我正在尝试将样式应用于嵌入的 SVG(使用<object>标签)。

Is it possible to use anything such as the following code?是否可以使用诸如以下代码之类的任何内容?

object svg { 
    fill: #fff; 
}

Short answer: no, since styles don't apply across document boundaries.简短回答:不,因为样式不适用于跨文档边界。

However, since you have an <object> tag you can insert the stylesheet into the svg document using script.但是,由于您有一个<object>标签,您可以使用脚本将样式表插入到 svg 文档中。

Something like this, and note that this code assumes that the <object> has loaded fully:像这样,请注意,此代码假定<object>已完全加载:

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);

It's also possible to insert a <link> element to reference an external stylesheet:也可以插入一个<link>元素来引用外部样式表:

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);

Yet another option is to use the first method, to insert a style element, and then add an @import rule, eg styleElement.textContent = "@import url(my-style.css)" .另一种选择是使用第一种方法,插入一个样式元素,然后添加一个@import 规则,例如styleElement.textContent = "@import url(my-style.css)"

Of course you can directly link to the stylesheet from the svg file too, without doing any scripting.当然,您也可以直接从 svg 文件链接到样式表,而无需编写任何脚本。 Either of the following should work:以下任何一项都应该有效:

<?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>

or:或者:

<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>

Update 2015: you can use jquery-svg plugin for apply js scripts and css styles to an embedded SVG. 2015 年更新:您可以使用jquery-svg插件将 js 脚本和 css 样式应用于嵌入式 SVG。

You can do this without javsscrpt by putting a style block with your styles inside the SVG file itself.您可以通过在 SVG 文件本身中放置一个带有您的样式的样式块来在没有 javsscrpt 的情况下执行此操作。

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

If the only reason for using the tag to inlcude the SVG is that you do not want to clutter your source code with the markup from the SVG, you should take a look at SVG injectors like SVGInject .如果使用标记来包含 SVG 的唯一原因是您不想用来自 SVG 的标记来混淆源代码,那么您应该看看像SVGInject这样的 SVG 注入器。

SVG injection uses Javascript to inject an SVG file inline into your HTML document. SVG 注入使用 Javascript 将 SVG 文件内联注入到您的 HTML 文档中。 This allows for clean HTML source code while making the SVGs fully styleable with CSS.这允许干净的 HTML 源代码,同时使 SVG 完全可以使用 CSS 进行样式化。 A basic example looks like this:一个基本示例如下所示:

<html>
<head>
  <script src="svg-inject.min.js"></script>
</head>
<body>
  <img src="image.svg" onload="SVGInject(this)" />
</body>
</html>

Based on @Erik Dahlström answer, found a short path as follow:根据@Erik Dahlström 的回答,找到了一条短路径如下:


let svg_objecst = document.getElementsByClassName('svg-object')

const forceStylingObjSvg = (svg)=>{
    var svgDoc = svg.contentDocument;
    svgDoc.firstElementChild.setAttribute('fill','blue')
}
Array.from(svg_objecst).forEach((obj)=>{
    obj.addEventListener('load',()=>forceStylingObjSvg(obj))
})


You can create a custom element to inject the SVG file into your html.您可以创建一个自定义元素来将 SVG 文件注入到您的 html 中。

This way, the SVG will be inlined, and you can easily apply styles using CSS.这样,SVG 将被内联,您可以使用 CSS 轻松应用样式。

This custom element will work just like the <object> or <embed> tags.这个自定义元素将像 <object> 或 <embed> 标签一样工作。 The only difference is that <object> or <embed> tags injects the data in a shadow root, which prevents styling from the parent document, while <custom-svg> injects the data in the document itself.唯一的区别是 <object> 或 <embed> 标签在影子根中注入数据,这会阻止父文档的样式,而 <custom-svg> 将数据注入文档本身。

I have tried too many ways to style my SVG images, and this was the easiest and more flexible way i have found so far.我尝试了太多方法来设置 SVG 图像的样式,这是迄今为止我发现的最简单、更灵活的方法。

<html>
  <head>
    <style>
      .blue {
        fill: blue;
      }
      .red {
        fill: red;
      }
    </style>
  </head>
  <body>
    <custom-svg class="blue" src="icon.svg"></custom-svg>
    <custom-svg class="red" src="icon.svg"></custom-svg>

    <script>
      class CustomSVG extends HTMLElement {
        constructor() {
          super();
        }
        connectedCallback() {
          fetch(this.getAttribute('src'))
            .then(response => response.text())
            .then(text => {
              this.innerHTML = text;
            });
        }
      }
      customElements.define('custom-svg', CustomSVG);
    </script>
  </body>
</html>

Notes笔记

  • The SVG image must not have the "fill" attribute if you want, for example, change the fill color using CSS.例如,如果您想使用 CSS 更改填充颜色,则 SVG 图像不得具有“fill”属性。

custom-svg works very good, for width style use this: custom-svg 效果很好,对于宽度样式,请使用:

custom-svg svg{
  max-width:64px;
  max-height:64px;
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM