本文最后更新于:2024年8月13日 下午
实现多个渐变色叠加的边框
如何实现下面这个由两个渐变色叠加的边框效果:
对于单个渐变色的边框可以用border-image
轻松实现
1 2 3 4 5 6 7
| .border-image-demo{ margin: 10px 0; width: 200px; height: 100px; border: 2px solid; border-image: linear-gradient(135deg, skyblue, purple) 1; }
|
但这个方式存在两个问题:
border-image
只能接受一个渐变色,无法叠加多个渐变色
border-image
无法通过border-radius
实现圆角
方法一:border-image+overflow
这一方法是在原有border-image
方法上的改进,既然使用了border-image
属性的元素无法通过border-radius
属性实现圆角,那么可以给该元素添加一个父元素,给父元素设置border-radius
属性,并设置overflow:hidden
,以此来实现边框的圆角效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| .border-image-demo-container{ margin: 10px 0; width: 206px; height: 106px; border-radius: 5px; overflow: hidden; }
.border-image-demo{ width: 200px; height: 100px; border: 3px solid; border-radius: 50px; border-image: linear-gradient(135deg, skyblue, purple) 1; }
|
但是也可以看到,这种方法存在两个问题
- 内部的黑色部分(内容部分)仍为方形,棱角分明
- 父元素的圆角不能太大,一但偏大就会出现边框断裂的问题
这是因为带有border-image
的子元素本身是没有任何变化的,只是父元素中通过设置border-raduis
对子元素进行遮挡而已,因此当父元素的圆角遮住了子元素的边框宽度后,子元素的边框便“断裂”了
方法二:多border-image元素叠加
此方法可以解决border-image
不能使用多个渐变色的问题,既然一个border-image
无法使用多个渐变色,那就用多个元素并设置border-image
进行叠加,即可实现多渐变叠加的效果。
1 2 3 4
| <div class="container"> <div class="mask1"></div> <div class="mask2"></div> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| .container{ width: 200px; height: 100px; background-image: linear-gradient(100.9deg, #112531 -1.03%, #111111 37.46%, #000001 96.14%); position: relative; margin-bottom: 10px; }
.mask1{ position: absolute; width: 100%; height: 100%; border: 2px solid; box-sizing: border-box; border-image: linear-gradient(125.19deg, rgba(208, 208, 242, 0) 48.74%, rgba(223, 223, 252, 0.6) 98.12%) 1; z-index: 1; }
.mask2{ position: absolute; width: 100%; height: 100%; border: 2px solid; box-sizing: border-box; border-image: linear-gradient(312.62deg, rgba(105, 124, 159, 0) 81.16%, rgba(255, 255, 255, 0.72) 99.61%) 1; z-index: 1; }
|
这种方法实现了浮于子元素上方的多渐变叠加的边框,但同样无法实现圆角的问题,此外这个方法的缺点显而易见,每个添加渐变都需要添加一个元素,很不方便。
方法三:clip-path
这种方法与方法一非常相似,方法一是通过添加父元素并设置overflow:hidden
来对边框进行遮挡,而这种方法则是通过clip-path
对元素本身进行裁剪。
1 2 3 4 5 6 7 8
| .clip-path-demo{ width: 200px; height: 100px; border: 3px solid; border-image:linear-gradient(135deg, rgba(123,123,252), rgba(0,253,252)) 1; margin: 10px 0; clip-path: inset(0 round 5px); }
|
首先还是通过border-image
设置渐变边框,之后通过clip-path
属性对元素进行裁剪。clip-path: inset(0 round 10px)
,其中inset()
是矩形裁剪,inset(0 round 10px)
表示为一个与父容器完全贴合的容器,并且其border-radius
为10px
,将这个元素之外的内容全部裁剪不可见。
inset()
方法的位置信息有四个可选项,分别对应距离上、下、左、右四条边的距离,round
为可选参数,其同样可以使用四个数值分别描述四个角的圆角数值。
这个方法的缺点也和方法一一样:
- 内部的黑色部分(内容部分)仍为方形,棱角分明
- 裁剪的圆角不能太大,一但偏大就会出现边框断裂的问题
方法四:background-image
在对border-image
尝试无果后,便开始考虑通过background-image
来实现这个效果,最常用的方法是给出一个宽高都略大于目标元素的div
标签,设置其background-image
和border-image
属性,将其放置在目标元素的下方,模拟出了一个边框。
1 2 3 4
| <div class="background-image-demo-container"> <div class="background-image-demo-content"> </div> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| .background-image-demo-container{ margin: 10px 0; width: 206px; height: 106px; position: relative; border-radius: 20px; background-image: linear-gradient(135deg, rgba(123,123,252,0.4), rgba(0,253,252,0.4)), linear-gradient(45deg,rgba(133, 208, 84, 0.4) 48.74%, rgba(23, 23, 232, 0.6) 98.12%); }
.background-image-demo-content{ width: 200px; height: 100px; position: absolute; top: 3px; left: 3px; border-radius: 20px; background-color: black; }
|
或者也可以不用两个元素,而用::after
替代
1 2 3 4 5 6 7 8 9 10
| .background-image-demo-container::after{ content: ""; width: 200px; height: 100px; position: absolute; top: 3px; left: 3px; border-radius: 20px; background-color: black; }
|
左侧为单个渐变的效果,右侧为两个渐变叠加的效果,可见多个渐变叠加得以实现。同时也可以通过border-radius
属性实现圆角。但这种情况下,如果需要该半透明的边框叠加在图片上方,则无法实现。
方法五:mask-image
为了将边框浮于元素上方,便思考有没有一种方法能够将元素裁剪为一个环,首先想到的是mask-image
,他能够定义一个蒙版,来遮挡住元素,mask-image
接收图片或者渐变色作为参数,而线性渐变无法实现效果,其只能实现渐隐的效果,因此采用径向渐变来进行蒙版的构建。
1 2 3 4 5 6 7 8 9 10 11 12
| .mask{ content:''; width:200px; height:100px; border-radius:50px 0; position:absolute; top: 0; left: 0; background: linear-gradient(125.19deg, rgba(208, 208, 242, 0) 48.74%, rgba(223, 223, 252, 0.6) 98.12%), linear-gradient(312.62deg, rgba(105, 124, 159, 0) 81.16%, rgba(255, 255, 255, 0.72) 99.61%); mask-image: radial-gradient(circle at center, transparent 60%, black 100%); }
|
虽然效果不是非常理想,但是至少模拟出了类似的效果,将其移至元素上方即可。
方法六:background-clip
最后,我找到了background-clip
方法,background-clip
方法设置元素的背景(背景图片或颜色)是否延伸到边框下面。它的部分取值和 box-sizing
类似。其中,
background-clip: border-box
表示设置的背景 background-image
将延伸至边框
background-clip: content-box
表示设置的背景 background-image
被裁剪至内容区(content box)外沿
具体的效果示例可见MDN
重要的是,这个方法可以设置多个参数,用以对应多个background
参数,也就是说,我们可以在background-image
属性中,设置四层背景,第四层背景(也就是最下方的背景)是要显示的子元素的背景色,第二三层背景则是两个构建边框的渐变色,第一层背景(也就是最上方的背景)也是要显示的子元素的背景色,用于遮挡住二三层的渐变色。为了使二三层的渐变色边框能够显露出来,将二三层边框的background-clip
参数设置为border-box
,而第一层背景的background-clip
属性设置为content-box
这样第一层背景就只遮挡住了content-box
部分的内容,而将border
部分的内容显露出现,正好形成了一个边框,并叠加在底层元素的上方。
1 2 3 4 5 6 7 8 9 10 11 12 13
| .background-clip-use{ width: 200px; height: 100px; border: solid 2px transparent; border-radius: 50px 0; background-image: linear-gradient(100.9deg, #F3F8FF -1.03%, #D7E1EE 37.46%, #A6B4FE 96.14%), linear-gradient(125.19deg, rgba(28, 208, 242, 0) 48.74%, rgba(23, 223, 252, 0.6) 98.12%), linear-gradient(312.62deg, rgba(105, 124, 159, 0) 81.16%, rgba(255, 25, 255, 0.72) 99.61%), linear-gradient(100.9deg, #F3F8FF -1.03%, #D7E1EE 37.46%, #A6B4FE 96.14%); background-origin: border-box; background-clip: content-box, border-box, border-box, border-box; }
|
裁剪得到的边框如下所示(该情况下去掉了最下方的背景,使得边框单独展示):
添加上最底层的背景后得到了想要的结果,如下图所示
方法七:复制为SVG
另外的开发过程中,对于这类复杂背景,可以直接从figma设计稿中选中图形,右键复制为svg或者png,导入到项目的静态资源中,直接使用url()
设置为背景图更加的便捷。
Reference
巧妙实现带圆角的渐变边框
不要图片?CSS实现圆角边框渐变色+背景透明