服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - 编程技术 - 不一样的SVG!SVG在 CSS 中的应用

不一样的SVG!SVG在 CSS 中的应用

2024-04-08 15:13前端侦探 编程技术

SVG通常不是手写的(能手写任意路径的都是大神),几乎都是设计师借助软件绘制生成的,比如设计都很喜欢的Figma(对前端非常友好,可以尝试一下)。

不一样的SVG!SVG在 CSS 中的应用

介绍一些你可能没用过的SVG小技巧。

在平时开发中,很多时候都会用到SVG。大部分情况我们都不必关注SVG里面到底是什么,直接当成图片资源引入就行,比如常见的图标资源。

不一样的SVG!SVG在 CSS 中的应用

我们可以通过多种方式使用这个特殊的图片。

<img src="https://www.51cto.com/article/a.svg">
.icon{
  background: url("a.svg")
}

甚至直接放到HTML中。

<div>
  <svg>
  	...
  </svg>
</div>

这些都没什么问题,但有时候,我们需要的是可以自适应尺寸的,比如像这样的渐变边框,尺寸会随着文本内容的变化而变化,而不是固定尺寸,如下:

不一样的SVG!SVG在 CSS 中的应用

或者是这样的虚线渐变边框。

不一样的SVG!SVG在 CSS 中的应用

这样的该如何用 SVG 动态实现呢,一起看看吧。

一、SVG导出的局限性

SVG通常不是手写的(能手写任意路径的都是大神),几乎都是设计师借助软件绘制生成的,比如设计都很喜欢的Figma(对前端非常友好,可以尝试一下)。

比如前面提到的渐变边框,在Figma中就是这样。

不一样的SVG!SVG在 CSS 中的应用

对于设计师来说,渐变边框很容易,只需要选择边框类型就行了。

不一样的SVG!SVG在 CSS 中的应用

对于 CSS 来说,这还算一个比较麻烦的事,通常我们需要额外嵌套一层渐变背景,通过遮盖或者mask裁切的方式实现,有兴趣的可以尝试一下,这里暂不展开。

那么,这个设计可以直接通过导出SVG实现吗?

先试试,Figma中可以直接将这个边框复制成SVG格式。

不一样的SVG!SVG在 CSS 中的应用

下面是这段复制出来的SVG代码(大概还是能看得懂一些的...)。

<svg     viewBox="0 0 41 25" fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect x="1" y="1"     rx="4" stroke="url(#paint0_linear_1_2)" stroke-linecap="round"/>
  <defs>
  <linearGradient   x1="0" y1="0" x2="1" y2="0">
  	<stop stop-color="#FFD75A"/>
  	<stop offset="1" stop-color="#ED424B"/>
  </linearGradient>
  </defs>
</svg>

我们尝试让这段SVG尺寸跟随button的大小,就行这样。

<style>
  svg{
    position: absolute;
    inset: 0;
  }
</style>
<button>
  CSS
  <svg>...</svg>
</button>

在内容不定的情况下,就变成了这样。

不一样的SVG!SVG在 CSS 中的应用

很显然不行,因为生成的SVG宽高是固定的,没法跟随文本内容自适应尺寸。

既然 SVG很擅长渐变边框,而 CSS很擅长自适应,那么,有没有取长补短的办法呢?

当然也是有的!不过需要“改造”一下,接着往下看。

二、SVG 自适应尺寸

首先我们把上面的那段SVG拿过来。

<svg     viewBox="0 0 41 25" fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect x="1" y="1"     rx="4" stroke="url(#paint0_linear_1_2)" stroke-linecap="round"/>
  <defs>
  <linearGradient   x1="0" y1="0" x2="1" y2="0">
  	<stop stop-color="#FFD75A"/>
  	<stop offset="1" stop-color="#ED424B"/>
  </linearGradient>
  </defs>
</svg>

有没有发现这里很多数值都固定的?如果想实现自适应,我们就需要将这些值改成百分比形式,注意看这个rect,有个x、y坐标,我们现在宽高都是100%了,所以这里的坐标也要改成0,不然就撑出去了。

<svg     viewBox="0 0 100% 100%" fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect x="0" y="0"     rx="4" stroke="url(#paint0_linear_1_2)" stroke-linecap="round"/>
  <defs>
  <linearGradient   x1="0" y1="0" x2="1" y2="0">
  	<stop stop-color="#FFD75A"/>
  	<stop offset="1" stop-color="#ED424B"/>
  </linearGradient>
  </defs>
</svg>

为了验证这个 SVG的自适应,我们将这个SVG放在一个div中。

<div style="width: 100px;height: 80px;">
  <svg>...</svg>
</div>

<div style="width: 200px;height: 180px;">
  <svg>...</svg>
</div>

效果如下:

不一样的SVG!SVG在 CSS 中的应用

是不是已经自适应了?

不过还是有点问题,仔细观察,圆角处有些不自然,感觉被裁剪了一样。

