我需要创建许多SVG文件,并且希望在一个文件中保留一组公共符号,并将它们导入其他文件中。
我使用了一个<use>
元素:
<use href="common.svg#symbol1" />
问题是,如果common.svg
具有影响元素的CSS样式,则该样式在导入元素的文件中没有影响。
我在svgur.com上传了两个SVG来显示:
https://svgur.com/i/bYv.svg
定义一个id为ball
的圆圈,该圆圈受在其周围设置红色边框的样式影响。
<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<style>#ball { stroke:#ff0000; stroke-width:10; }</style>
<circle id="ball" cx="50" cy="50" r="45" />
</svg>
https://svgur.com/i/bXA.svg
使用圆形。圆圈可见,但边框不可见。
<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<use href="bYv.svg#ball" />
</svg>
问题:
这是我正在使用的SVG渲染器的一个错误,还是它的行为方式?
我尝试的每个渲染器(chrome、firefox、inkscape)都显示相同的结果,所以我怀疑这可能是预期的行为。
有没有办法从外部SVG文件和影响它的CSS样式中导入元素,使其看起来与原始文档中完全一样?
- 这是我正在使用的SVG渲染器的一个错误,还是它的行为方式
这是预期行为。CSS规则不适用于文档边界。您正在将SVG导入到主文档中,但CSS在另一个文档中。
- 有没有办法从外部SVG文件导入元素以及影响它的CSS样式
否。
好吧,我想你可以从技术上写一些Javascript来加载另一个文件并提取CSS规则。但我强烈怀疑你不想那样做。
您的SVG";精灵文档";<style>
标记中不应包含CSS规则。
最好的方法是预先准备要用作精灵的SVG。
我要做的是将common.svg
导入到矢量编辑器中,并将所有CSS属性转换为表示属性。例如,Illustrator允许您在导出SVG时选择样式设置方法。
你想要的是这样的东西:
<svg>
<style>
.st0 {
fill: red;
}
</style>
<symbol id="whatever">
<path d="..." class="st0"/>
</symbol>
</svg>
转换为:
<svg>
<symbol id="whatever">
<path d="..." fill="red"/>
</symbol>
</svg>
根据可缩放矢量图形(SVG)2规范(W3C编辑草案,2021年6月8日)似乎应该在导入元素的地方应用原始文档的样式。
第5.5条。"使用"元素:
克隆的内容继承了"use"元素的样式,可以成为用户事件的目标。但是,这些克隆的元素实例仍然链接到引用的源,并反映原始源中的DOM突变。此外,在引用元素的作用域中应用的所有样式规则也应用于克隆的阴影树的作用域。
和5.5.3。风格范围界定和继承:
use元素shadow tree和其他shadow树一样,展示了CSS Scoping模块[CSS-scopeing-1]中定义的样式封装。这意味着阴影树中的元素从其宿主"use"元素继承样式,但外部文档中定义的样式规则与阴影树中元素不匹配。相反,影子树维护自己的样式表列表,其CSS规则与影子树中的元素相匹配。
当引用的元素来自外部文档时,处理该文档时生成的样式表对象应用于影子树,并且是只读的。样式表中的所有URL引用,包括仅限片段的引用,都必须相对于包含引用元素的文档的URL进行绝对化。用户代理可以对引用相同外部文档的任何阴影树重用相同的样式表对象。
所以我尝试的浏览器和SVG渲染器不符合标准。
我仍在寻找在现有SVG用户代理上模拟这种行为的方法。
如果您的svg资产代码是内联,则将应用您的样式
<svg style="display:none" class="svg-asset" width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<style>
#inline-ball { stroke:#ff0000; stroke-width:10; }
</style>
<circle id="inline-ball" cx="50" cy="50" r="45" />
</svg>
<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<use xlink:href="#inline-ball" />
</svg>
如果你不喜欢内联svg代码,那么"片段标识符">可能是更好的嵌入方法。
这基本上是一个sprite概念:
因此,您的图像资产(如符号)需要在sprite窗格上以一定的x或y偏移进行定位(与可以重叠定位的符号不同)。实际上,您正在加载一个完整的svg,其中包括嵌入的css样式元素,但选择了一个特定的视图框架。
请参阅css.tricks.com上的这篇文章
css.trics.com:SVG片段标识符如何工作
你的svg会像这个一样
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 32 96" >
<g id="icon01">
<path d="M20.6,23.3L14,16.7V7.9h4v7.2l5.4,5.4L20.6,23.3z M16-0.1c-8.8,0-16,7.2-16,16s7.2,16,16,16s16-7.2,16-16S24.8-0.1,16-0.1z M16,27.9c-6.6,0-12-5.4-12-12s5.4-12,12-12s12,5.4,12,12S22.6,27.9,16,27.9z"/>
</g>
<g id="icon02">
<path d="M32,43.2c0,2.7-1.2,5.1-3,6.8l0,0l-10,10c-1,1-2,2-3,2s-2-1-3-2l-10-10c-1.9-1.7-3-4.1-3-6.8c0-5.1,4.1-9.2,9.2-9.2c2.7,0,5.1,1.2,6.8,3c1.7-1.9,4.1-3,6.8-3C27.9,33.9,32,38.1,32,43.2z"/>
</g>
<view id="icon-clock-view" viewBox="0 0 32 32" />
<view id="icon-heart-view" viewBox="0 32 32 32" />
</svg>
为了使用片段标识符,我们需要添加具有相应sprite区域坐标(在viewBox属性中定义)的<view>
元素
与符号定义不同,我们不会在视图元素中嵌套实际路径数据。
嵌入html的方法是将目标ID添加到我们的src-url中。
<img class="svg-fragment" src="fragment-ready-1.svg#icon-heart-view">
然而,在html中内联svg图形仍然提供了最好的样式控件。(例如,在您的网站css文件中设置元素样式)
也许我们将来会看到对远程嵌入svg资产样式的额外支持。。。在那之前,我们仍然需要应对一些浏览器的怪癖。