前言
需求说明
实现如图效果的S型步骤条:
关键点
首先复习一些要用到的css知识
grid
布局:before
:after
伪元素的应用:nth-child(3n)
css选择器 选择属于其父元素的第3n(3,6,9...)个子元素:last-child
css选择器 选择属于其父元素最后一个子元素calc(2x + 100%)
css 计算属性less
基本用法和函数
实现过程
排列元素
<div class="container">
<div class="item"><div class="step">step1</div></div>
<div class="item"><div class="step">step2</div></div>
<div class="item"><div class="step">step3</div></div>
<div class="item"><div class="step">step4</div></div>
...
</div>
大致效果
step1
step2
step3
step4
...
grid布局
忽略连接线单看步骤,很显然它是一个n行3列的二维宫格样式。我们直接上grid布局,连接线加箭头样式比较简单可以用伪元素定位实现。内部用flex布局使步骤元素居中。
关于grid布局不熟的可以看一看大佬的教程,通俗易懂 CSS Grid 网格布局教程-阮一峰
<div class="grid-container">
<div class="grid-item"><div class="step">step1</div></div>
...
</div>
<style>
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr; // 3列等宽 同: repeat(3, 1fr)
grid-gap: 30px 30px; // 宫格间距
}
.grid-item{
display: flex;
align-items: center;
justify-content: center;
}
</style>
实现效果:
grid布局明细:
伪元素实现步骤间连线
给每个格子右方放置向右的连接线,折行的元素(即3n:3、6、9..)下方加上向下的连接线。
用伪元素:before
和 :after
分别写出连线和箭头样式。
.grid-item {
position: relative;
}
.grid-item::before{
content: '';
position: absolute;
right: -30px;
width: 30px;
height: 0;
border-top: 1px dashed #f00;
}
/** 使用三边border,两边透明,实现三角箭头 */
.grid-item::after{
content: '';
position: absolute;
right: -30px;
border-top: 3px solid transparent;
border-left: 6px solid #f00;
border-bottom: 3px solid transparent;
}
.step{
position: relative;
}
/** 折行元素添加向下的箭头。作为最后一行最后一个子元素则不用添加*/
.grid-item:nth-child(3n):not(:last-child) {
.step::before{
content: '';
position: absolute;
bottom: -30px;
height: 30px;
height: 0;
border-left: 1px dashed #f00;
}
.step::after{
content: '';
position: absolute;
bottom: -30px;
border-top: 6px solid transparent;
border-left: 3px solid #f00;
border-right: 3px solid transparent;
}
}
效果
完成这一步已经实现了流程图的基本结构和元素了,剩下的就是对照UI进行样式变换。
偶数行:元素倒序排列,箭头向左转
当前: 蛇形:
1 2 3 -> 1 2 3
4 5 6 6 5 4
7 8 7 8
对比蛇形走位,可以发现第二行元素(456 -> 654)顺序是反的,再往下也是一行正序一行倒序。
👉 我们只需要将每两行(6个)看做一组,每组第4号和第6号元素交换位置即可。
/** 4号向右平移 2 个 格子+间距,因为格子是等宽的,可以直接用100% */
.grid-item:nth-child(6n + 4) {
transform: translateX(calc(2 * (100% + 30px)));
}
/** 6号则向左平移*/
.grid-item:nth-child(6n) {
transform: translateX(calc(-2 * (100% + 30px)));
}
👉 步骤顺序反过来了,箭头方向自然也得反过来
/** 4、5、6同学,听我口令向左转*/
.grid-item:nth-child(6n + 4),
.grid-item:nth-child(6n + 5),
.grid-item:nth-child(6n) {
&::after {
transform: translateX(25%) rotate(180deg) !important;
}
}
得到
step1 -> step2 -> step3 ->
|
step6 <- step5 <- step4 <-
|
step7 -> step8 ->
隐藏多余的小尾巴
现在看3、4和8号元素后面还赘余着多余的箭头,要把他们删除。找规律:
- 3号、4号:当前蛇形结构最右一列的元素
:nth-child(6n + 3)
、:nth-child(6n + 4)
- 8号:属于奇数行(
6n+1
6n+2
6n+3
)的最后一个元素:last-child
// 去掉最右排箭头
.item:nth-child(6n + 3),
.item:nth-child(6n + 4) {
&::before, &::after {
display: none;
}
}
// 去掉末尾元素箭头。6n+3跟上面重合了所以这里不用写
.item:nth-child(6n + 1),
.item:nth-child(6n + 2) {
&:last-child {
&::before,
&::after {
display: none;
}
}
}
至此,我们就完成了最终效果
less 扩展:如何推演多列情况
我们现在实现了3列,如果要4列、5列呢?其实思路都是一样的。使用less函数,可以轻松处理多列的情况。有兴趣可以看看代码: