圆角、渐变边框、毛玻璃的叠加实现与优化
实现一个圆角的效果最简单的方案便是border-raduis,同样的,实现渐变边框可以使用border-image。但两种属性的叠加并不会出现理想的效果,元素的边框呈现渐变效果,圆角却失效了。那如何使元素同时具备圆角和渐变边框的效果呢?
【能用】background-image
使用两个元素,底层元素使用渐变色背景,上层元素使用纯色背景,同时给两个元素设置圆角,从视觉上实现边框的效果
<div class="wrap">
<div class='content'>
“圆角渐变边框示例”是一个展示如何使用圆角和渐变效果来美化边框的案例。这个示例通过结合圆角的柔和视觉效果与渐变的色彩变化,展现出一种现代而富有层次感的设计风格。
</div>
</div>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrap {
width: 300px;
height: 150px;
padding: 4px;
margin: 25px auto;
background-image: linear-gradient(112deg, #696bff 47%, #f0aeff 86%);
border-radius: 16px 16px 4px 16px;
}
.content {
width: 100%;
height: 100%;
padding: 8px;
background-color: #fff;
border-radius: 16px 16px 4px 16px;
}
虽然渐变边框和圆角的问题都解决了,但是正常情况下,内部圆角应该比外部圆角的尺寸要小,这里设置为相同的值,导致渐变边框在圆角的地方视觉上不协调。可以尝试减小内圆角弥补这个问题,但具体减小的尺寸不好确定。
【好用】background-image + background-clip
为了解决圆角尺寸不协调问题,在此引入background-clip。同样使用两个元素,底层元素使用渐变色背景,上层元素使用纯色背景,额外为上层元素添加透明边框,并设置background-clip: padding-box
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrap {
width: 300px;
height: 150px;
margin: 25px auto;
background-image: linear-gradient(112deg, #696bff 47%, #f0aeff 86%);
border-radius: 16px 16px 4px 16px;
position: relative;
}
.content {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
padding: 8px;
background-color: #fff;
border: 4px solid transparent;
border-radius: 16px 16px 4px 16px;
background-clip: padding-box;
}
以透明边框和background-clip的方式,使得内圆角不需要手动设定,纯色背景存在于边框内部,下层的渐变色因为透明边框的原因得以显现,在视觉上充当渐变边框。完美解决了手动设置内圆角,内外不协调问题。
【优化】background-image + background-clip + background-origin
background-image + background-clip的方案已经可以完美解决圆角渐变边框的问题了,但使用两个元素代码显得不够优雅,因此借助background-origin对代码进行简化。
<div class="wrap">
“圆角渐变边框示例”是一个展示如何使用圆角和渐变效果来美化边框的案例。这个示例通过结合圆角的柔和视觉效果与渐变的色彩变化,展现出一种现代而富有层次感的设计风格。
</div>
.wrap {
width: 300px;
height: 150px;
margin: 25px auto;
padding: 8px;
border: 4px solid transparent;
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
background-image: linear-gradient(to right, #fff, #fff), linear-gradient(112deg, #696bff 47%, #f0aeff 86%);
border-radius: 16px 16px 4px 16px;
}
使用padding-box和border-box将纯色背景限制在padding及其以内,将渐变色限制在border及其以内,透明的border为渐变色预留空间,以两种不同的背景渲染方式叠加,实现一个节点圆角渐变边框,大大减少了代码量。需要注意的是必须先定义padding-box再定义border-box。
【扩展1】添加毛玻璃效果
实现此功能,需要解决两个问题:
- 如何实现毛玻璃效果
- 如何让背景半透明
第一个问题不言而喻,使用滤镜backdrop-filter,不过backdrop-filter与background-image并不能同时设置,因此毛玻璃滤镜需要独立于背景。对于背景半透明的效果,rgba必然是首选,但这里使用的是渐变色,故采用opacity赋予背景块半透明。这种方式处理后发现,文字也跟随背景有了半透明的效果,因此需要将文字独立于背景。最后,我们将滤镜加在文字节点上,使用伪元素实现背景块,背景块使用position: absolute;绝对定位,z-index: -1将背景块置于文字底部。
<div class="wrap">
“圆角渐变边框示例”是一个展示如何使用圆角和渐变效果来美化边框的案例。这个示例通过结合圆角的柔和视觉效果与渐变的色彩变化,展现出一种现代而富有层次感的设计风格。
</div>
.wrap {
position: absolute;
top: 20px;
left: 20px;
width: 300px;
height: 150px;
padding: 8px;
backdrop-filter: blur(5px);
border-radius: 16px 16px 4px 16px;
}
.wrap::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 4px solid transparent;
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
background-image: linear-gradient(to right, #fff, #fff), linear-gradient(112deg, #696bff 47%, #f0aeff 86%);
border-radius: 16px 16px 4px 16px;
opacity: 0.7;
z-index: -1;
}
图片中间的元素同时具备了圆角、渐变边框和毛玻璃的效果,唯一美中不足是opacity将背景色块的颜色变浅了,不能接受的话就只能用SVG去实现了。
【扩展2】封装为 scss 方法
以上的方案已经基本实现了我们的需求,但页面中广泛应用时,需要频繁复制粘贴,造成了代码冗余,因此我们借助 scss 将圆角渐变边框封装为一个通用方法linear-gradient-bg,通过参数控制边框颜色、圆角、宽度等
@mixin linear-gradient-bg(
$innerBg: linear-gradient(to right, #fff, #fff),
$borderBg: linear-gradient(112deg, #696bff 47%, #f0aeff 86%),
$borderWidth: 4px,
$borderRadius: 16px 16px 4px 16px,
$backdropFilter: blur(5px),
$opacity: 0.7,
$boxSizing: content-box
) {
position: relative;
backdrop-filter: $backdropFilter;
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
@if $boxSizing == content-box {
width: 100%;
height: 100%;
} @else {
width: calc(100% - $borderWidth * 2);
height: calc(100% - $borderWidth * 2);
}
border: $borderWidth solid transparent;
background-clip: padding-box, border-box;
background-origin: padding-box, border-box;
background-image: $innerBg, $borderBg;
border-radius: $borderRadius;
opacity: $opacity;
z-index: -1;
}
}
接下来我们使用linear-gradient-bg这个 scss 方法实现一下圆角渐变边框的功能
<div class="wrap">
“圆角渐变边框示例”是一个展示如何使用圆角和渐变效果来美化边框的案例。这个示例通过结合圆角的柔和视觉效果与渐变的色彩变化,展现出一种现代而富有层次感的设计风格。
</div>
.wrap {
@include linear-gradient-bg();
position: absolute;
top: 20px;
left: 20px;
width: 300px;
height: 150px;
padding: 8px;
border-radius: 16px 16px 4px 16px;
}
通过封装 scss 方法的方式,使用时仅需@include linear-gradient-bg();一行代码即可实现圆角渐变边框的功能。在调用这个方法时,还可以通过参数控制边框样式,例如要修改渐变边框颜色、圆角属性,仅需在调用时传入自定义$borderBg与$borderRadius即可
.wrap {
@include linear-gradient-bg(
$borderBg: linear-gradient(112deg, #65c9eb 47%, #6bd750 86%),
$borderRadius: 16px
);
position: absolute;
top: 20px;
left: 20px;
width: 300px;
height: 150px;
padding: 8px;
border-radius: 16px;
}
【扩展3】使用 SVG 实现
上述方案中为了实现毛玻璃的效果,我们不得不为背景色设置opacity,让背景变得半透明,但这样同时导致了边框颜色变淡。进一步解决这个问题,我们采用 SVG 重新实现此功能
<div className="wrap">
“圆角渐变边框示例”是一个展示如何使用圆角和渐变效果来美化边框的案例。这个示例通过结合圆角的柔和视觉效果与渐变的色彩变化,展现出一种现代而富有层次感的设计风格。
<svg width="100%" height="100%">
<!-- 定义渐变 -->
<defs>
<linearGradient id="gradient1" x1="0%" y1="0%" x2="100%" y2="0" gradientTransform="rotate(112deg)">
<stop offset="47%" style={{ stopColor: '#696bff', stopOpacity: 1 }} />
<stop offset="86%" style={{ stopColor: '#f0aeff', stopOpacity: 1 }} />
</linearGradient>
</defs>
<!-- 绘制圆角矩形,应用渐变边框 -->
<rect
x="2"
y="2"
width="calc(100% - 4px)"
height="calc(100% - 4px)"
rx={16}
fill="none"
stroke="url(#gradient1)"
strokeWidth="4"
/>
</svg>
</div>
.wrap {
position: absolute;
top: 20px;
left: 20px;
width: 300px;
height: 150px;
padding: 8px;
border-radius: 16px;
backdrop-filter: blur(5px);
}
svg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
可以看出 SVG 的方案,相比于 css 没有颜色偏差,毛玻璃效果也更加明显,缺点是书写起来较为复杂,如果项目中使用类似 postcss 对 px 进行转换的话,还需要手动针对 SVG 的数值做对应的处理。
补充:rect 的 x、y 需要设置为边框宽度的一半,width、height 也需要减去一个边框宽度。下面引用 MDN 中的图,可以看出边框是以设置点为中心,两侧均分,如果x、y设置为0,有一半边框会丢失
至此已经通过多种方式实现了圆角渐变边框的功能,优先推荐使用 scss 封装方法的方案,这种方案更简洁、复用性更强,项目中如果没有集成 scss 则使用background-image + background-clip + background-origin的方案。如果需要毛玻璃效果,且对精度要求很高,颜色不能有偏差,则使用 SVG 的方案。
本文来自博客园,作者:寒沁,转载请注明原文链接:https://www.cnblogs.com/hanqin/p/18990105

浙公网安备 33010602011771号