SVG(
可缩放矢量图形)是一种用于描述二维矢量图形的XML
标记语言。响应式SVG
是指能够在不同屏幕尺寸和分辨率下适应并保持清晰度的SVG
图形。
在响应式设计中,SVG图形可以通过各种技术和属性来实现适应性,以确保在不同设备上都能提供最佳显示效果。
SVG可能是一个棘手的主题。如果你是一名开发者,你可能需要对设计感兴趣,以深入了解SVG。而如果你是一名设计师,除了从设计工具(如Figma
)导出文件,你还需要了解一些编码知识。这可能是为什么我们很少看到自定义响应式SVG
,尽管它们非常有用且多才多艺。在这篇文章中,我将向你介绍创建响应式SVG
的基础知识。
有一个有趣的设计元素,即一个小漩涡线将回复的头像与原始消息的头像连接起来。
这种设计是通过使用三个单独的SVG
来实现的,其中最长部分的长度是通过JavaScript
计算的,该JavaScript
在页面加载时触发,以及每次窗口调整大小时触发。虽然这是一种有效的方法,但它严重依赖于JavaScript
。相比之下,我想向你展示如何使用响应式SVG
而完全不需要JS
来实现类似的效果。
为了构建所需的图像,有三个基本的事物我们需要理解:viewBox
属性,preserveAspectRatio
属性以及SVG
符号。
ViewBox基础知识
1 | <svg viewBox="0 0 300 400" xmlns="http://www.w3.org/2000/svg"> |
在SVG
中,将viewBox
想象成设计工具中的画板。例如,当你看到 viewBox="0 0 300 400"
时,类似于说:“创建一个宽300个单位、高400个单位的画板”。
请记住,我们正在使用矢量图形,所以最好不要以像素为单位思考,因为这些图形可以按任意尺寸缩放。
SVG还具有像任何其他图像一样的width和height属性。但是,有一个关键的区别:默认情况下,SVG的行为就像应用了 object-fit: contain
一样。这意味着,如果由width
和height
设置的纵横比与viewBox
定义的纵横比不同,你的“画板”将始终保持完全可见,并保持其比例而不发生扭曲。
为了增加一些复杂性,实际上你可以选择不定义viewBox
。当发生这种情况时,SVG本身的实际宽度和高度成为我们的“画板”的尺寸。现在这可能听起来有点令人困惑,但别担心,我们稍后会更详细地探讨这个问题。
PreserveAspectRatio ↔ Object-fit
1 | <svg viewBox="0 0 300 400" preserveAspectRatio="xMaxYMin" xmlns="http://www.w3.org/2000/svg"> |
正如我之前提到的,SVG
在行为上自然地就像它们有object-fit: contain
一样。还有一个属性的作用类似于object-position
,那就是preserveAspectRatio
属性。
默认情况下,它被设置为preserveAspectRatio="xMidYMid"
,这会将画板居中。但是你可以更改此设置以模仿其他object-fit行为。例如,要复制object-fit: right top
,你将使用preserveAspectRatio="xMaxYMin"
。请记住,由于“contain”
行为,只有其中一个定位规则会被应用。
SVG符号
当我们将SVG中的viewBox看作是画板时,SVG
符号与设计工具(如Figma
)中的组件非常相似。基本上,符号就像是一个小画板,它本身可以在另一个SVG中被插入(多次)。每个符号都有自己的viewBox
和preserveAspectRatio
属性,定义了这个小画板的空间和边界。
要使用SVG
符号,首先使用<symbol>
元素定义它,并为其提供一个唯一的id。该符号充当模板。然后,您可以在SVG
的任何位置使用<use>
元素放置此模板,该元素引用符号的id
。
1 | <svg viewBox="0 0 300 400" xmlns="http://www.w3.org/2000/svg"> |
构建响应式SVG
在我们组合最终的SVG之前,让我们从涡旋元素开始,稍后我们将将其用作符号。
我首先创建了一个宽度为21、高度为25的画板,在上面绘制了一条螺旋线。我将路径宽度设置为2,并选择了圆形的起始点和结束点,以获得平滑的外观。为了确保对称性,我将曲线的起始点和结束点定位在它们的x坐标都为16的位置。
根据您使用的图形工具,导出设计后获得的SVG
代码可能会有所不同。以下是我从Figma
导出涡旋设计时的代码示例:
1
2
3
4
5
6
7
8
9
10<svg width="21" height="25" viewBox="0 0 21 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_34_935)">
<path d="M16 21.5C16 19.25 16 18.6 16 15C16 7 11.75 3 7.5 3C3.2503 3 2 6.5 2 8C2 9.5 3.2503 13 7.5 13C10.5 13 16 12 16 2V0" stroke="#FF0099" stroke-width="2" stroke-linecap="round"/>
</g>
<defs>
<clipPath id="clip0_34_935">
<rect width="21" height="25" fill="white"/>
</clipPath>
</defs>
</svg>
其中包含了很多不必要的内容。最终,我们只需要定义涡旋的路径。
Figma
经常包含一个clipPath,在我们的小演示中是不需要的。手动移除了除了path
标签之外的所有内容。
1 | <svg width="21" height="25" viewBox="0 0 21 25" fill="none" xmlns="http://www.w3.org/2000/svg"> |
1 | <svg width="21" height="25" viewBox="0 0 21 25" fill="none" xmlns="http://www.w3.org/2000/svg"> |
准备好我们的涡旋图像后,我们就可以构建实际的SVG
了。让我们将宽度设置为21(与涡旋相同的宽度),并初步将SVG
的高度设置为80。正如我们之前讨论的,我们将省略viewBox
属性。
在我们的SVG
中,我们将在
主要的更改涉及将<svg>
标签替换为<symbol>
标签,并删除xmlns
属性,因为对于符号而言这是不必要的。我们确实需要一个id
,以便在use
标签中引用它。
将其移到<defs>
作为<symbol>
将防止路径在内容中可见。
1 | <svg width="21" height="80" fill="none" xmlns="http://www.w3.org/2000/svg"> |
为了使涡旋路径可见,我们必须插入一个
此外,通过通过<use>
中的引用将符号的高度设置为100%
,我们确保它始终与SVG
的高度匹配,可以灵活适应SVG
尺寸的任何变化。
1 | <svg width="21" height="80" fill="none" xmlns="http://www.w3.org/2000/svg"> |
现在我们有一个SVG
,其中的涡旋始终位于底部,而不管通过CSS
进行的任何高度更改。
接下来,让我们添加那根长竖线,为此,我们将插入一个从顶部延伸到底部的矩形。通过将矩形的高度设置为100%
,可以轻松实现这一点。
1 | <svg width="21" height="80" fill="none" xmlns="http://www.w3.org/2000/svg"> |
然而,实际上我们并不希望矩形的高度延伸到SVG
的整个100%
。理想情况下,它应该停在涡旋开始的地方。
在SVG
中,不能从底部定义坐标,但我们可以巧妙地使用CSS
来实现所需的效果。通过将矩形的高度设置为100% - 24px
,我们确保它仅达到涡旋的上方。这个调整可以直接在SVG
的代码中进行。
1 | <style> |
搞定了!我们成功地创建了一个响应式的SVG,它可以调整大小,同时始终保持漩涡循环位于底部,确保不会发生形变。
使用响应式SVG
现在,您可能想知道,我们实际上如何在代码中使用漩涡线呢?您有几种选择。
内联SVG
其中一种最简单的方法是将其用作内联SVG
。此方法允许您仅在文档开头定义一次该符号,而不是多次重复。此外,SVG
的样式定义可以包含在常规CSS
样式表中。最好使用特定类应用这些样式,以避免全局影响所有矩形元素。
使用图像标签
您还可以将代码保存为SVG
文件,然后使用图像标签。请注意,对于此方法,您必须从SVG
中删除宽度和高度属性,而是将它们应用于<img>
标签。
CSS中的SVG
也许最激动人心的选择是将SVG直接嵌入我们的CSS
中作为数据URI背景图像。
为此,我推荐使用@yoksel的一个很棒的工具,该工具允许您简单地复制并粘贴任何SVG,并为您的样式表生成一个准备就绪的代码片段。然后,例如,您可以使用伪元素并应用背景图像。
这个过程实质上是在SVG中嵌入CSS,然后将其嵌入到您的CSS文件中。