css实现带圆角且内部透明的渐变边框

628 阅读3分钟

实现方法来自:现代 CSS 解决方案:全尺寸的带圆角的渐变边框

结合了自身业务遇到的场景进行改进,方便下次直接复制粘贴就能用上,有相同场景的可以参考下~

image.png

背景

在AI相关的需求越来越多的背景下,前端上元素也多少要沾点"AI风"了。

我这遇到的AI相关样式总会有个蓝紫渐变的容器背景。最近遇到容器中出现了一个0.5px边框带圆角的Tag,粗略一看,使用公司内的Tag组件就完事了。但稿子放大一看,😱,边框咋是渐变的啊!

之前其实也写过不少渐变边框,无一例外都是纯色背景,即边框内容不需要透明,或者可以跟所处容器一致。

遇到问题先是使用VSCode的Copilot Chat(Claude 3.7,询问模式) 问一问,效果不太行,就转战掘金。看到的文章还是Coco大佬的。

总结下需求就是:

  • 支持圆角
  • 支持0.5px粗细边框
  • 边框内的容器要透明
  • 兼容性要好:Android5+,iOS11+
  • 不需要额外元素,最好只通过伪元素实现
  • 仅用一个css类能加上更好!

实现

先贴核心实现,需要注意的是加这个类的元素的定位需要是非static,按需添加padding,避免伪元素实现的边框遮盖到内容。

      .gradient-border::after {
        content: '';
        box-sizing: border-box;
        position: absolute;
        top: -50%;
        right: -50%;
        bottom: -50%;
        left: -50%;
        transform: scale(0.5);

        /* 圆角大小,注意scale的缩放*/
        border-radius: 12px;
        /* 边框大小,不能小于0.5,注意scale的缩放 */
        padding: 2px;
        /* 边框颜色 */
        background: linear-gradient(#804cff, #3b63ff);

        /* 核心,兼容性 ios2+ android2+ */
        -webkit-mask: linear-gradient(#fff 0 100%) content-box,
          linear-gradient(#fff 0 100%);
        mask: linear-gradient(#fff 0 100%) content-box,
          linear-gradient(#fff 0 100%);
        -webkit-mask-composite: xor;
        mask-composite: exclude;

        pointer-events: none;
      }

顺带贴一下不需要考虑内部透明的渐变实现,看场景使用

clip-gradient-border {
        border: 1px solid transparent;
        border-radius: 6px;
        background-clip: padding-box, border-box;
        background-origin: padding-box, border-box;
        /* 第一个渐变为内部背景色,第二个渐变为边框渐变色 */
        background-image: linear-gradient(to right, #fff, #fff),
          linear-gradient(90deg, #8f41e9, #578aef);
}

关于mask相关的原理和详细用法直接看coco大佬文章就可以。

这里列一下直接使用coco文章中的实现所遇到的问题:

  1. 不支持0.5px边框实现,底部边框不可见了
  2. 内部镂空了,但是内部的元素也不可见了

总结

还好之前学过transform是实现0.5px边框,这下就能把原理利用到新知识上了,这种融会贯通的感觉很棒!

还有在写文章的时候又用ChatGPT 4o问了下,它竟然也知道用mask来实现了,虽然还需要微调一些,但是比Vscode copilot chat那玩意强些。提示词如下(可以帮忙看看有没有什么没问好的地方)

如何通过纯css实现一个支持圆角、0.5px粗细、所处的背景是渐变背景或者半透明背景(自身内容是要透明的)的渐变边框,最好通过伪元素实现,或者不需要额外元素?