你有没有试过把CSS的边框做成重复的之字形?比如在网站的一个彩色部分结束,另一个不同颜色部分开始的地方--不是用直线,而是有角度的之字形、圆形的驼峰或波浪。有很多方法可以实现这种CSS边框,可以一直追溯到使用background-image 。但我们可以用它来做得更现代、更程式化。在这篇文章中,我们将看看一些现代的CSS遮罩技术来实现这种外观。
不过,在我们深入研究技术部分之前,让我们先看看我们正在构建的东西。我做了一个CSS边框生成器,你可以在几秒钟内轻松生成任何种类的边框,并获得CSS代码。
你看到了吗?通过CSSmask 属性和一些CSS渐变,我们得到了一个反应灵敏、外观很酷的边框--所有这些都是通过CSS本身完成的。不仅如此,这种效果还可以应用于任何可以有任何颜色的元素(如图像、渐变等)。我们可以得到这一切,而不需要额外的元素、伪元素或不知从何而来的神奇数字
哦,太好了!我所要做的就是复制这些元素。我所要做的就是复制/粘贴代码,然后就完成了!
是的,但了解逻辑是很好的,如果你需要,可以手动调整代码。
遮蔽东西
由于我们所有的效果都依赖于CSSmask 属性,让我们快速回顾一下它是如何工作的。直接来自规范。
对图形对象应用遮罩的效果,就好像图形对象将通过遮罩被涂到背景上,从而完全或部分地遮住了图形对象的一部分。
如果我们检查mask 属性的正式语法,我们可以看到它接受一个<image> 作为值,这意味着要么是图像的URL,要么是颜色渐变。梯度是我们将在这里使用的。让我们从基本的例子开始。
在这个演示的第一个例子中,一个渐变被用来使它看起来好像图像正在逐渐消失。同时,第二个例子也使用了渐变,但不是颜色之间的柔和过渡,而是用一个硬的色块来隐藏(或掩盖)图像的一半。第二个例子说明了我们将使用的技术来创建我们的花式边框。
哦,CSSmask 属性可以接受多个梯度,只要它们是以逗号分隔的。这意味着我们有更多的控制权来掩盖图像的其他部分。
那个显示多个遮蔽渐变的例子乍一看可能有点棘手,但所发生的事情与应用background 属性上的多个渐变是一样的。但我们不是使用与页面背景相融合的颜色,而是对图像的隐藏部分使用一个 "透明 "的黑色值 (#0000) ,对可见部分使用全黑 (#000) 。
就这样了!现在我们可以处理我们的花式边框了。
之字形的CSS边框
正如我们在本文开头的视频中所看到的,生成器可以在一边、两边或所有边上应用边框。让我们从底面开始,使用一步步的图示。
- 我们首先在顶部添加第一个带有纯色的渐变层(
red)。用一个等于calc(100% - 40px)的高度,在底部留下40px的空位。 - 我们在底部添加第二个渐变层,它占用了容器的剩余高度。为了实现这个目标,有一点几何学上的变化。
- 接下来,我们在水平方向上重复最后一个梯度(用
repeat-x替换no-repeat)。我们已经可以看到 "之 "字形了。 - 众所周知,梯度有抗锯齿问题,会产生锯齿状的边缘(尤其是在Chrome上)。为了避免这种情况,我们在颜色之间添加一个轻微的过渡,将
blue 90deg, green 0改为green, blue 1deg 89deg, green 90deg。 - 然后我们更新颜色,使其具有统一的形状
- 最后,我们使用
mask属性内的所有内容!
我们可以从这些步骤中提取两个变量来定义我们的形状:大小 (40px) 和角度 (90deg)。下面是我们如何使用这些变量的占位符来表达。我将使用JavaScript将这些变量替换成它们的最终值。
mask:
linear-gradient(red 0 0) top/100% calc(100% - {size}) no-repeat,
conic-gradient(
from {-angle/2} at bottom,
#0000, #000 1deg {angle - 1} ,#0000 {angle}
) bottom/{size*2*tan(angle/2)} {size} repeat-x;
我们可以为大小和角度使用CSS自定义属性,但三角函数目前是不支持的功能。在未来,我们将能够做这样的事情。
--size: 40px;
--angle: 90deg;
mask:
linear-gradient(red 0 0) top/100% calc(100% - var(--size)) no-repeat,
conic-gradient(
from calc(var(--angle)/-2) at bottom,
#0000, #000 1deg calc(var(--angle) - 1deg), #0000 var(--angle)
) bottom/calc(var(--size)*2*tan(var(--angle)/2)) var(--size) repeat-x;
与底部边框类似,顶部的边框也会有几乎相同的代码,只是做一些调整。
mask:
linear-gradient(red 0 0) bottom/100% calc(100% - {size}) no-repeat,
conic-gradient(
from {180deg - angle/2} at top,
#0000, #000 1deg {angle - 1}, #0000 {angle}
) top/{size*2*tan(angle/2)} {size} repeat-x;
我们把bottom 改为top ,把top 改为bottom ,然后把梯度的旋转更新为180deg - angle/2 ,而不是-angle/2 。 就这么简单!
这就是我们可以用在其他侧面的模式,比如左边。
mask:
linear-gradient(red 0 0) right/calc(100% - {size}) 100% no-repeat,
conic-gradient(
from {90deg - angle/2} at left,
#0000, #000 1deg {angle - 1}, #0000 {angle}
) left/{size} {size*2*tan(angle/2)} repeat-y;
...和右边。
mask:
linear-gradient(red 0 0) left/calc(100% - {size}) 100% no-repeat,
conic-gradient(
from {-90deg - angle/2} at right,
#0000, #000 1deg {angle - 1}, #0000 {angle}
) right/{size} {size*2*tan(angle/2)} repeat-y;
让我们为它们同时应用于两边的时候做边框。我们实际上可以重复使用相同的代码。为了得到顶部和底部的边框,我们简单地结合顶部和底部边框的代码。
我们使用顶部的conic-gradient() ,底部的conic-gradient() ,再加上一个linear-gradient() 来覆盖中间区域。
mask:
linear-gradient(#000 0 0) center/100% calc(100% - {2*size}) no-repeat,
conic-gradient(
from {-angle/2} at bottom,
#0000, #000 1deg {angle - 1},
#0000 {angle}
) bottom/{size*2*tan(angle/2)} {size} repeat-x;
conic-gradient(
from {180deg - angle/2} at top,
#0000, #000 1deg {angle - 1}, #0000 {angle}
) top/{size*2*tan(angle/2)} {size} repeat-x;
在左右两边一起应用边框时也是如此。
mask:
linear-gradient(#000 0 0) center/calc(100% - {2*size}) 100% no-repeat,
conic-gradient(
from {90deg - angle/2} at left,
#0000, #000 1deg {angle - 1}, #0000 {angle}
) left/{size} {size*2*tan(angle/2)} repeat-y,
conic-gradient(
from {-90deg - angle/2} at right,
#0000, #000 1deg {angle - 1}, #0000 {angle}
) right/{size} {size*2*tan(angle/2)} repeat-y;
CodePen Embed Fallback
所以,如果我们想一次将边框应用到所有的侧面,我们将所有的梯度加在一起,对吗?
没错!我们有四个圆锥梯度(即 "L")。我们有四个锥形渐变(每边一个)和一个linear-gradient() 在中间。我们设置了一个等于90deg 的固定角度,因为只有这个角度可以产生更漂亮的角,而不会出现奇怪的重叠。请注意,我也使用了space ,而不是repeat-x 或repeat-y ,以避免像这样的角落的坏结果。
调整一个四边配置的容器的大小
圆形的CSS边框
现在让我们来解决圆角边框的问题!
哦,不!又是一个有很多计算的长篇解释?
一点也不!这里没有什么可解释的。conic-gradient() 我们从 "之 "字形的例子中提取所有内容,然后用radial-gradient() 。这就更容易了,因为我们没有任何角度需要处理--只有尺寸变量。
圆形的CSS边框:
同样,我所做的只是将conic-gradient() (使用尺寸的占位符)。
background:
radial-gradient(circle farthest-side, #0000 98%, #000)
50% calc(100% + {size})/{1.85*size} {2*size} repeat-x
而这是第二个。
background:
radial-gradient(circle farthest-side, #000 98%, #0000)
bottom/{1.85*size} {2*size} repeat-x
1.85和98%这两个神奇数字背后的逻辑是什么?
从逻辑上讲,我们应该使用100% ,而不是98% ,以便有一个接触到背景区域边缘的圆;但同样,这也是抗锯齿问题和那些锯齿状的边缘。我们使用一个稍小的值来防止奇怪的重叠。
1.85 的值更多的是个人的偏好,而不是什么。我最初使用的是2 ,这是获得一个完美圆圈的逻辑值,但结果看起来并不那么好,所以较小的值在圆圈之间创造了一个更无缝的重叠。
这就是区别。
现在,我们需要在其余的边上复制这个方法,就像我们对人字形CSS边框所做的那样。
然而,在一次应用所有四个边时,有一个小的区别。 你会注意到,对于其中一个圆形边框,我只用了一个radial-gradient() ,而不是四个。这是有道理的,因为我们可以用一个梯度在所有的边上重复一个圆形。
这里是最终的CSS。
mask:
linear-gradient(#000 0 0) center/calc(100% - {1.85*size}) calc(100% - {1.85*size}) no-repeat,
radial-gradient(farthest-side,#000 98%,#0000) 0 0/{2*size} {2*size} round;
注意我是如何使用round ,而不是repeat 。这是为了确保我们不会切断任何一个圆圈。还有,1.85 这个值是一个个人偏好的值。
对于另一种类型的圆形边框,我们仍然要使用四个径向渐变,但我不得不引入CSS clip-path属性来纠正边角处的重叠问题。
这是一个八点式的切角路径。
clip-path: polygon(
{2*size} 0,calc(100% - {2*size}) 0,
100% {2*size},100% calc(100% - {2*size}),
calc(100% - {2*size}) 100%,{2*size} 100%,
0 calc(100% - {2*size}),0 {2*size}
);
波浪形的CSS边框
人字形和圆形的CSS边框都需要一个梯度来获得我们想要的形状。那么波浪形的边框呢?这需要两个渐变。下面是一个插图,以了解我们如何用两个径向渐变创造一个波浪。
我们在底部重复这个形状,再加上顶部的线性渐变,我们在底部得到了波浪形的边界。
mask:
linear-gradient(#000 0 0) top/100% calc(100% - {2*size}) no-repeat,
radial-gradient(circle {size} at 75% 100%,#0000 98%,#000) 50% calc(100% - {size})/{4*size} {size} repeat-x,
radial-gradient(circle closest-side at 25% 50%,#000 99%,#0000 101%) bottom/{4*size} {2*size} repeat-x;
我们对其他边做同样的处理,就像我们对之字形和圆形的CSS边框所做的那样。我们只需要更新几个变量,就可以让每一面有不同的波浪。
显示每一面的部分CSS。 你可以在生成器上找到完整的代码。
在所有四边都应用波浪形的CSS边框呢?我们总共会有9个梯度吗?"
不是的,这是因为没有一个在所有四边都应用波浪形边框的演示。我无法找到一种梯度的组合,可以在角落里得到很好的效果。也许读到这篇文章的人知道一个好方法?
这是很有边界的好东西!
所以,你知道我这个很酷的在线CSS边框生成器的来龙去脉了!你可以使用它的代码。当然,你可以使用它吐出的代码并做得很好--但现在你有了使它发挥作用的秘方。
具体来说,我们看到了梯度是如何被用来掩盖一个元素的部分的。然后我们在多个渐变上下功夫,用这些渐变的CSS遮罩做出某些形状。其结果是一个可以沿着元素的边缘使用的图案,创造出花哨的边框,否则你可能会导致background-image 。只是这样一来,只需要交换一些数值就可以改变外观,而不是替换整个光栅图像文件或其他东西。