SVG 的一个优秀特性是,您可以定义一个形状(或一组形状)一次,然后在整个页面中多次使用它。您甚至可以对不同版本应用不同的填充和滤镜等。如果可以的话,可以将其视为 SVG 模板。
让我们看看是否可以通过创建一些选项卡来充分利用它。
我从 Oleg Solomka 的 Codrops 文章 中了解到这是可能的。很聪明!
它的工作原理如下
- 定义形状(可以是圆形、矩形、多边形或 任何形状,或用
<g>
包裹的一组形状)。 - 给该形状一个 ID。
- 隐藏该形状。
- 在需要的地方使用
<use>
使用该形状。
在 HTML 中看起来像这样
<!-- TEMPLATE -->
<svg width="100px" height="100px" viewBox="0 0 100 100" class="visually-hidden">
<circle id="template" cx="50" cy="50" r="50">
</svg>
<!-- USE TEMPLATE SEVERAL TIMES -->
<svg viewBox="0 0 100 100" class="circle circle-1">
<use xlink:href="#template">
</svg>
<svg viewBox="0 0 100 100" class="circle circle-2">
<use xlink:href="#template">
</svg>
<svg viewBox="0 0 100 100" class="circle circle-3">
<use xlink:href="#template">
</svg>
然后,您可以分别引用这些模板的不同用法,并对它们执行任何您喜欢的操作。例如,使用 SVG 渐变填充或 SVG 滤镜等。

display: none;
来隐藏它。我可能会避免尝试直接使用它,以保持良好的关注点分离。演示
查看 Chris Coyier 在 CodePen 上的笔 基本 SVG 模板 (@chriscoyier)。
创建选项卡
我刚刚从律师那里收到了一些文件,当然,它们都使用了经典的文件文件夹设计进行了选项卡式布局。

以前曾尝试过使用 CSS 来创建这种形状。 圆角选项卡 处理了形状逐渐变细到文件夹其余部分的形状。 倾斜选项卡 处理了倾斜的侧面。但它们都不是完美的,组合它们将很困难或不可能,并且虽然很巧妙,但它们在使用生成内容等方面有点“hacky”。
难道仅仅将该形状绘制为矢量并使用它不是更容易吗?绝对地,这是 SVG 的完美领域。更好的是,我们可以只使用一个模板来定义它一次,然后反复使用它。这使我们能够更改颜色等,而无需请求新的资源,并且无论我们最终使用它的大小如何,它都能看起来很清晰。
您可以轻松地在任何矢量绘图工具中绘制该形状,并获取其 SVG 代码。如果您需要帮助, 这篇文章应该会有帮助。
我只是在一些图片网站上搜索了一些图片,只是为了好玩,并且 在 Shutterstock 上找到了一些 符合我的目标。我下载了它们并从中提取了形状。

