以下内容是由 Rob Levin 撰写的客座文章。Rob 是 Mavenlink 的高级 UI/UX 开发人员,也是 Unicorn UI CSS 按钮库 的合著者。他们的 2.0 版本使用了一个 SVG 图标系统,在这里他分享了一些他在此过程中遇到的问题,以及你如何注意并解决这些问题。此外,Rob 还提供了一个你可以使用的完整系统,包括一个可工作的构建过程和演示。
你已经阅读了有关内联 SVG 比字体图标更好的内容,并准备开始尝试。你与你的团队开会,讨论迁移到内联 SVG 图标。你的老板持怀疑态度。他看着你的眼睛说:“所以,你能保证这不会反过来咬我们吗?”你犹豫了一下,但不知何故鼓起勇气,确定地回答:“是的,这绝对是我们需要前进的方向!”
这只是我几个月前的情况,以下是我遇到的“陷阱”以及相应的解决方法。我将首先逐一检查这些解决方法,然后在最后提供一个可工作的示例。
请注意,这不是一篇说服你应该使用内联 SVG 的文章。为此,你应该阅读这篇文章 流行的 CSS-Tricks 文章,它指出了内联 svg 比图标字体更具优势。
陷阱一:未命中目标
为了使用外部 SVG 文件实现缓存(你真的不想以不可缓存的方式将 ~1.5kb * 50
个图标倾倒在你的页面上,对吧?!),你需要在你的页面上包含 svg4everybody 库。本质上,这个 shiv 将使用 UA 探测来检测你是否正在运行一个不支持正确缓存外部定义文件的 “问题版本” 的 IE 或 Android,如果是的话,它将删除所有 svg use
元素,并用包含相应的 SVG 定义数据的嵌入元素替换它们,这些数据是通过 ajax 获取的。归根结底,我们只关心原始 SVG 的样子,它可能看起来像这样
<svg viewBox="0 0 16 16">
<use xlink:href="/path/to/svgdef.svg#your-icon" … ></use>
</svg>
将被替换为一个看起来像这样的嵌入元素
<svg viewBox="0 0 16 16">
<path> ... </path>
</svg>
CSS:命中目标
根据源 SVG,你最终可能会得到一个类似这样的层次结构:svg path
(如上所示),或者可能是 svg g
,或者可能是组合的组和路径后代 - 但请记住,你需要你的 CSS 来定位“polyfilled”的情况 - 这意味着你的 CSS 规则绝对不应该直接定位 svg > use
元素...它将在 IE 中被完全删除!
JavaScript:命中目标
同样的想法也适用于对 SVG 克隆本身的任何 JavaScript 操作。例如,我们可能想要在悬停时 交换图标,我们可能选择的一种技术是,当这样的事件触发时,用 JavaScript 更改 xlink:href
属性。由于在本文中,我们选择使用具有上述描述的 shiv 的外部文件,因此我们不能可靠地使用这种技术(同样,use
元素在 IE 中被替换)。我的建议是,只使用 CSS 类隐藏/显示(在 交换 SVG 图标 文章中描述的技术 #1),并确保定位 SVG 克隆本身。
如果我们直接在页面顶部(例如,在打开的 <body>
标签之后)插入内联 SVG 定义,我们就不必担心这个问题,并且可以使用操作 xlink:href
属性的技术。
选择器示例
为了让上述要点更加清晰,以下是一个在完全支持外部 SVG 定义的浏览器中有效的 CSS 选择器,但在 svg4everybody 对 IE 进行 polyfill 时失效
.my-svg use {
fill: red;
}
事实证明,没有必要或好处去定位 use
,所以只需将其更改为以下内容即可在所有情况下都能正常工作
.my-svg {
fill: red;
}
既然我们正在谈论选择器,我们应该借此机会指出,你将无法使用类似以下方法“进入”原始 SVG 定义
svg.parent path.child { /* won't work! */ }
同样的情况也适用于尝试通过克隆实例(无论是形状、路径、组等)对 def 中的任何内容进行样式设置。这可能很明显,但这里只有在我们使用 use xlink:href
策略时才会出现问题。
陷阱二:与设计师合作
如果你的图标通常只使用一种颜色,那么使用 fill: <your-color>
将 CSS 样式应用于克隆实例的“一次性操作”非常简单。对于这种情况,项目中的设计师需要注意以以下两种方式之一创建矢量图:仅使用黑色填充和透明描边,或者仅使用路径数据(透明填充和描边)。如果你需要,仍然可以通过 CSS 应用描边。
要理解为什么会出现这种情况,我们首先需要了解我们的矢量应用程序如何导出 SVG。
我使用 Adobe Illustrator,但如果你使用其他矢量程序,例如 Inkscape 或 Sketch 等,你可能需要参考该软件的文档,看看它们的运行方式是否与以下内容一致。最糟糕的情况是你只需按照以下描述的各种方式导出文件,并测试你的应用程序生成的 SVG 看起来像什么。
Illustrator SVG 导出行为
在撰写本文时,最新版本的 Illustrator CC 将 SVG 导出如下
- 如果你没有定义填充或描边,或者你只定义了填充,但该填充是黑色(完全黑色,如
#000
),那么导出的 SVG 路径和形状将不包含填充或描边属性
<path ... positional information ... >
<rect ... positional information ... >
- 如果你定义了非黑色的填充,或者如果你定义了描边(任何颜色,包括黑色),那么导出的 SVG 的相应路径和形状将包含描边和/或填充属性,例如
<path stroke="#000000" ... >
<rect fill="fabdad" ... >
如果你直接对 SVG 符号、路径、形状等应用样式,这些表示属性始终可以被 CSS 覆盖。在下一节中将描述与将 CSS 应用于克隆实例(而不是直接应用)相关的注意事项。
导出黑色填充和透明描边
如果你的源 SVG 仅使用黑色填充(没有描边)或仅使用路径进行导出,那么你将拥有很大的灵活性,因为你可以通过 CSS 应用描边或填充。

在这个第一个示例中(请注意我使用的是 SCSS 语法),我们向克隆实例应用了 CSS 填充和描边
.filled-instance {
stroke: #cc8ac1;
stroke-width: 5px;
fill: lighten(#cc8ac1, 20%);
}
你还可以通过简单地关闭填充并通过 CSS 应用描边来实现轮廓效果
.filled-instance-off {
stroke: #d08aaf;
stroke-width: 5px;
fill: transparent;
}
之所以能够如此完美地实现,是因为我们的 SVG 定义没有定义任何填充或描边属性,因此我们的 CSS 会被应用,一切正常。
导出透明填充和描边

这里的不利消息是,你无法将样式应用于克隆实例的描边(请记住,在这个例子中,我们的克隆实例指向我们用“仅描边”创建的 SVG 定义)。我们也不能将填充应用于我们的克隆实例,因为我们的 SVG 形状现在有 `fill="none"`,这将具有优先权。)
.stroked-instance {
stroke: green; /* nothing happens */
fill: red; /* nothing happens */
}
这与 HTML/CSS 类似,比如
<div id="very-strong">
<span>still green.</span>
</div>
#very-strong { color: red; }
span { color: green; } /* I'm the actual element, so I win. */
一些解决方法
你可能应该完全避免这种情况,通过导出具有透明描边的黑色填充,或者只是路径,但是,如果你由于某种原因仍然需要你的样式生效,你将不得不直接用类似于以下内容的样式来设置 SVG 符号:
symbol#completed-copy-stroked [stroke] {
stroke: #dd6435;
stroke-width: 5px;
}
请注意,上面的选择器中的 `symbol` 部分是不必要的,但在这里使用是为了清楚地说明我们所针对的元素。
同样,如果你正在使用内联 SVG 和克隆实例的方法,这不是理想的,因为我们希望尽可能地将样式应用于克隆实例。
你始终可以使用另一种技术,就是直接在源 SVG 中添加类,并直接将 CSS 应用于这些类。这些样式将是全局的,这可能是一个问题,也可能不是问题——你必须根据自己的情况决定。无论你如何导出 SVG,这种技术都有效。因为你正在手动添加 CSS 类,所以你可以使用它(尽管是直接的——我们直接针对 SVG 定义的子元素,而不是通过克隆实例进行样式化)。
.ibestrokin {
stroke: magenta;
stroke-width: 5px;
}
.istrokeittotheeast {
stroke: green;
stroke-width: 7px;
}
也许我暴露了我的年龄,但我忍不住想到 Clarence Carter,所有关于 “strokin” 的谈话。
在我看来,只能够直接设置 SVG 样式(而不是克隆实例),并不理想。因此,我的建议是,在使用内联 SVG 和克隆实例的情况下,避免完全导出描边。如果你已经有定义了描边的艺术作品,你可以使用类似于“轮廓描边”之类的工具将它们转换为路径,然后再导出。
查看 CodePen 上 Rob Levin (@roblevin) 的笔 内联 SVG 填充和描边。
后期处理
另一个需要考虑的问题是,如果你使用的是 grunt-svgstore 等后期处理库来清理填充和描边。在这种情况下,生成的 SVG 可能根本没有显式的填充或描边属性,并且只有路径信息将保留在生成的定义文件中。对于这种情况,你绝对需要将所有描边转换为路径,否则可能会完全丢失相应的可见线条。或者,不要要求后处理器删除描边(但要面对我之前讨论过的一些问题)。底线是,如果你的艺术作品必须有描边,那么你将不得不直接针对 SVG 进行设置。
结论
因此,我认为关键在于,你需要与设计师一起决定,你是希望通过 CSS 完全控制所有填充和描边——在这种情况下,你应该只使用具有透明填充和描边的路径(或者如果你希望保留填充用于参考,则使用黑色填充)——还是更合理的方式是从合理的默认值开始,然后使用 CSS 根据需要覆盖这些默认值。如果你使用内联 SVG,并且希望对克隆实例进行样式设置(而不是直接对 SVG 进行样式设置),我的建议是只使用路径。
问题三:实现颜色变化
一般来说,使用 SVG 的一个好处是可以灵活地控制样式,因为我们可以将 CSS 应用于 SVG 的 `path`、`shape` 等。但是,使用 `use xlink:href` 机制会导致一个 未公开的克隆 DOM 树,我们的 `fill` 或 `stroke` 样式将全局应用于引用的 SVG。这意味着所有克隆实例将共享相同的填充颜色。
幸运的是,我们有一个技巧,至少可以为每个实例获得一种独特的颜色。如果我们进入 SVG 定义本身,我们可以将 `fill=“currentColor”` 应用于我们选择的形状或路径。这有什么作用呢?好吧,长期支持的 CSS 值 `currentColor` 指定颜色将被继承。这意味着我们可以在树中更高的地方定义字体颜色(例如,在克隆实例本身),并且该路径或形状的填充将继承颜色。我不确定是谁第一个想到这个方法的,但我将把功劳归功于我第一次看到它的地方:Jenna Smith 的推文。
实现
我们从基础填充开始,它可能看起来像这样
.icon-primary {
fill: #ccc;
color: #3bafda;
}
这些类将被放置在未公开的 `svg` 克隆实例上。
<svg class="icon-primary"> ...
现在,神奇的事情开始发生了——我们的 `fill` 定义了图标的常规填充颜色(在本例中为 `#cc`),但现在我们的字体 `color` 定义了我们上面描述的继承的强调颜色,如下所示:
<path fill="currentColor" ... />

