纯 css 实现一个级联连线效果
1、前言
今天在css学习群里看到一个下图的效果,看到群中讨论如何实现时, 正好之前其实也做过类似的, 就想写个demo在回顾一下
2、思路
看到类似的其实首先就是想到用伪元素去实现左侧的引导线,目的是利用元素自身的两个隐藏的元素, ::before 和 ::after , 来简化dom, 元素能省则省。 所以大致思路就是, 每个子节点(图中片区)通过伪元素的边框设置横向的引导条。 父节点(图中区域)的竖线可以通过盒子的伪元素利用盒子的高度填充
3、实现细节
第一步: 先了解伪元素的用法
其实工作中伪元素的使用非常常见, 就类似这种,前面有个填充线,或者背景图,或者一个定位了一个小icon 都是用这种方式实现
一般我们的伪元素都是相对于元素进行定位的,其实伪元素可以理解为元素的子节点。 元素使用相对定位后, 子元素就可以通过绝对定位,自由的设置相对于该元素的定位位置 第二个重点是,伪元素一定要设置 content 属性, 才会展示出来, 如果不需要值。一般设置为空即可, 设置content的值可以理解为给伪元素增加文字
下面是使用伪元素的demo,先给每个元素通过伪元素在前面增加一个 背景块
<style> .box { position: relative; left: 20%; top: 100px; } .box .ul { list-style: none; position: relative; } ul li { position: relative; } .box li { position: relative; } .box li::before { content: ""; position: absolute; width: 10px; height: 10px; background: #f00; top: 50%; transform: translateY(-50%); left: -15px; } </style> <body> <div class="box"> <div class="ul"> <li>四川区域</li> <li>四川一区</li> <li>四川二区</li> <li>四川三区</li> </div> </div> </body>
这样就轻松使用::before 伪元素实现了每个li 前面增加一个元素背景块
用 浏览器的元素审查工具就是这样的,很明显可以看出来,::before 元素貌似就是li的子元素。 可以选中这个伪元素,在右下所示区域输入样式实时进行调整,调到理想效果后, 然后在复制到代码中保存
第二步: 设置子节点的横向分割线
在设置子节点横向分割线之前, 我们先通过class类对父节点和子节点进行一下区分, 在第一个dom上添加.parent类,下面三个dom节点添加.child类, 然后通过给child 设置margin-left 进行区分
<style> .box .child { margin-left: 30px; } </style> <body> <div class="box"> <div class="ul"> <li class="parent">四川区域</li> <li class="child">四川一区</li> <li class="child">四川二区</li> <li class="child">四川三区</li> </div> </div> </body>
因为li的 ::before 伪元素已经被用成红色的背景块了, 所以设置横线的任务要用::after 来实现了, 有了上面的基础,实现起来就比较简单了, 只需要给 li上 child 类的元素,添加横线
css
复制代码
.box li.child::after { content: ""; position: absolute; width: 24px; height: 1px; background: #000; top: 50%; transform: translateY(-50%); left: -39px; top: 12px; }
效果如下:
此时案例的效果就完成了一半
实现最后一步: 左侧的竖线
实现左侧的竖线,两种思路, 一种是继续用伪元素, 给li.parent增加::after 来设置父元素的竖线, 但是这种情况下,是需要通过js动态计算,子元素的高度,再赋值,其实也有更简单的方式, 直接利用外面的大盒子设置伪元素来设置左侧的竖线, 这样就能利用盒子的高度,不再需要依赖js或者css的计算属性进行计算了
核心代码,给ul设置相对定位, 再给ul设置一个伪元素, 并且设置伪元素的样式
.box .ul { list-style: none; position: relative; } .box .ul::before { content: ""; position: absolute; width: 1px; background: #000; left: -10px; height: calc(100% - 20px); top: 10px; }
效果如下:
这样就完成了上面的案例
最后的动态增删效果如下
4、总结
在工作中实现元素前面有一些额外附加物,比如一些icon、背景区块、 或者背景图、指引线,或者上浮的小文字的时候, 我们经常是通过伪元素进行设置,核心就是先对元素自身增加相对定位, 之后就可以大胆的使用元素自身隐藏的两个伪元素进行设置, 通过都是对伪元素进行绝对定位, 这样伪元素是相对于元素本身进行定位的。 然后设置伪元素的content属性, 有值代表伪元素自身文字,如果不需要文字可以设置为空字符串,这个是必填项
通过伪元素进行设置,可以避免引入更多的dom,产生更多的样式设置。 使用伪元素可以大大减少我们的代码量, 也可以将元素进行集中处理, 类似代码封装一样, 和其他元素进行结偶, 更有利于复用和封装
5、加餐
群里有人问多层级实现
类似这种 多层级 如何没有问题的表现出来,图中就是左侧因为有了三级目录,导致左侧的引导线长度过长了 看到群里有人分享的思路不错
给每一个元素都通过伪元素设置竖线, 在让竖线重合,看起来像一条线, 于是我们根据这种思路进行了实现
效果如下
如图,在这种情况下,确实实现了, 左下的缺角也留出来了, 但是我们增加多些节点,再看看,还能不能实现
我们发现节点多了之后,不再适合,长度不会根据情况自适应填充满。 但是通过观察我们是可以发现,和我们的理想情况相比, 只是最左侧的线没有填充满, 而且有规律可循, 最左侧的线的高度就是,第一层级最后一个元素的高度, 于是我们结合之前的给ul设置伪元素的方式,通过js 给ul的伪元素设置高度, 但是伪元素本身不能直接通过 JavaScript 来操作,但是我们可以给ul设置高度, 那么ul的伪元素高度也会设置上
于是增加一段伪代码