简而言之,基本上是 这个
<svg>
<path id="tab-shape" d="M116.486,29.036c-23.582-8-14.821-29-42.018-29h-62.4C5.441,0.036,0,5.376,0,12.003v28.033h122v-11H116.486
z">
</svg>
HTML
由于我们可能会将选项卡称为导航,并且 导航是列表,因此我们将得到以下内容
<nav role="navigation" class="main-navigation">
<ul>
<li class="tab-1 active">
<a href="#home">
<span>Home</span>
<svg viewBox="0 0 122 40">
<use xlink:href="#tab-shape"></use>
</svg>
</a>
</li>
<li class="tab-2">
<a href="#about">
<span>About</span>
<svg viewBox="0 0 122 40">
<use xlink:href="#tab-shape"></use>
</svg>
</a>
</li>
<!-- etc. as many tabs as you'd like -->
</ul>
</nav>
我们需要在标记中使用 <svg>
,因为这就是它的工作原理。我们将其包装在 <a>
中,因为我们希望选项卡成为可点击/可触摸的链接。我们需要 <span>
,因为我们打算将 <svg>
和文本正好彼此叠加,文本在顶部。
CSS
我们可以使用其中一个包装元素作为定位上下文。我们将绝对定位 <span>
和 <svg>
,并为 <span>
提供更高的 z-index
。
这里以 SCSS 呈现,因为嵌套使它更容易阅读
.main-navigation {
overflow: hidden;
position: relative;
padding: 0 0 0 1rem; /* push tabs back to right */
ul {
list-style: none;
padding: 0;
}
li {
float: left;
width: 12rem;
height: 5rem;
margin: 0 0 0 -1rem; /* pull to left to overlap tabs */
position: relative;
&.active {
z-index: 6; /* active one on top */
}
}
a {
position: relative;
display: inline-block;
width: 100%;
height: 100%;
}
svg {
width: 120%; /* tab shape should stick out past clickable box */
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 1;
pointer-events: none; /* SVG eats clicks weird */
}
span {
position: relative;
padding: 1rem 0 0 3.3rem; /* position the text */
z-index: 2;
display: inline-block;
width: 100%;
height: 100%;
}
}
现在要更改每个选项卡的外观,您可以按类名引用它们并更改 fill
。我们还需要以相反的 z-index
顺序排列它们,以便第一个选项卡位于顶部而不是最后一个,这很容易通过显式声明它们来完成。
.tab-1 {
z-index: 4;
svg {
fill: red;
}
}
.tab-2 {
z-index: 3;
svg {
fill: orange;
}
}
演示
查看 Chris Coyier 在 CodePen 上的笔 SVG 选项卡 (@chriscoyier)。
其中有一些 JavaScript 用于激活不同的选项卡,其本质只是更改类名。
您可能会注意到选项卡也有一些细微的渐变。这里有趣的联系是,您可以在与原始模板形状相同的 <svg>
中声明该 SVG 渐变,然后只需通过按 ID 引用滤镜即可填充模板形状。
<linearGradient id="tab-1-bg" x1="0%" y1="0%" x2="0%" y2="65%">
<stop offset="0%" style="stop-color: rgba(136, 195, 229, 1.0);" />
<stop offset="100%" style="stop-color: rgba(118, 160, 192, 1.0);" />
</linearGradient>
.tab-1 {
svg {
fill: url(#tab-1-bg);
}
}
因此,基本上您可以将您的滤镜也视为模板,随意重复使用它们。也请尝试一下 演示。其中有一些注释掉的关于阴影的部分,您可能喜欢。真正酷的事情是使它们灵活,以便选项卡大小根据可用空间(以及文本)变化得更大或更小,然后在空间非常小的时候完全放弃它们,并切换到移动导航解决方案。
嘿!感谢您认可我) 我可以提到 Iconmelon 是基于该技术的构建的吗?;)
非常棒的文章。这只是使用矢量编辑器(或浏览器,如果那是您的选择)设计网站的另一个原因。
很棒的文章…
“viewbox=”0 0 20 30” 属性是什么意思以及作用是什么…这些数字代表什么?它们等价于像素吗?
SVG 元素上的 viewbox 属性创建了图像的坐标系。它是可缩放矢量图形“可缩放”方面的关键:您不是根据像素、em 或任何绝对测量值来定义形状,而是通过任意的“用户坐标”来定义它们。请注意,在选项卡形状的 SVG 路径定义中,数字是无单位给出的;这些位于用户坐标中。
浏览器根据 viewbox 属性将用户坐标系缩放为绘制 SVG 的矩形。这四个数字分别是左上角的坐标以及图像的宽度和高度,以用户坐标表示。宽度和高度值会根据需要进行缩放,以匹配最终由 CSS 或 SVG 宽度和高度属性定义的图像宽度和高度。一个单独的属性 preserveAspectRatio 可以强制统一缩放(高度和宽度使用相同的缩放因子),以便图像不会失真。
viewbox 中的前两个数字可用于相对于绘制图像的框移动图像。这类似于使用位置值移动 img 元素或背景图像。如果您发现更容易使用左下角作为坐标系的原点,您甚至可以执行类似于 viewbox=”0 100 100 -100” 的操作:负高度值翻转默认方向,而前两个数字将左上角定义为 (0,100)。
如果您不使用 viewbox,则 SVG 内的所有尺寸都将解释为相对于左上角测量的像素,并且不会发生缩放。
这是完整的规范
http://www.w3.org/TR/SVG11/coords.html#ViewBoxAttribute
感谢 Amelia BR 对 viewbox 属性的精彩解释…
更正
在发布答案之前,实际阅读链接的来源是一个好主意。抱歉。我将 D3.js 缩放与基本的 SVG viewbox 语法混淆了。
不,您不能使用负高度值来翻转用户坐标方向。规范中明确将其描述为错误。如果要翻转坐标的方向,则必须使用 scale(1,-1) 的变换。(所有变换都会更改用户坐标映射到渲染绘图的空间的方式。)
http://www.w3.org/TR/SVG11/coords.html#TransformAttribute
一张图片胜过千言万语
http://codepen.io/AmeliaBR/full/lvkyD
还有
<lineargradient>
标签,它必须是<svg>
标签的子元素吗?或者它可以是一个独立的标签?某些浏览器可能会正确渲染它,但
<linearGradient>
标签是一个 SVG 元素,因此应该作为 SVG 块的一部分。推荐的格式是将其也包装在<defs>
标签中,但这不会影响渲染,因为 SVG 渐变本身不会被渲染。再次感谢 Amelia BR……您抽出时间回答我的问题,我非常感谢……
正如你所说,它不仅可以很好地缩放,而且在 MacBook Pro、平板电脑等大型“视网膜/高清”设备上看起来也很棒。
很棒的文章,Chris!SVG 拥有许多很酷的功能,并且可以直接嵌入到 HTML 中,这确实展示了它的实用性和强大性。此外,它非常适合视网膜就绪图形。
很酷的技术。我不太喜欢那样在 HTML 中看到 SVG。这使得它不太语义化。
我正要这么说。我工作的网站都具有相同的 HTML,所以我无法使用依赖于非语义标记的此类技术。我爱 SVG,但它们必须在 CSS 中。
很棒的技术。非常有用。谢谢 Chris!
非常好。我想根据我自己的经验提一下,自己构建曲线路径(d=”…”)并且不让 AI 来做(如果路径不太复杂)是值得的。良好的曲线语法很容易计算,当然比通常的 Adobe 标记短得多。在大多数情况下,一个小数点(0.1)就足够了。
你可以避免使用 CSS 隐藏模板,方法是在
<def>
元素内定义它,这样它就不会被渲染,但你仍然可以使用<use>
来使用它,就像你在此技术中所做的那样。我在我的 Codrops 文章(关于创建纹理文本)中也做了同样的事情,例如,当我创建 SVG
pattern
或 SVGmask
然后在text
元素上使用它们时。同样很酷的是将你的 Illustrator 文件保存为 SVG 文件,然后当 SVG 框弹出时,你会看到 SVG 代码,就这么简单,你就可以超快地获得 SVG 代码。很棒的文章!!
哇,这真的很令人印象深刻,我听说过 Iconmelon,但还没有机会查看它。
看起来越来越多的 SVG 即将入侵我们的 HTML 文件。
再次感谢这个很棒的演示,我一定会将其中的一些内容用于未来的项目。
嗨!它真的很棒!但是关于拉直选项卡呢?如果我的选项卡必须灵活呢?
谢谢 Chris,这将非常有用……
很棒的文章。谢谢 Chris。
嗨,这是一个很棒的技术,但我无法更改克隆元素的路径填充。
我可以使用 CSS 针对原始 SVG 中的路径,但似乎无法使任何克隆的 SVG 与父级不同。
希望 这支笔 能显示问题。
有人有什么想法吗?
http://www.w3.org/TR/SVG11/struct.html#UseElement
“CSS 选择器仅适用于正式文档树,而不适用于生成的树;因此,这些选择器将不会产生匹配。”
分叉了演示 以尝试将 Douglas Bowman 的“滑动门”背后的概念与这种 SVG 模板技术结合起来。需要两个 SVG 形状:一个非常宽的用于左侧,另一个小的,仅用于右角。
非常有用!如果您使用 grunt,我编写了一个工具,可以扫描您的项目文件夹以查找 SVG,提取形状,删除标题和一些空格,将它们放入带有其文件名作为 ID 的单个组中,并将这些组合的组写入您选择的 HTML 文件的不可见 SVG 标签中。
https://github.com/serrynaimo/grunt-svgtemplater