最近有遇见一个圆角渐变边框的需求,顺便整理了一些 css 写法~
实际需求如下:
(圆角+渐变边框+透明背景)
我们先从圆角渐变边框开始吧~
示意图如下:
代码:
wrap: {
width: 200,
padding: 10,
textAlign: 'center',
color: 'white',
border: '1px solid ',
borderImageSource: 'conic-gradient(#f88fe9,#7000ff 20%,#58d2f2 50%,#fff 75%,#f88fe9 100%)',
borderImageSlice: 1,
borderImageRepeat: 'stretch',
},
<div className={classes.wrap}>圆角边框1</div>
这里用到的 border-image ,它是一个CSS规范(border-image新加的一个属性值,用于设置元素的边框图像。它允许将图像作为边框应用到元素的边缘,而不是使用常规的边框样式。总的来说,就是可以非常方便地设置渐变或者图片背景啦~
border-image非常奶思,但很可惜,它不支持设置border-radius,这就导致了我们当遇见圆角边框需求的时候,就得重新找方案了
方案1 background-image+伪元素
我们将border-image换成background-image+ 伪元素的方案,这也是在 border-image 规范没有出现最常用的方法
效果:圆角 ✅ 透明背景 ❎
示意图如下:
代码:
wrap: {
position: 'relative',
borderRadius: 10,
background: 'linear-gradient(45deg, gold, deeppink)',
width: 200,
height: 100,
'&::after': {
content: "''",
position: 'absolute',
width: 180,
height: 80,
background: '#fff',
top: '50%',
left: '50%',
transform: 'translate(50px, -50%)',
zIndex: 1,
animation: 'move 4s infinite',
},
'@keyframes move': {
'0%': {
transform: 'translate(50px, -50%)',
},
'50%, 100%': {
transform: 'translate(-50%, -50%)',
},
},
},
显而易见,这个方法存在两个问题,第一个是多加了一个伪元素(::before),而且还要计算它的宽高。第二个是,如果要求边框内的背景是透明的,那么这个方案就行不通啦
方案2 background-clip:content-box + background-clip:border-box
效果:圆角 ✅ 透明背景 ❎
background-clip是一个CSS属性,用于指定背景图像的绘制区域。它控制了背景图像的绘制范围,可以将背景限制在元素的内容区域、内边距区域或边框区域内。
它包含以下几个取值:
border-box:背景图像将绘制在元素的边框盒子(包括边框和内边距)内,超出边框的部分不可见。padding-box:背景图像将绘制在元素的内边距盒子内,超出内边距的部分不可见。content-box:背景图像将绘制在元素的内容区域内,超出内容区域的部分不可见。text:背景图像将绘制在文本内容的前景上,超出文本内容的部分不可见。
那么在这里,我们设置两个background-image和两个background-clip,最后将border设置为透明就可以啦~
代码:
wrap: {
width: 200,
textAlign: 'center',
color: 'white',
border: '1px solid transparent',
borderRadius: 10,
// 双层渐变
backgroundImage: ' linear-gradient(#fee, pink),linear-gradient(to right, red, yellow)',
backgroundOrigin: 'border-box',
backgroundClip: 'content-box, border-box',
},
缺点:它也不支持透明的背景
方案3 border-image + overflow:hidden
效果:圆角 ✅ 透明背景 ❎
上面我们提到border-image不支持设置border-radius,那么我们在外层给他加一个父容器,给父容器设置overflow:hidden和border-radius就可以啦
代码:
<Box className={classes.borderWrap}>
<div className={classes.gradientOverlay} />
<div className={classes.content}>内容</div>
</Box>
borderWrap: {
backdropFilter: 'blur(2px)',
transition: 'all 0.2s',
overflow: 'hidden',
zIndex: 1,
padding: '2px',
color: 'white',
borderRadius: 16,
},
gradientOverlay: {
top: '-1000%',
right: '-1000%',
bottom: '-1000%',
left: '-1000%',
content: "''",
opacity: 0.75,
position: 'absolute',
backgroundImage: 'conic-gradient(#f88fe9,#7000ff 20%,#58d2f2 50%,#fff 75%,#f88fe9 100%)',
animation: 'rotate 2s infinite linear',
transition: 'opacity 0.2s',
animationDuration: '3s',
animationTimingFunction: 'linear',
animationDelay: '0s',
animationIterationCount: 'infinite',
animationDirection: 'normal',
animationFillMode: 'none',
animationPlayState: 'running',
animationName: '$spin',
'@keyframes rotate': {
from: {
transform: 'rotate(0deg)',
},
to: {
transform: 'rotate(360deg)',
},
},
},
content: {
position: 'relative',
background: 'black',
borderRadius: 'inherit',
}
方案4 border-image + clip-path
效果:圆角 ✅ 透明背景 ✅
除了上面添加父容器的写法,我们还可以借助其他方法产生带圆角的容器,在这里用的就是clip-path
它用于裁剪元素的可见部分,使其只显示指定的区域。它可以用来创建各种形状的剪切效果,包括矩形、圆形、多边形等。感兴趣的同学可以好好研究研究~
那么在这里,我们只需要利用clip-path裁剪出一个圆角的容器就可以啦
代码:
wrap: {
width: 200,
textAlign: 'center',
position: 'relative',
color: 'white',
border: '10px solid',
borderRadius: 10,
// 双层渐变
borderImage: 'linear-gradient(45deg, gold, pink) 1',
clipPath: 'inset(0 round 10px)',
filter: 'hue-rotate(360deg)',
animation: 'huerotate 6s infinite linear',
'@keyframes huerotate': {
'0%': { filter: 'hue-rotate(0deg)' },
'100%': { filter: 'hue-rotate(360deg)' },
},
},
小tips:
clip-path: inset(0 round 10px)
具体来说,剪切路径的含义如下:
inset:指定剪切区域是一个相对于元素内边距框的矩形。0:表示剪切区域上、右、下、左边界与内边距框的边界重合,也就是不偏移剪切区域。round:表示剪切区域的边角使用圆角。10px:表示圆角的半径为10像素。
这里可以利用 filter: "hue-rotate(360deg)"顺手加个渐变动画~
方案5 -webkit-mask-composite
效果:圆角 ✅ 透明背景 ✅
代码:
wrap: {
padding: 10,
display: 'inline-block',
position: 'relative',
zIndex: 0,
textAlign: 'center',
width: 200,
'&::before': {
content: '""',
position: 'absolute',
zIndex: -1,
top: 0,
left: 0,
right: 0,
bottom: 0,
border: '10px solid transparent',
borderRadius: 10,
background: `linear-gradient(to right, ${theme.colors.pink[3]}, ${theme.colors.red[6]}) border-box`,
WebkitMask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
WebkitMaskComposite: 'xor',
maskComposite: 'exclude',
},
},
在这里采用了xor,在这个模式下,当源蒙版图像和目标蒙版图像中的重叠像素都完全不透明,那么它们将变得完全透明,就解决了透明背景的问题啦
demo实例
上面所有写法的demo汇总: 圆角渐变边框demo
好了,本文整理完毕,希望对你有所帮助:)
如果还有疑问或者更多好方法,欢迎多多交流哟~