我最近遇到了一个有趣的切片光盘设计。 圆盘有一个对角线渐变,并被分成水平的切片,从左到右有些偏移。 自然地,我开始思考用CSS做到这一点的最有效方法是什么。
![屏幕截图。显示对角渐变光盘,该光盘已被分成八个水平切片,一个在另一个切片上,在它们之间有微小的间隙,并且根据奇偶校验在左右方向上略有偏移(相对于光盘的垂直轴)。](https://i-blog.csdnimg.cn/blog_migrate/9d830ed65f54ef719482bc06bcb5b32d.png)
首先想到的是,这应该可以在border-radius
,对吗? 好吧,不! 具有border-radius
的东西是它创建了一个椭圆形的角,其末端与所连接的边缘相切 。
我的第二个想法是使用circle()
剪切路径。 好吧,事实证明此解决方案就像一个魅力,因此让我们仔细看看吧!
请注意,以下示例无法在Edge中使用,因为Edge尚不支持HTML元素上的clip-path
。 都可以使用带有overflow: hidden
嵌套元素来模拟它overflow: hidden
以便具有跨浏览器的支持,但是为了简单起见,我们在本文中剖析了clip-path
方法。
将光盘切成相等的部分
就HTML结构而言,我们使用预处理器生成该结构以避免重复。 首先,我们确定多个切片n
。 然后,我们将此数字作为自定义属性--n
传递给CSS。 最后,我们循环生成切片,将每个切片的索引作为另一个自定义属性--i
传递给CSS。
- var n = 8;
style :root { --n: #{n} }
- for(var i = 0; i < n; i++)
.slice(style=`--i: ${i}`)
转到CSS,我们首先确定光盘的直径$d
。 这是切片的width
。 height
是直径除以项目数量calc(#{$d}/var(--n))
。
为了能够区分它们,我们为切片提供了由奇偶校验确定的虚拟背景。
$d: 20em;
.slice {
--parity: 0;
width: $d;
height: calc(#{$d}/var(--n));
background: hsl(36, calc(var(--parity)*100%), calc(80% - var(--parity)*30%));
&:nth-of-type(2n) { --parity: 1 }
}
我们还将切片放在容器的中间(在本例中为body
在其中间放置一个列flex
布局。
见笔由thebabydino( @thebabydino )上CodePen 。
为了获得圆盘形状,我们使用一个circle()
剪切路径,其半径$r
等于直径.5*$d
一半,并且中心点位于装配的中间。 由于我们在切片上设置了此clip-path
,因此每个切片的中心点的位置都相对于切片本身。
在水平方向上,它始终位于切片的50%
的中间。 垂直方向,它需要位于程序集的中间,因此这是我们作为预处理器代码中CSS变量传递的项目总数和项目索引的地方。
在组件的中间是指距组件顶部一半的高度。 组件高度的一半是直径.5*$d
一半,它等于半径$r
。 但是此值是相对于整个程序集的,因此我们需要一个相对于当前切片的值。 为了得到这个,我们减去当前切片相对于装配的垂直位置,即当前切片的顶部相对于装配的顶部的距离。
第一个切片(索引--i: 0
)位于程序集的最顶部,因此在这种情况下我们减去的量为0
。
第二个切片(索引为--i: 1
)位于距程序集顶部一个切片的高度(第一个切片占用的空间),因此在这种情况下,我们减去的量为1
切片高度。
第三个切片(索引为--i: 2
)位于距程序集顶部两个切片的高度处(第一和第二切片占用的空间),因此在这种情况下,我们减去的量为2
切片高度。
在一般情况下,我们为每个切片减去的量是切片的索引( --i
)乘以一个切片的height
。
--h: calc(#{d}/var(--n)); /* slice height */
clip-path: circle($r at 50% calc(#{$r} - var(--i)*var(--h))
见笔由thebabydino( @thebabydino )上CodePen 。
完成此操作后,我们可以基于奇偶校验偏移切片。
--sign: calc(1 - 2*var(--parity));
transform: translate(calc(var(--sign)*2%))
现在我们有了切片的碟片!
见笔由thebabydino( @thebabydino )上CodePen 。
切开切片
这里首先想到的是在每个切片上使用margin
。
见笔由thebabydino( @thebabydino )上CodePen 。
在某些情况下,这可能是一个很好的结果,但是如果我们不希望光盘拉长怎么办?
好吧,我们可以选择将background
限制为content-box
并添加垂直padding
:
box-sizing: border-box;
padding: .125em 0;
background: hsl(36, calc(var(--parity)*100%), calc(80% - var(--parity)*30%))
content-box;
当然,在这种情况下,我们需要确保将box-sizing
设置为border-box
以便垂直padding
不会增加到height
。