如果你在构建过程中使用 grunt-svgstore(本文末尾的示例使用它),你可能会将其配置为通过 `cleanup` 属性删除不需要的杂物,并且这个库现在 保留具有 `currentColor` 值的填充属性……所以你不用担心破坏上面定义的自定义属性。
我创建了一个 Sass 混合宏(故意兼容到 3.2 版本)来实现这个功能
@mixin svgColors($fill: false, $color: false, $patchCurrentColorForIE: false) {
@if $fill {
fill: $fill;
}
@if $color {
color: $color;
}
}
我使用类似以下内容来调用它
.icon-primary {
@include svgColors($neutralColor, $primaryColor, true);
}
如果你想知道 `$patchCurrentColorForIE` 参数的作用,我将其添加到不需要多种颜色的图标中,因此不需要应用 shim。
其他颜色变化技术
除了使用上面列出的 `currentColor` 技术之外,你还可以使用 grunt-svgstore 中现在可用的 `preserve--` 属性功能。它的工作原理是,如果你使用 `preserve--` 作为源 SVG 中任何有效属性的前缀,该属性将被强制保留在生成的 SVG 中(`preserve--` 前缀将被删除)。例如,`preserve--stroke` 将在输出 SVG 定义中只生成 `stroke`。
如果你想知道如何实现颜色变化,特别是对于 `background-image` 来说,另一种需要考虑的技术是使用 SVG 的 `data-uri`,但首先要对 `fill` 值进行搜索和替换,就像 这里描述的那样。但是,这种方法有点超出本文的范围,并且偏离了主题,因为它意味着使用不可缓存的 `data-uri`,违背了我们使用可缓存的外部 SVG 定义文件的首要目标。
问题四:jQuery 抛出错误
如果你在页面上包含了 jQuery,直接点击渲染的 `svg use` 元素可能会导致 jQuery 抛出一个错误,该错误在他们的 错误追踪器 中有记录。实际上,这个错误有点难重现,因为你很可能会有一个包含块元素作为锚点或按钮——并且该元素将具有更大的点击区域——但是,如果你直接点击图标本身,同样会发生。以下是推荐的解决方法
svg { pointer-events: none; }
由于 `pointer-events` 是继承的,这将导致任何 SVG “子元素”也不响应 `pointer-events`。设置好之后,你应该注意确保任何事件处理(例如 JavaScript 的 `click` 处理程序)都是由祖先元素处理的,而不是由未公开的 SVG 克隆本身处理的——按钮或锚点是明显需要在这种情况下进行事件处理的包装元素示例。
如果你确实打算在 SVG 本身处理鼠标或指针事件(用于动画等),你可能应该考虑只使用 `img` 或 CSS `background` 标签来处理该特定 SVG;这样做将使这个问题不再存在。
问题五:GitHub 差异
我们当时的一个担心是,SVG 差异对于潜在的代码审阅者来说可能过于陈旧。Chris Coyier 指出,GitHub 最近发布了一个很棒的 SVG 查看功能,它允许您切换对Blob 的查看。非常方便。