不一样的SVG!SVG在 CSS 中的应用

造成这种现象的原因有两个:

  • SVG描边是居中描边,并且不可修改。
  • SVG默认是超出隐藏的,也就是自带overflow:hidden。

我们把边框改大一点就可以很明显的观察到描边是居中的。

不一样的SVG!SVG在 CSS 中的应用

由于是居中的,所以在不做修改的情况下,我们看到的其实只有原边框的一半,利用这个原理我们其实可以实现常说的0.5px边框。

在这里,我再介绍一种新的方式,那就是利用 CSS calc !

没错,在 SVG中也可以使用CSS函数,比如我们这里边框是4px,那么坐标x、y就应该是2,然后宽高应该是calc(100% - 4px),所以可以很自然的改成这样。

<div style="width: 100px;height: 80px;">
  <svg   height="100%">
    <rect x="2" y="2"        rx="4" stroke="url(#paint0_linear_1_2)" stroke-  stroke-linecap="round"/>
     <defs>
    <linearGradient   x1="0" y1="0" x2="1" y2="0">
      <stop stop-color="#FFD75A"/>
      <stop offset="1" stop-color="#ED424B"/>
    </linearGradient>
    </defs>
  </svg>
</div>

非常完美了,不会有任何裁剪!(大家也可以复制上面这段代码放在 HTML 中验证)。

不一样的SVG!SVG在 CSS 中的应用

这样就“轻易”实现了SVG的尺寸自适应。

