介绍一些你可能没用过的SVG小技巧。
在平时开发中,很多时候都会用到SVG。大部分情况我们都不必关注SVG里面到底是什么,直接当成图片资源引入就行,比如常见的图标资源。
我们可以通过多种方式使用这个特殊的图片。
<img%20src="a.svg">
.icon{%20%20background:%20url("a.svg")}
甚至直接放到HTML中。
<div>%20%20<svg>%20%20 ...%20%20</svg></div>
这些都没什么问题,但有时候,我们需要的是可以自适应尺寸的,比如像这样的渐变边框,尺寸会随着文本内容的变化而变化,而不是固定尺寸,如下:
或者是这样的虚线渐变边框。
这样的该如何用 SVG 动态实现呢,一起看看吧。
SVG通常不是手写的(能手写任意路径的都是大神),几乎都是设计师借助软件绘制生成的,比如设计都很喜欢的Figma(对前端非常友好,可以尝试一下)。
比如前面提到的渐变边框,在Figma中就是这样。
对于设计师来说,渐变边框很容易,只需要选择边框类型就行了。
对于 CSS 来说,这还算一个比较麻烦的事,通常我们需要额外嵌套一层渐变背景,通过遮盖或者mask裁切的方式实现,有兴趣的可以尝试一下,这里暂不展开。
那么,这个设计可以直接通过导出SVG实现吗?
先试试,Figma中可以直接将这个边框复制成SVG格式。
下面是这段复制出来的SVG代码(大概还是能看得懂一些的...)。
<svg%20width="41"%20height="25"%20viewBox="0%200%2041%2025"%20fill="none"%20xmlns="http://www.w3.org/2000/svg">%20%20<rect%20x="1"%20y="1"%20width="39"%20height="23"%20rx="4"%20stroke="url(#paint0_linear_1_2)"%20stroke-linecap="round"/>%20%20<defs>%20%20<linearGradient%20id="paint0_linear_1_2"%20x1="0"%20y1="0"%20x2="1"%20y2="0">%20%20 <stop%20stop-color="#FFD75A"/>%20%20 <stop%20offset="1"%20stop-color="#ED424B"/>%20%20</linearGradient>%20%20</defs></svg>
我们尝试让这段SVG尺寸跟随button的大小,就行这样。
<style>%20%20svg{%20%20%20%20position:%20absolute;%20%20%20%20inset:%200;%20%20}</style><button>%20%20CSS%20%20<svg>...</svg></button>
在内容不定的情况下,就变成了这样。
很显然不行,因为生成的SVG宽高是固定的,没法跟随文本内容自适应尺寸。
既然 SVG很擅长渐变边框,而 CSS很擅长自适应,那么,有没有取长补短的办法呢?
当然也是有的!不过需要“改造”一下,接着往下看。
首先我们把上面的那段SVG拿过来。
<svg%20width="41"%20height="25"%20viewBox="0%200%2041%2025"%20fill="none"%20xmlns="http://www.w3.org/2000/svg">%20%20<rect%20x="1"%20y="1"%20width="39"%20height="23"%20rx="4"%20stroke="url(#paint0_linear_1_2)"%20stroke-linecap="round"/>%20%20<defs>%20%20<linearGradient%20id="paint0_linear_1_2"%20x1="0"%20y1="0"%20x2="1"%20y2="0">%20%20 <stop%20stop-color="#FFD75A"/>%20%20 <stop%20offset="1"%20stop-color="#ED424B"/>%20%20</linearGradient>%20%20</defs></svg>
有没有发现这里很多数值都固定的?如果想实现自适应,我们就需要将这些值改成百分比形式,注意看这个rect,有个x、y坐标,我们现在宽高都是100%了,所以这里的坐标也要改成0,不然就撑出去了。
<svg%20width="100%"%20height="100%"%20viewBox="0%200%20100%%20100%"%20fill="none"%20xmlns="http://www.w3.org/2000/svg">%20%20<rect%20x="0"%20y="0"%20width="100%"%20height="100%"%20rx="4"%20stroke="url(#paint0_linear_1_2)"%20stroke-linecap="round"/>%20%20<defs>%20%20<linearGradient%20id="paint0_linear_1_2"%20x1="0"%20y1="0"%20x2="1"%20y2="0">%20%20 <stop%20stop-color="#FFD75A"/>%20%20 <stop%20offset="1"%20stop-color="#ED424B"/>%20%20</linearGradient>%20%20</defs></svg>
为了验证这个 SVG的自适应,我们将这个SVG放在一个div中。
<div%20style="width:%20100px;height:%2080px;">%20%20<svg>...</svg></div><div%20style="width:%20200px;height:%20180px;">%20%20<svg>...</svg></div>
效果如下:
是不是已经自适应了?
不过还是有点问题,仔细观察,圆角处有些不自然,感觉被裁剪了一样。
造成这种现象的原因有两个:
我们把边框改大一点就可以很明显的观察到描边是居中的。
由于是居中的,所以在不做修改的情况下,我们看到的其实只有原边框的一半,利用这个原理我们其实可以实现常说的0.5px边框。
在这里,我再介绍一种新的方式,那就是利用 CSS%20calc !
没错,在 SVG中也可以使用CSS函数,比如我们这里边框是4px,那么坐标x、y就应该是2,然后宽高应该是calc(100%%20-%204px),所以可以很自然的改成这样。
<div%20style="width:%20100px;height:%2080px;">%20%20<svg%20width="100%"%20height="100%">%20%20%20%20<rect%20x="2"%20y="2"%20width="100%"%20height="100%"%20style="width:%20calc(100%%20-%204px);height:%20calc(100%%20-%204px);"%20%20rx="4"%20stroke="url(#paint0_linear_1_2)"%20stroke-width="4"%20stroke-linecap="round"/>%20%20%20%20%20<defs>%20%20%20%20<linearGradient%20id="paint0_linear_1_2"%20x1="0"%20y1="0"%20x2="1"%20y2="0">%20%20%20%20%20%20<stop%20stop-color="#FFD75A"/>%20%20%20%20%20%20<stop%20offset="1"%20stop-color="#ED424B"/>%20%20%20%20</linearGradient>%20%20%20%20</defs>%20%20</svg></div>
非常完美了,不会有任何裁剪!(大家也可以复制上面这段代码放在%20HTML%20中验证)。
这样就“轻易”实现了SVG的尺寸自适应。
这里小结一下
除此之外,还能直接加上style样式,就像这样。
<svg%20width="100%"%20height="100%"%20viewBox="0%200%20100%%20100%"%20fill="none"%20xmlns="http://www.w3.org/2000/svg">%20%20<style>%20%20%20%20rect{%20%20%20%20%20%20width:%20calc(100%%20-%204px);%20%20%20%20%20%20height:%20calc(100%%20-%204px);%20%20%20%20}%20%20</style>%20%20<rect%20x="2"%20y="2"%20width="100%"%20height="100%"%20rx="4"%20stroke="url(#paint0_linear_1_2)"%20stroke-width="4"%20stroke-linecap="round"/>%20%20<defs>%20%20%20%20<linearGradient%20id="paint0_linear_1_2"%20x1="0"%20y1="0"%20x2="1"%20y2="0">%20%20%20%20%20%20<stop%20stop-color="#FFD75A"/>%20%20%20%20%20%20<stop%20offset="1"%20stop-color="#ED424B"/>%20%20%20%20</linearGradient>%20%20</defs></svg>
虽然看着多,但后面作用更大,可以添加更多的 CSS 样式。
其实前面的这段 SVG 可以直接放到 HTML 中用了,比如:
<button>%20%20<svg%20width="100%"%20height="100%"%20fill="none"%20xmlns="http://www.w3.org/2000/svg">%20%20%20%20<rect%20x="2"%20y="2"%20width="100%"%20height="100%"%20style="width:%20calc(100%%20-%204px);height:%20calc(100%%20-%204px);"%20rx="16"%20stroke-width="2"%20stroke="url(#paint0_linear_3269_5233)"/>%20%20%20%20<defs>%20%20%20%20%20%20<linearGradient%20id="paint0_linear_3269_5233"%20x1="0"%20y1="0"%20x2="100%"%20y2="100%"%20gradientUnits="userSpaceOnUse">%20%20%20%20%20%20%20%20<stop%20stop-color="#FFD75A"/>%20%20%20%20%20%20%20%20<stop%20offset="1"%20stop-color="#ED424B"/>%20%20%20%20%20%20</linearGradient>%20%20%20%20</defs>%20%20</svg>%20%20CSS</button>
我们需要将这个 SVG撑满整个button,所以可以直接绝对定位。
button{%20%20position:%20relative;}button>svg{%20%20position:%20absolute;%20%20inset:%200;}
这样就得到了一个自适应尺寸的、带有渐变边框的按钮,效果如下:
你也可以访问在线链接:buton%20with%20SVG%20(juejin.cn)[1]
不知道你有没有这样的感觉,把一大段 SVG放在 HTML不是特别优雅,总觉得太臃肿了。
如果你有这种感觉,不妨将这段 SVG转换成内联CSS代码。
在这里可以借助张鑫旭老师的这个工具:SVG在线压缩合并工具[2]
我们将这段SVG粘贴过去,可以得到这样的一段内联SVG。
data:image/svg+xml,%3Csvg%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3E%3Crect%20x='1'%20y='1'%20width='100%25'%20height='100%25'%20style='width:calc(100%25%20-%202px);height:calc(100%25%20-%202px)'%20rx='16'%20stroke-width='2'%20stroke='url(%23paint0_linear_3269_5233)'/%3E%3Cdefs%3E%3ClinearGradient%20id='paint0_linear_3269_5233'%20y2='100%25'%20gradientUnits='userSpaceOnUse'%3E%3Cstop%20stop-color='%23FFD75A'/%3E%3Cstop%20offset='1'%20stop-color='%23ED424B'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E
有了这段内联SVG,我们可以直接用在background背景上。
button{%20%20background:%20url("data:image/svg+xml,%3Csvg%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3E%3Crect%20x='1'%20y='1'%20width='100%25'%20height='100%25'%20style='width:calc(100%25%20-%202px);height:calc(100%25%20-%202px)'%20rx='16'%20stroke-width='2'%20stroke='url(%23paint0_linear_3269_5233)'/%3E%3Cdefs%3E%3ClinearGradient%20id='paint0_linear_3269_5233'%20y2='100%25'%20gradientUnits='userSpaceOnUse'%3E%3Cstop%20stop-color='%23FFD75A'/%3E%3Cstop%20offset='1'%20stop-color='%23ED424B'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E")}
而HTML只需要干净的button元素就够了。
<button>CSS</button><button>CSS%20&%20SVG</button>
神奇的是,即便是转为内联了,SVG仍然保持着自适应特性,这样也能实现同样的效果,是不是好多了?
你也可以访问在线链接:button%20with%20SVG%20background%20(juejin.cn)[3]
如果说上面的效果 CSS 还能勉强模拟一下,那如果是这样的虚线呢?
对于 SVG 就非常容易了,只需要设置stroke-dasharray属性就行,并且可以随意更改虚线的间隔。
<svg%20width="100%"%20height="100%"%20fill="none"%20xmlns="http://www.w3.org/2000/svg">%20%20<rect%20x="2"%20y="2"%20width="100%"%20height="100%"%20style="width:%20calc(100%%20-%204px);height:%20calc(100%%20-%204px);"%20rx="16"%20stroke-width="2"%20stroke="url(#paint0_linear_3269_5233)"%20%20stroke-dasharray="8%204"/>%20%20<defs>%20%20%20%20<linearGradient%20id="paint0_linear_3269_5233"%20x1="0"%20y1="0"%20x2="100%"%20y2="100%"%20gradientUnits="userSpaceOnUse">%20%20%20%20%20%20<stop%20stop-color="#FFD75A"/>%20%20%20%20%20%20<stop%20offset="1"%20stop-color="#ED424B"/>%20%20%20%20</linearGradient>%20%20</defs></svg>
还有这种虚线边缘是圆角的情况,CSS就更加无能为力了。
SVG只需要设置stroke-linecap就行。
<svg%20width="100%"%20height="100%"%20fill="none"%20xmlns="http://www.w3.org/2000/svg">%20%20<rect%20x="2"%20y="2"%20width="100%"%20height="100%"%20style="width:%20calc(100%%20-%204px);height:%20calc(100%%20-%204px);"%20stroke-width="2"%20rx="16"%20stroke-linecap="round"%20%20stroke="url(#paint0_linear_3269_5233)"%20%20stroke-dasharray="8%206"/>%20%20<defs>%20%20%20%20<linearGradient%20id="paint0_linear_3269_5233"%20x1="0"%20y1="0"%20x2="100%"%20y2="100%"%20gradientUnits="userSpaceOnUse">%20%20%20%20%20%20<stop%20stop-color="#FFD75A"/>%20%20%20%20%20%20<stop%20offset="1"%20stop-color="#ED424B"/>%20%20%20%20</linearGradient>%20%20</defs></svg>
更进一步,SVG还能实现虚线滚动动画,CSS 应该是实现不了了。
看似复杂,其实只需要改变stroke-dashoffset属性就行了,我们可以直接在SVG中插入CSS动画。
<svg width="100%" height="100%" fill="none" xmlns="http://www.w3.org/2000/svg"> <style> .rect{ width: calc(100% - 4px); height: calc(100% - 4px); animation: move .3s infinite linear; } @keyframes move { 0% { stroke-dashoffset: 0; } 100% { stroke-dashoffset: 14; } } </style> <rect class="rect" x="2" y="2" width="100%" height="100%" stroke-width="2" rx="16" stroke-linecap="round" stroke="url(#paint0_linear_3269_5233)" stroke-dasharray="8 6"/> <defs> <linearGradient id="paint0_linear_3269_5233" x1="0" y1="0" x2="100%" y2="100%" gradientUnits="userSpaceOnUse"> <stop stop-color="#FFD75A"/> <stop offset="1" stop-color="#ED424B"/> </linearGradient> </defs></svg>
所有情况都可以将 SVG转为内联CSS直接用在背景上,极大的保证了HTML的简洁性。
你也可以访问在线链接:dot border with animation (juejin.cn)[4]
以上就是本文的全部内容了,主要介绍了如何利用 SVG和CSS各种的优势来实现更加灵活的布局,下面总结一下:
你可能已经发现SVG并不是非常孤立的一门语言,现在还能和 CSS、HTML联动起来,充分发挥各自的优势,这样才能事半功倍 。
[1]buton with SVG (juejin.cn): https://code.juejin.cn/pen/7341373491785236532。
[2]SVG在线压缩合并工具: https://www.zhangxinxu.com/sp/svgo/。
[3]button with SVG background (juejin.cn): https://code.juejin.cn/pen/7341378448348643379。
[4]dot border with animation (juejin.cn): https://code.juejin.cn/pen/7341382517888876582。
本文链接:http://www.28at.com/showinfo-26-82040-0.html不一样的SVG!SVG在 CSS 中的应用
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: Java中的String,这一篇就够了