此外,将此类 SVG 工作保留在单独的提交中(这样它不会混淆更有意义的代码更改)的团队范围策略可能是务实的选择。
一个工作示例
我已经设置了一个“玩具示例”,希望您会发现它很有用。它使用 Grunt 工作流程实现内联 SVG,并依赖于可缓存的外部 SVG 定义文件。请注意,此示例需要 IE9 及更高版本。
如果您还没有准备好进行设置,这是一个演示页面,展示了我们将要部署的内容。
如果您需要支持 IE8 及更低版本,您可以回退到与您的 SVG 同名的 png 图像(但扩展名为 .png)。设置方法在 svg4everybody 库的说明中进行了描述,我们已经在使用它了,因此请从那里开始。
要运行示例,您需要安装以下内容
在您的终端中运行以下命令以获取示例并在本地部署它
根据您的系统设置,您可能需要在以下两个 `npm install` 命令之前使用 `sudo`
# Install the Buttons example and set up npm dependencies
git clone -b svg-inline-experiments --single-branch https://github.com/unicorn-ui/Buttons.git Buttons && cd Buttons && npm install
# Install the SVG specific dependencies and run example
pushd svg-builder && npm install && grunt && popd && grunt dev
使用这些命令,我们
- 克隆存储库,仅获取相关的 `svg-inline-experiments` 分支
- 安装按钮节点依赖项
- 安装 SVG 生成器节点依赖项
- 运行我们的 Grunt 开发工作流程,该工作流程会构建示例的内联 SVG 定义,还会构建示例页面
根据您的设置,最后一步应该会在您的系统默认浏览器中打开以下页面(如果没有,请手动访问 http://localhost:8000)

如果您想对这种设置进行逆向工程以告知您自己的项目设置,您需要参考的文件是
styleguide/includes/svg.html
显示用于创建 SVG 实例的标记styleguide/scss/module/_svgs.scss
显示应用于我们的 SVG 图标的 CSS 样式svg-builder/Gruntfile.js
专为内联 SVG 定制的工作 Grunt 配置styleguide/pages/index.html
您需要在这个文件中注意的唯一一件事是,我们包含了svg4everybody.min.js
结论
在成功解决上述挑战之后,我断言构建现代 Web 应用程序的团队现在应该认真考虑使用内联 SVG。 Unicorn-UI 正在为我们最近发布的 Buttons 2.0 Beta 实现一个“交互式游乐场”,出于显而易见的原因,我们肯定会利用内联 SVG 来完成该项目……也许您也应该在您的下一个项目中考虑它。
作为 SVG 高级使用的后续内容,您绝对需要观看 此演讲!它深入探讨了浏览器支持,以及您想要避免的更多怪癖。
谢谢 Nico……我会下班后看看的。
如果从您的图形程序中导出的 SVG 代码具有表示属性(以属性形式指定的笔划/填充颜色),您可以强制浏览器忽略它们并使用您在样式表中为各个图标指定的颜色值,只需一条简单的规则
[注意,此规则应与您的图标定义位于同一个文件中,因此,如果您使用的是外部文件,但使用 AJAX 将图形插入到您的主文件中(当外部引用不受支持时),您需要将此规则添加到您的外部文件和您的主样式表中。]
*
选择器在 CSS 选择器特异性方面可能处于最底层,但它仍然会覆盖表示属性 - Illustrator 和 Inkscape 都使用表示属性来表示颜色信息。现在您可以做以下事情
每个图标中的图形将继承样式。
当然,这只适用于简单的单色图标。如果您想要更细致的控制,您需要进入代码并了解 SVG 样式级联规则。
Amelia,感谢您分享这个。这是一种有趣的方法,我肯定会对它进行实验,以更好地了解它在实践中的工作方式。
我同意使用
*
并不理想,SVG 定义中的额外表示数据也不理想(如果它与预期目标背道而驰,那么我认为它是额外的负担,也许根本不应该导出)。所以我的直觉是,直接导出不带表示属性的 SVG 仍然是最佳选择。我很想听听您是否同意这个观点?绝对同意。但有时,覆盖比深入挖掘和更改代码更容易。或者,在某些情况下,您可能希望能够在图标定义中定义默认颜色,但仍然可以选择根据用例更改它们。(没有意图的双关语……)
嗨 Amelia,这对笔划(颜色)绝对有效吗?我已经用填充完成了,但笔划不行。
不用了;我已经找到了问题所在。我使用的是
[role=img]
作为选择器来设置继承。虽然这适用于填充,但不适用于笔划。这似乎很奇怪。非常感谢您的提示。
哦,对不起,在这里发了三遍。
我不知道我正在设置填充的符号在 SVG 中没有设置填充。因此,
[role=img]
(和svg
)在我的情况下不会覆盖 SVG 的表示属性。(符号和使用/xlink 以及外部 CSS 文件。)对于第 3 点,我认为
<use>
元素可以使用::shadow
或/deep/
选择器来定位影子 DOM,但 浏览器一致性 参差不齐。Ian,是啊,浏览器之间的差异,真是令人头疼;不过,这仍然是一个很有用的提示(尤其是用于调试)。您愿意在这里分享一个笔或更明确的示例 markdown 注释吗?
嗨 Rob,
我提到的选择器是今年 4 月发布的草案的一部分,由于它太新了,所以支持得不是很好 - 但是 Blink 尽管存在一个阻止 CSS 正确计算的错误,但仍然匹配了这些规则。您可以在此处看到一个笔
http://codepen.io/TigerC10/pen/LEYGoo
Ian,感谢您提供指向笔的链接。非常酷的东西,尤其是在调试方面。仅仅打开那些 Chrome 标志就很有帮助,因为您获得了对“主机”的整个 #shadow-root 可见性,这非常方便。
您在浏览器中使用什么开发者工具?是 Safari 内置的工具吗?以前从未见过。
是啊,我通常使用 Chrome 的开发者工具,但我有很多难看的插件等等。所以我只是使用 Safari 来使截图更干净一点。
您错过了一种方法,我发现它非常有效:将外部 SVG 内联注入到您的 HTML 中。
在页面加载后,我使用 jQuery AJAX 将 SVG 内容直接注入到我的 HTML 中。这样一来,浏览器会缓存可缓存的 SVG 文件,但仍然可以对 SVG 元素的 CSS 进行精细控制,并且允许您使用 xlink href 引用 SVG 元素。
我使用这种方法,它运行良好。非常简单且有效。
使用外部 SVG 最大的缺点是,您无法精细控制各个 SVG 元素的 CSS 颜色。
感谢您的分享,Jake!当您提到:“会产生一个可缓存的 SVG 文件”时 - 您指的是浏览器会缓存执行注入的 JavaScript 文件吗?
您是否在注入前使用 JavaScript 更改颜色,并通过内联方式添加 CSS?您是否直接对 SVG defs 进行样式化?这很酷,但同样地,我尽量避免“全局”样式化,如果可能,我更倾向于对克隆的实例进行样式化。
我感兴趣的是,这是否允许您跨域托管 JS 文件,但仍然注入 SVG。在我的测试中,外部 SVG 文件需要与同一个域上。因此,这种技术可能会有所帮助。如果您已经有了可以分享的笔或测试,我想看一下。
@Rob
你能详细解释一下这个错误吗?我无法复制它。
如果这是一个问题,我认为使用 CSS 将样式设置为表示属性的值没有任何问题,但我从未遇到过 currentColor 的问题。
http://codepen.io/anon/pen/yyLNXx
以上在 Win7 上的 IE11 和 IE10 兼容模式下按预期工作(无法在 CodePen 中测试 IE9 模式)。我从您对图形的样式化方式中遗漏了什么?
Amelia,我认为存在一个混淆,即这个问题专门针对使用内联 SVG,但使用外部文件和 svg4everybody polyfill(尽管我不确定 pollyfill 是否需要重现这种情况……只是我的设置方式)。我在上班,所以我将在有更多时间的时候再回到这个问题。我可以说(如果您想复制问题),最好尝试使用类似于最后一个示例的类似内容进行测试,并使用
git clone
指令。我利用了已经存在的 Buttons 展示来整理示例,因此,不幸的是,它不是一个简单的“精简”设置,但您应该能够根据我在本文末尾提供的信息将其组合在一起。如果/当我有一些时间时,我可能会自己这样做,并将其发布在 github 上。讨论这个话题确实很有挑战性,因为直接为 SVG 进行样式化、使用外部文件、后期处理等之间存在差异。也许我需要更多视觉效果才能将这些差异传达出来。
Amelia,我重新测试了我的演示代码和更简单的测试用例,看起来我犯了一个错误。我的感觉是,在我看到错误的否定结果时,我的 CSS 有问题。无论如何,我已经测试了更新的版本,没有使用提到的 IE 技巧,在 IE9-11 中,并确认了最新的 FF/Safari/Chrome,它工作正常。所以我已经更新了“Gotcha Three: Achieving Color Variation”部分,并将其发送出去,希望这篇文章能在今天晚些时候更新。感谢你指出这一点。
感谢您查看。我很高兴知道我不必再记住一个 SVG 错误了!
我在公司客户列表中使用了一种稍微不同的技术,其中包含两个颜色的徽标,这些徽标的颜色可以根据网站当前的“混合”动态更改。
我使用 WordPress 将 SVG 徽标动态组合为
symbol
,并将根svg
标签的类设置为.client-logos
(在此处查看源代码)。然后,这些徽标将通过use
包含在页面上,位于具有.client__logo
类的span
内。单独的
path
没有fill
属性,但有class="light"
或class="dark"
。然后通过定位.client-logos
(svg
元素的类,用于 Firefox 和 IE)和.client__logo
(包含元素的类,用于 Chrome/Webkit)在 CSS 中设置填充,如下所示:这种方法在 IE9+ 中完美运行(使用 svg4Everybody 进行
use
支持)。甚至可以使用悬停状态等动态更改颜色。理论上,您可以使用 SVG 中的类添加任意数量的颜色。嘿 Shaw,感谢您分享。我认为这与我提到的直接定位 SVG 类似。我想知道的一件事是,您动态生成的 WP 文件是否被缓存。另一件事(许多用例不需要)是,您是否需要有两个实例指向同一个 def,但需要不同的强调色。我相信您的策略更接近于全局方法(这很好,但需要考虑)。
对于 svg4everybody 或其他 shim 之类的工具,可能更方便的做法是将 SVG 定义直接放在正文中,用于 IE 等情况。嵌入每个定义可能并不比将定义推送到页面上更好;然后我们仍然可以定位
use
,而不会出现任何麻烦。我想这有点偏离了您的评论,但我想到了这一点,因为您提到了 svg4everybody。感谢您的回复。通过 CSS 更改颜色是由于“混合”功能,该功能会更改整个网站的皮肤。用户会收到一个新的 CSS 文件,但不会收到页面的新内容,这意味着
use
引用将保持不变。能够通过 CSS 控制这些 SVG 徽标的样式是迄今为止最简单的方法,因此我不必为未知数量的混合创建 SVG 文件本身的变体,或者尝试使用 Javascript 交换图标引用。关于动态 SVG 的缓存,在 Chrome 的网络工具中,响应头有
Cache-Control:max-age=2592000
,我已在 .htaccess 中为所有图像设置了此值。但是,其他图像和 CSS/JS 都显示304 Not Modified
状态,而此 SVG 显示200 OK
。您知道可能发生了什么吗?关于为什么它没有被缓存,是的,这就是我提到的“我想知道的是您动态生成的 WP 文件是否被缓存”的原因,因为(不详细查看您的实现)它看起来就像您将 SVG 定义“作为内容”放进去一样;您只是动态地执行此操作(这很酷,可能是您要实现的效果的要求)。我想我会对此采取务实的态度。总的尺寸增加了多少?您是否试图支持在早晨火车上观看手机的用户,或者,它更像是“炫耀”网站?再说一次,我不确定您的实现需要多动态,而且我只使用它来设置相当静态的图标集,但我可以想象以下内容:
假设您有三种“主题”,用户可以选择红色、绿色、蓝色(为了简单起见)。
您的动态代码会确定他们在过去选择了什么(我不知道如何,可能是 cookie 或数据库检索等)。
您会调入相应的外部 SVG def 文件,该文件会特别针对该用户进行缓存,如果他们在后续访问中保持该主题。
如果您发现这完全与您要实现的目标不符,我深表歉意,我只是在进行头脑风暴,因为动态外部可缓存文件的通用用例似乎是一个有趣的解决问题。
如果您找到了解决方案,请务必在 gist、笔等中发布链接。感谢 Shaw!
在重新阅读我的回复和您的初始帖子后,我想提一下,我建议的主要区别在于,虽然您的文件是动态生成的,但我正在思考是否让“预先配置的静态文件”有所不同,动态部分只是在它们之间进行选择。它可能完全不支持您的用例,我不知道,但我的想法是,这些文件作为静态文件可以被缓存。
我可能已经通过在 WordPress 中设置一个重定向来解决动态缓存问题,该重定向将
clients.svg
指向动态 SVG 页面。通过使用实际的 .svg 扩展名,Chrome 似乎能够正确地对其进行缓存,并获得正确的304 Not Modified
响应。这绝对是一个“炫耀”网站,因为我们是一家创意机构,但我尝试在移动设备上尽可能减轻体验(尽管总体上仍然很重),尽可能减少图像和文件数量。
我认为对于这种用例,在 CSS 中设置颜色是最合理的。用户在单击“混合”按钮时会获得随机主题,但网站本身的内容不会改变,因此页面上的 SVG 引用保持不变(
<use xlink:href="logo-att">
)。由于他们已经获得了包含大部分新主题外观的新 CSS 文件,因此只需在其中设置颜色即可,无需生成另一个 SVG 文件。这使维护和添加新主题变得更加容易。
动态 SVG 不一定是一个必要条件,但我希望在将来更容易添加新徽标,现在可以在 WordPress 中完成,而不必使用笨拙的 grunt 过程来连接 SVG 文件,或尝试手动维护 SVG 文件。
感谢您的来回交流,它帮助我更深入地了解了这种方法。如果我能稍微改进一下这种动态 SVG 方法,它可以成为一个有用的 WordPress 插件来生成 SVG 图标。
我发现内联 svg 和 Angular 有几个问题。
Angular 视图默认情况下不理解 xlink:href。您必须创建一个新的模块才能使其理解。 这是一个可解决的问题。
当您将内联 svg 放入 ng-repeat 中以显示图标列表时,图标在页面加载时不会渲染。图标会在某些事件发生后出现(我不记得具体是什么事件)。我找不到解决方案。如果有时间,我会创建一个笔来演示这一点。
感谢您的文章。
Mouly,我曾经花了两周时间研究 Angular,但并没有深入研究,所以我不太可能是引导你走上正轨的人,抱歉(也许其他 css-trick 阅读者会)。如果您有时间,请创建这个笔并发布回来。感谢 Mouly!
在开发 Rushmore 网站并使用 React.js 时,我发现了一些有趣的东西,让生活变得更简单。
如果你打算使用 React,并使用 JavaScript 来渲染所有内容(使用 Node.js 在服务器端渲染是可能的),那么 use 元素实际上并没有帮助。在这种情况下,最好的方法始终是注入内联 SVG。
一个很大的好处是,它使编写针对 SVG 及其各个部分的 CSS 变得更加容易。使用 use 标签,定位 SVG 的小部分变得非常不可靠。
其次,如果你使用 browserify 或 webpack 之类的工具,你可以将整个 SVG 文件作为字符串内联到你的 js 包中,从而进一步减少 HTTP 请求,同时还可以缓存。当然,如果你愿意,仍然可以依赖 AJAX 调用。
Sam Ellis 写了一篇关于 SVG 的有趣文章