这里小结一下

  • 将SVG的尺寸改为`百分比。
  • 由于是居中描边,所以要修正一下坐标和大小。

除此之外,还能直接加上style样式,就像这样。

<svg     viewBox="0 0 100% 100%" fill="none" xmlns="http://www.w3.org/2000/svg">
  <style>
    rect{
      width: calc(100% - 4px);
      height: calc(100% - 4px);
    }
  </style>
  <rect x="2" y="2"     rx="4" stroke="url(#paint0_linear_1_2)" stroke-  stroke-linecap="round"/>
  <defs>
    <linearGradient   x1="0" y1="0" x2="1" y2="0">
      <stop stop-color="#FFD75A"/>
      <stop offset="1" stop-color="#ED424B"/>
    </linearGradient>
  </defs>
</svg>

虽然看着多,但后面作用更大,可以添加更多的 CSS 样式。

三、SVG 在 HTML 中的应用

其实前面的这段 SVG 可以直接放到 HTML 中用了,比如:

<button>
  <svg     fill="none" xmlns="http://www.w3.org/2000/svg">
    <rect x="2" y="2"       rx="16" stroke-  stroke="url(#paint0_linear_3269_5233)"/>
    <defs>
      <linearGradient   x1="0" y1="0" x2="100%" y2="100%" gradientUnits="userSpaceOnUse">
        <stop stop-color="#FFD75A"/>
        <stop offset="1" stop-color="#ED424B"/>
      </linearGradient>
    </defs>
  </svg>
  CSS
</button>

我们需要将这个 SVG撑满整个button,所以可以直接绝对定位。

button{
  position: relative;
}
button>svg{
  position: absolute;
  inset: 0;
}

这样就得到了一个自适应尺寸的、带有渐变边框的按钮,效果如下:

不一样的SVG!SVG在 CSS 中的应用

你也可以访问在线链接:buton with SVG (juejin.cn)[1]

四、SVG 在 CSS 中的应用

不知道你有没有这样的感觉,把一大段 SVG放在 HTML不是特别优雅,总觉得太臃肿了。

如果你有这种感觉,不妨将这段 SVG转换成内联CSS代码。

在这里可以借助张鑫旭老师的这个工具:SVG在线压缩合并工具[2]

不一样的SVG!SVG在 CSS 中的应用

我们将这段SVG粘贴过去,可以得到这样的一段内联SVG。

data:image/svg+xml,%3Csvg fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='1' y='1'       rx='16' stroke-  stroke='url(%23paint0_linear_3269_5233)'/%3E%3Cdefs%3E%3ClinearGradient   y2='100%25' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23FFD75A'/%3E%3Cstop offset='1' stop-color='%23ED424B'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E

有了这段内联SVG,我们可以直接用在background背景上。

button{
  background: url("data:image/svg+xml,%3Csvg fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='1' y='1'       rx='16' stroke-  stroke='url(%23paint0_linear_3269_5233)'/%3E%3Cdefs%3E%3ClinearGradient   y2='100%25' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23FFD75A'/%3E%3Cstop offset='1' stop-color='%23ED424B'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E")
}

而HTML只需要干净的button元素就够了。

<button>CSS</button>
<button>CSS & SVG</button>

神奇的是,即便是转为内联了,SVG仍然保持着自适应特性,这样也能实现同样的效果,是不是好多了?

不一样的SVG!SVG在 CSS 中的应用

你也可以访问在线链接:button with SVG background (juejin.cn)[3]

五、SVG 的独特魅力

如果说上面的效果 CSS 还能勉强模拟一下,那如果是这样的虚线呢?

不一样的SVG!SVG在 CSS 中的应用

对于 SVG 就非常容易了,只需要设置stroke-dasharray属性就行,并且可以随意更改虚线的间隔。

<svg     fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect x="2" y="2"       rx="16" stroke-  stroke="url(#paint0_linear_3269_5233)"  stroke-dasharray="8 4"/>
  <defs>
    <linearGradient   x1="0" y1="0" x2="100%" y2="100%" gradientUnits="userSpaceOnUse">
      <stop stop-color="#FFD75A"/>
      <stop offset="1" stop-color="#ED424B"/>
    </linearGradient>
  </defs>
</svg>

还有这种虚线边缘是圆角的情况,CSS就更加无能为力了。

不一样的SVG!SVG在 CSS 中的应用

SVG只需要设置stroke-linecap就行。

<svg     fill="none" xmlns="http://www.w3.org/2000/svg">
  <rect x="2" y="2"       stroke-  rx="16" stroke-linecap="round"  stroke="url(#paint0_linear_3269_5233)"  stroke-dasharray="8 6"/>
  <defs>
    <linearGradient   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 应该是实现不了了。

不一样的SVG!SVG在 CSS 中的应用

看似复杂,其实只需要改变stroke-dashoffset属性就行了,我们可以直接在SVG中插入CSS动画。

<svg     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   x="2" y="2"     stroke-  rx="16" stroke-linecap="round"  stroke="url(#paint0_linear_3269_5233)"  stroke-dasharray="8 6"/>
  <defs>
    <linearGradient   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都是固定尺寸的,不能自适应尺寸。
  • SVG很擅长渐变边框,而CSS很擅长自适应尺寸,得想办法取长补短。
  • SVG部分属性支持百分比类型,可以实现尺寸自适应。
  • SVG描边是居中描边,并且不可修改,所以需要调整圆角矩形的坐标的大小。
  • SVG中也支持 CSS部分特性,比如calc计算函数。
  • SVG还支持内嵌style标签,直接插入CSS代码。
  • 可以将SVG转为内联CSS代码,在支持SVG特性的同时极大的保证了HTML的整洁。
  • 借助SVG可以很轻松的实现渐变虚线边框。
  • 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。

原文地址:https://mp.weixin.qq.com/s/VH2U-jqm3cXI0yQFrR3adQ

延伸 · 阅读

精彩推荐
  • 编程技术gVim, gVim Easy, gVim Read-only 的简单区别

    gVim, gVim Easy, gVim Read-only 的简单区别

    今天打算好好学习一下python,买了一本书看了介绍无语了,gVim, gVim Diff, gVim Easy, gVim Read-only 的简单区别,需要的朋友可以参考下...

    编程猫3192020-07-31
  • 编程技术如何回溯解决组合问题和字符串分割

    如何回溯解决组合问题和字符串分割

    LeetCode 39:给你一个无重复元素的整数数组candidates和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有不同组合 ,并以列表形式返...

    怒码少年7552023-12-15
  • 编程技术代码是如何被编译的?

    代码是如何被编译的?

    在我们使用的所有编程语言,比如Java、C、javascript等,我们都会编写文本格式的源代码,编译器或解释器会将源代码按照语言语法解析成对应的语法结构树...

    Java技术指北11452024-04-01
  • 编程技术Git的使用规范流程总结

    Git的使用规范流程总结

    大家都明白在团队开发中,遵循一个合理、清晰的Git使用流程,是非常重要的。否则,每个人都提交一堆杂乱无章的commit,项目很快就会变得难以协调和维...

    阮一峰5582020-08-04
  • 编程技术网络编程之get与post的区别与联系

    网络编程之get与post的区别与联系

    这里来说说get与post的区别与联系,对这方面不懂的同学可以参考下。...

    编程技术网5092020-07-19
  • 编程技术2020年部署Web应用的4种方式

    2020年部署Web应用的4种方式

    使用什么托管服务?如何设置DNS和SSL?最重要的是,如何部署web应用程序?今天在这里,我们将讨论和比较部署这类应用的不同平台,并找到最适合你的平台!...

    Python学会5692020-10-27
  • 编程技术WKWebview 秒开的实践及踩坑之路

    WKWebview 秒开的实践及踩坑之路

    一般情况下,只要对照这个列表,对比差异就基本能搞定绝大部分前端性能问题了。不过我们在里面仔细再分析下,对首屏启动速度影响最大的就是网络请...

    网罗开发6792021-07-28
  • 编程技术一个有趣的带有版本控制的 CMS 现已开源!

    一个有趣的带有版本控制的 CMS 现已开源!

    最近,TinaCMS 通过 宣布已经彻底实现开源 ,使 自我托管变得更加便捷 ,从而成为了 开源 CMS 俱乐部的新成员。 如果你对此还不太了解,那么简单介绍一...

    Linux中国8892023-12-01