简单上手圆角渐变边框

2,171 阅读4分钟

最近有遇见一个圆角渐变边框的需求,顺便整理了一些 css 写法~

实际需求如下: (圆角+渐变边框+透明背景) image.png

我们先从圆角渐变边框开始吧~

示意图如下:

image.png

代码:

  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 规范没有出现最常用的方法

效果:圆角 ✅ 透明背景 ❎

示意图如下:

image.png

代码:

 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:hiddenborder-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

它用于裁剪元素的可见部分,使其只显示指定的区域。它可以用来创建各种形状的剪切效果,包括矩形、圆形、多边形等。感兴趣的同学可以好好研究研究~

那么在这里,我们只需要利用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

采用 -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

好了,本文整理完毕,希望对你有所帮助:)

如果还有疑问或者更多好方法,欢迎多多交流哟~