微信小程序css实现1rpx的带圆角的渐变border

1,056 阅读3分钟

有一个需求,需要实现一个带圆角的渐变border,大概类似这样:

9897d5652919a3893d9f69a4cf8e4c6.jpg

上手第一件事当然是康康border支不支持渐变,于是发现:border-image这个属性支持渐变。好!加上,刷新。 欸,我的圆角咋没了!?变成了这样:

ce245a84e4682ad12d3292a0df30e11.jpg

然后才发现border-image这个属性会导致border-radius失效。

稍加思索:如果我把两个盒子放在一起,上面的盒子背景色为白色,下面的盒子背景色为渐变色,下面的盒子比上面的盒子的宽高都大2px。然后下面的盒子的位置的top相对于上面的盒子往上移1px,left往左移1px。这样下面的盒子露出来的部分看起来不就像是上面的盒子的边框了吗? 好! 说干就干。代码如下,这里用了伪元素来实现下面的盒子

.border-test{
    position: absolute;
    width: 160rpx;
    height: 260rpx;
    left: 50rpx;
    bottom: 50rpx;
    background-color: white;
    border-radius: 10rpx;
}
.border-test::after{
    position: absolute;
    top: -1rpx;
    left: -1rpx;
    right: -1rpx;
    bottom: -1rpx;
    content: '';
    background: linear-gradient(#ec4b19, rgba(255, 0, 0, 0));
    border-radius: 10rpx;
    pointer-events: none;
    z-index: -2;
}

于是边框变成了这样

19fd9e4a0744855531ddccc15d70c0b.jpg

但是新的问题又来了,ui要求的边框粗细为1rpx。在微信小程序里面1rpx的边框是不生效的,会被计算成2rpx。解决这个问题的办法一般是给想要设置边框的元素加一个大小为它两倍的伪元素。然后给这个伪类设置一个2rpx的border,然后再将这个伪元素缩放0.5倍,最后让伪元素和这个盒子处于在同一位置。这样就可以实现1rpx的border,类似这样:

.border-test{
    position: absolute;
    width: 160rpx;
    height: 260rpx;
    left: 50rpx;
    bottom: 50rpx;
    background-color: white;
    border-radius: 10rpx;
}
.border-test::after{
    position: absolute;
    top: 0;
    left: 0;
    width: 200%;
    height: 200%;
    content: '';
    border: solid 2rpx #ec4b19;
    transform-origin: 0 0;
    transform: scale(0.5);
    box-sizing: border-box;
    border-radius: 20rpx;
    pointer-events: none;
}

效果如下:

0cce9c43363c119bdf2495e246215f1.jpg

于是再度稍加思索:缩放后的border是1rpx,那如果我能让这个1rpx的border变成渐变色就好了。那如果能有三个盒子,最上面的负责正常显示,中间的负责提供一个透明的1rpx的border,然后它自己有一个背景色。最下面的盒子负责提供一个渐变的背景色。这样子由于中间的盒子边框透明且有背景色。那岂不是只有边框会被下面的盒子的渐变背景染色。那不就获得了一个渐变的1rpx的border?ok!那我去试试

试试就逝世,结果变成了这样子,我那么大一个边框直接就无了

0a8cd943ad9f9bc0c322228220ffd38.jpg

因为中间那个盒子的背景色直接将它透明的边框给染色了...不过还好,天无绝人之路,css里面有这么一个属性:background-clip,mdn的解释如下:

设置元素的背景(背景图片或颜色)是否延伸到边框、内边距盒子、内容盒子下面。

只需要将中间盒子的这个属性设置为padding-box那它的边框就不会被背景染色了。于是一个完美的1rpx的带圆角的渐变border就出来了:

9897d5652919a3893d9f69a4cf8e4c6.jpg

全部代码:

.border-test{
    position: absolute;
    width: 160rpx;
    height: 260rpx;
    left: 50rpx;
    bottom: 50rpx;
    background-color: white;
    border-radius: 10rpx;
    z-index: 10;
    overflow: hidden;
}
.border-test::before{
    position: absolute;
    top: 0;
    left: 0;
    width: 200%;
    height: 200%;
    content: '';
    border: solid 2rpx transparent;
    transform-origin: 0 0;
    transform: scale(0.5);
    box-sizing: border-box;
    border-radius: 20rpx;
    pointer-events: none;
    background-color: white;
    background-clip: padding-box;
    z-index: -1;
}
.border-test::after{
    position: absolute;
    top: -2rpx;
    left: -2rpx;
    right: -2rpx;
    bottom: -2rpx;
    content: '';
    background: linear-gradient(#ec4b19, rgba(255, 0, 0, 0));
    border-radius: 10rpx;
    pointer-events: none;
    z-index: -2;
}