使用外部引用的 SVG `use` 元素

Avatar of Chris Coyier
Chris Coyier 发布

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

SVG 有一个 <use> 元素,其本质含义是:去查找具有此 #identifier 的 SVG 片段,对其进行克隆,并将其放置在当前位置。它是 SVG 图标系统 的重要组成部分。关于这一点,我们有一些之前 未涉及 的内容需要了解。

作为提醒,它看起来像这样

<!-- Reference IN THIS SAME DOCUMENT -->
<svg>
  <use xlink:href="#icon-1"></use>
</svg>

<!-- EXTERNAL reference -->
<svg>
  <use xlink:href="sprite.svg#icon-1"></use>
</svg>

该 #icon-1 标识符很可能引用该文件中的一个符号,例如…

<svg xmlns="http://www.w3.org/2000/svg">
  
  <symbol id="icon-1" viewBox="0 0 1024 1024">
    <title>Kinda like alt text</title>
    <path class="path-1" d="..."></path>
  </symbol>

  ...

</svg>

外部引用的好处在于它可以很好地利用浏览器缓存。

此外,它也很容易使用。您只需将正确的文件路径提供给文件(“SVG sprite”)并引用一个标识符,它就能正常工作。您可以让服务器设置该文件的所有正确标头,以便浏览器像保留任何其他要缓存的资产一样保留它。

问题在于 IE,但它正在被修复。

大多数支持内联 SVG 的浏览器都支持此功能,因此它几乎可用,但主要例外是 IE。但是他们已经 在 Microsoft Edge 中修复了该问题。Edge 还没有很大的市场份额,但它是 Windows 的未来,因此最终我们将能够在没有任何额外工作的情况下开始使用它。

由于缺乏完美支持,因此有两种主要的解决方法。

  1. 在所有 HTML 文档中包含 SVG sprite。效果很好。通常非常快,但会增加页面缓存的大小。为了获得最佳支持,您需要将其包含在文档顶部,这意味着可能更重要的内容的渲染会稍有延迟。或者…
  2. 使用 Ajax 加载 sprite。 然后可以利用浏览器缓存。但是,如果没有一点 FONI(无图标闪烁),这可能很难做到。

一旦我们能够直接开始使用外部引用,情况就不一样了

这个概念让我感到困惑,这就是我想要写这篇文章的原因。

我以为外部引用是最终的解决方案,因为它可以完成内联 SVG 引用同一文档中 SVG 所能完成的所有操作。但不幸的是,它做不到。以这种方式引用的 SVG 具有其自己的独立 DOM。它超出了所有 <use> 都受制于的常规 Shadow DOM 边界。

使用此方法

<svg class="icon-1">
  <use xlink:href="#icon-1"></use>
</svg>

您可以编写 CSS(在您用于网站其余部分的同一样式表中)来对其进行着色

/* This works.
  It will cascade this fill through the shapes,
  as long as there are no presentational fill 
  attributes on the shapes themselves. */
.icon-1 {
  fill: red;
}

实际上,您仍然可以使用外部引用的 <use> 来做到这一点。但是您无法像以前那样设置单个形状的样式。

/* You could reach individual shapes 
   to style because they share the same DOM. 
   But this WON'T WORK with externally referenced SVG. */
.path-1 {
  fill: yellow;
}

/* This won't work either way,
   because it crosses a shadow DOM boundary */
.icon-1 /* ~shadow~ */ .path-1 {
  fill: yellow;
}

当您外部引用时,您根本无法访问内部形状。例如,从 HTML 文档中

<script>
  var shape = document.querySelectorAll(".path-1");
  console.log(shape);
  // [ ] (empty set)
</script>

这是一个 gist,它有点强调了这一点。

它仍然很酷。

级联单一颜色仍然有效的事实使其非常有用。大多数图标往往是单色的。而且您仍然可以拥有不同的单色。

奇怪的未来事物

Tab Atkins 以其疯狂的未来思维方式记录了一些潜在的未来想法,称为 SVG 参数

.foo {
  background-image: url("http://example.com/image.svg" param(--color var(--primary-color)));
}

这是一个 CSS 示例,但大概内联 SVG 也能使用。