• :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函数,可以轻松处理多列的情况。有兴趣可以看看代码:

    掘金code