最近在做一个看上去很酷炫的代码项目,其中有一个需求是做带渐变色的圆角边框,本来以为这是一个很简单的事情,殊不知踩了很多坑,终于艰难的完成了。这个过程中最大的收获就是,啊,原来css还有那么多神奇的好用的属性啊
废话不多说,先上一个最终的版本
.normal-btn {
position: relative;
z-index: 2;
}
.normal-btn:before {
content: "";
position: absolute;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 3px;
border-radius: 8px;
background: linear-gradient(to right, red 0%, green 100%);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
}
.normal-btn:hover::before {
content: "";
position: absolute;
z-index: -1;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 3px;
border-radius: 8px;
background: linear-gradient(to right, green 0%, red 100%);
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude;
}
这个版本获得的是背景透明的渐变边框,如果想要背景半透明或者背景为其他颜色的小伙伴,修改mask颜色即可
但是友(wan)好(e)的产品经理想要实现边框背后发光,利用mask并不能实现,实现方法接着往下看吧
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
接下来就是正题了,因为涉及的属性有点多,而且最近项目比较着急,所以也没有完全研究透彻,希望跟大家多点交流
第一步尝试
按照提议分析:渐变:linear-gradient
,圆角:border-radius
,边框:border
,这三个属性结合,那不就完美结合了么,于是有了以下代码(代码隐去了其他必要的属性,只提炼最精华的部分):
.card {
border: 2px solid linear-gradient(red, green);
border-radius:8px;
}
然后惊讶的发现,border不支持渐变色,呜呜呜~只能另外找办法了,还好有个叫border-image
的小可爱支持渐变,于是代码变成了这个样子:
.card {
border: 2px solid;
border-radius:8px;
border-image: linear-gradient(red, green)
}
想着这回总没问题了吧,但是桑心的事情又出现了,渐变是有了,我的圆角呢,我可可爱爱的圆角哪里去了,答案是被border-image
给吞了,呜呜呜~
border-image
与border-radius
并不兼容,border-image
的出现会覆盖border
关于形状,颜色等的属性,所以这两个属性同时使用时无法展示圆角
第二步尝试
遇事不决当然是求助搜索引擎啦~于是各种搜搜搜,啊,可以使用background
来模拟这个过程啊,毕竟这也是一个可以愉快使用渐变的属性,可不可以使用两个圆角的元素重叠在一起,利用元素的padding当作border,说干就干!!
.card {
position: relative;
height:300px;
width:300px;
padding:10px;
border-radius: 8px;
background-image: linear-gradient(red,green);
}
.card::before {
content: "";
position: absolute;
height: 300px;
width: 300px;
left: 8px;
right: 0;
top: 8px;
bottom: 0;
border-radius: 8px;
background-color: white;
}
完成是完成了,但是要怎么往里面加内容咧。。。我陷入了沉思,但是不管怎样,总算有了一个好的开始吧,如果要加内容,往里面继续div也不是不可以,但是这样下来,这层级越加越多并不是什么好事情
成功的方案
那有没有不需要添加伪元素的方案呢?答案当然是肯定的啦,有个很神奇的属性叫做background-clip
,利用它以及background-image
就可以完美实现一个元素完成需求。但这个方案有个缺陷,必须有一个背景色,因为这个方案的原理与上一个方案本质上是一样的,只不过少了一个伪元素
.card {
background-image: linear-gradient(#fff, #fff),
linear-gradient(red, green);
padding: 2px;
background-clip: content-box, padding-box;
}
后来,产品经理说想要个透明的,emmm,最后找到了mask的方案(文章开头的方案),但还是依赖伪元素,但目前来说已经算是不过的解法了。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
完结,撒花🎉🎉🎉
后记:CSS还是有好多好玩的元素,能够完成很多出彩的元素,现在用太多框架组件库,都差点忘记CSS是前端三巨头之一,以后有机会还是需要多一点使用CSS,创造更多炫酷的页面