在Web前端开发中,树形级联菜单,是一种常见且实用的界面交互组件。它不仅可以提供清晰的导航和大量信息分类展示,还能让用户更方便地进行操作和查询。然而,除了其直观的功能外,树形级联菜单,还可以被用于学习和应用CSS选择器以及CSS技巧。本文将通过代码和实例,分步骤地讲解如何通过树形级联菜单,来理解和运用CSS选择器与CSS技巧。
基本示例
接下来,我们通过上一篇文章的例子,来了解本文的信息点。
HTML
<ul id="tree-menu">
<li><label>Device 1</label>
<ul>
<li><label>Subdevice 1-1</label></li>
<li><label>Subdevice 1-2</label>
<ul>
<li><label>Subdevice 1-2-1</label></li>
<li><label>Subdevice 1-2-2</label></li>
<li><label>Subdevice 1-2-3</label></li>
<li><label>Subdevice 1-2-4</label></li>
<li><label>Subdevice 1-2-5</label></li>
<li><label>Subdevice 1-2-6</label></li>
<li><label>Subdevice 1-2-7</label></li>
<li><label>Subdevice 1-2-8</label></li>
<li><label>Subdevice 1-2-9</label></li>
</ul>
</li>
</ul>
</li>
<li><label>Device 2</label></li>
</ul>
基础样式
CSS
<style type="text/css">
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
/* 默认隐藏子项 */
#tree-menu ul {
display: none;
}
/* 点击节点展开子项 */
#tree-menu li.collapsed>ul {
display: block;
}
</style>
层级样式
CSS
<style type="text/css">
#tree-menu li ul {
padding: 0.5rem 1rem;
}
</style>
边框及选中样式
CSS
<style type="text/css">
#tree-menu li ul {
padding: 0.5rem 1rem;
}
#tree-menu li {
border: 1px solid #ddd;
}
#tree-menu li+li {
border-top: 0;
}
#tree-menu label {
display: block;
padding: 0.5rem 1rem;
}
#tree-menu label:hover {
background-color: aliceblue;
}
</style>
圆角样式1
CSS
<style type="text/css">
#tree-menu li ul {
padding: 0.5rem 1rem;
}
#tree-menu li {
border: 1px solid #ddd;
border-radius: 10px;
margin-bottom:0.5rem;
}
/* #tree-menu li+li {
border-top: 0;
} */
#tree-menu label {
display: block;
padding: 0.5rem 1rem;
}
#tree-menu label:hover {
background-color: aliceblue;
border-radius: 10px;
}
</style>
圆角样式2
li label{ }
这个示例表示:li元素下面所有层级的label
li>label{ }
这个示例表示:li元素孩子级层级的label
CSS
#tree-menu li ul {
padding: 0.5rem 1rem;
}
#tree-menu li {
border: 1px solid #ddd;
/* border-radius: 10px;
margin-bottom:0.5rem; */
}
/* 第一个子节点之后的所有兄弟节点 */
#tree-menu li+li {
border-top: 0;
}
/* 第一个子节点 设置顶部圆角 */
#tree-menu li:first-child,
#tree-menu li:first-child>label {
border-radius: 10px 10px 0 0;
}
/* 最后一个子节点 设置底部圆角 */
#tree-menu li:last-child,
#tree-menu li:last-child>label {
border-radius: 0 0 10px 10px ;
}
/* 只有唯一 一个子节点时,顶部底部都设置圆角 */
#tree-menu li:only-child,
#tree-menu li:only-child>label {
border-radius: 10px ;
}
/*
展开时背景圆角修复
:first-child 第一个子节点
:not(:only-child)非唯一子节点
这里表示这个子节点有子项
*/
#tree-menu li.collapsed:first-child:not(:only-child)>label {
border-radius: 10px 10px 0 0;
}
#tree-menu li.collapsed:not(:only-child)>label {
border-radius: 0;
}
#tree-menu label {
display: block;
padding: 0.5rem 1rem;
}
/*
:hover 鼠标在元素上面时
*/
#tree-menu label:hover {
background-color: aliceblue;
/* border-radius: 10px; */
}
节点标记样式
CSS
#tree-menu li label {
position: relative;
padding: 0.5rem 1rem 0.5rem 1.5rem;
}
/**
如果有子项,添加展开或折叠的标记符号。
默认折叠标记
*/
#tree-menu li label::before {
position: absolute;
content: '-';
left: 0;
width: 1.6rem;
height: 1.2rem;
text-align: center;
line-height: 1.2rem;
color: #333;
}
/**
:only-child表示没有兄弟元素
不显示标记
*/
#tree-menu li label:only-child::before {
content: ' ';
}
/* 显示展开标记 */
#tree-menu li.collapsed>label::before {
content: '+';
}
到此,一个还比较美观的树形菜单,基本完成了。
但是,有朋友说,我要实现以下需求呢?
1、不要边框;
2、保留缩进;
3、保留展开折叠标记;
3、横向拉通选择;
横向拉通选择样式
CSS
#tree-menu label {
position: relative;
display: block;
padding: 0.5rem 1rem;
}
#tree-menu label:hover {
background-color: aliceblue;
}
/** 缩进拉通选择*/
#tree-menu li label {
padding-left: 0;
}
#tree-menu li li label {
padding-left: 0.5rem;
}
#tree-menu li li li label {
padding-left: 1rem;
}
#tree-menu li li li li label {
padding-left: 1.5rem;
}
#tree-menu li li li li li label {
padding-left: 2rem;
}
#tree-menu li li li li li li label {
padding-left: 2.5rem;
}
/**
如果有子项,添加展开或折叠的标记符号。
默认折叠标记
*/
#tree-menu li label::before {
float: left;
content: '-';
width: 1.6rem;
height: 1.2rem;
text-align: center;
line-height: 1.2rem;
color: #333;
}
/**
:only-child表示没有兄弟元素
不显示标记
*/
#tree-menu li label:only-child::before {
content: ' ';
}
/* 显示展开标记 */
#tree-menu li.collapsed>label::before {
content: '+';
}
如果层级很深,我不是得写很多个li才能实现多级缩进?
比如:tree-menu li li li li li li li li li li li label{}
JavaScript方式
查找所有 label 元素,然后看 label 元素上面有多少个 li 元素,以此判断所属层级。
CSS
<script>
function parents(element, selector) {
var parentsArray = [];
var parent = element.parentNode;
while (parent && parent !== document) {
if (parent.matches(selector)) {
parentsArray.push(parent);
}
parent = parent.parentNode;
}
return parentsArray;
}
const items = document.querySelectorAll('#tree-menu label');
items.forEach((item) => {
const level = parents(item.parentElement, 'li').length
const padding = 10 * level;
item.style.paddingLeft = `${padding}px`;
});
</script>
1、我不想写JavaScript;
2、我不想写多个li li li li li li li;
3、我不想写多个.level1{} .level2{} .level3{};
4、我想写少量CSS代码,来解决这个问题,一劳永逸;
5、我想它支持无限层级的缩进;
有这样CSS代码吗?我怎么不知道?
你别说,还真有这样得CSS代码。
当然,这也是本文得重点,算一个CSS得小技巧吧。
counters() 简介
CSS 函数 counters() 是一个嵌套计数器,返回表示指定计数器当前值的连接字符串。counters() 函数有两种形式: counters(name, string) 或 counters(name, string, style) 。它通常和伪元素搭配使用,但是理论上可以在支持<string>值的任何地方使用。生成的文本是具有给定名称的所有计数器的值,从最外层到最内层,之间由指定字符串分隔。计数器以指示的样式呈现,如果未指定样式,则默认为十进制。
先看一个例子:
HTML
<ol>
<li>
<ol>
<li></li>
<li></li>
<li></li>
</ol>
</li>
<li></li>
<li></li>
<li>
<ol>
<li></li>
<li>
<ol>
<li></li>
<li></li>
<li></li>
</ol>
</li>
</ol>
</li>
</ol>
CSS
ol {
counter-reset: listCounter;
}
li {
counter-increment: listCounter;
}
li::marker {
content: counters(listCounter, '.', upper-roman) ') ';
}
li::before {
content: counters(listCounter, ".") " == " counters(listCounter, ".", lower-roman) ;
}
counters() 示例
通过上面的例子,我们看到了类似word的多级列表。此时很多朋友可能已经有思路了,那么我们将利用CSS这个特性,来实现上面的要求。
修改了部分样式
#tree-menu label {
position: relative;
display: block;
/* padding: 0.5rem 1rem; */
padding: 0.5rem 1rem 0.5rem 0;
}
/* #tree-menu li label::before {} */
#tree-menu li label::after {}
/* #tree-menu li label:only-child::before {} */
#tree-menu li label:only-child::after {}
/* #tree-menu li.collapsed>label::before {} */
#tree-menu li.collapsed>label::after {}
counters属性样式
/** 缩进拉通选择 修改前*/
/* #tree-menu li label {
padding-left: 0;
}
#tree-menu li li label {
padding-left: 0.5rem;
}
#tree-menu li li li label {
padding-left: 1rem;
}
#tree-menu li li li li label {
padding-left: 1.5rem;
}
#tree-menu li li li li li label {
padding-left: 2rem;
}
#tree-menu li li li li li li label {
padding-left: 2.5rem;
} */
/* 修改后 */
#tree-menu,
#tree-menu ul {
counter-reset: listCounter;
}
#tree-menu label {
counter-increment: listCounter;
}
#tree-menu label::before {
float: left;
/* 把标记设置成透明 */
color:transparent;
/* 默认数字*/
content: counters(listCounter, "");
}
完整的CSS
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
/**
折叠状态与展开状态样的样式
*/
#tree-menu ul {
display: none;
}
#tree-menu li.collapsed>ul {
display: block;
}
#tree-menu label {
position: relative;
display: block;
padding: 0.5rem 1rem 0.5rem 0;
}
#tree-menu label:hover {
background-color: aliceblue;
}
/** 缩进拉通选择*/
/* 修改后 */
#tree-menu,
#tree-menu ul {
counter-reset: listCounter;
}
#tree-menu label {
counter-increment: listCounter;
}
#tree-menu label::before {
float: left;
/* 将序号设置为透明 */
color:transparent;
/***/
content: counters(listCounter, "");
}
/**
如果有子项,添加展开或折叠的标记符号。
默认折叠标记
*/
#tree-menu li label::after {
float: left;
content: '-';
width: 1.6rem;
height: 1.2rem;
text-align: center;
line-height: 1.2rem;
color: #333;
}
/**
:only-child表示没有兄弟元素
不显示标记
*/
#tree-menu li label:only-child::after {
content: ' ';
}
/* 显示展开标记 */
#tree-menu li.collapsed>label::after {
content: '+';
}
通过树形级联菜单,学习CSS选择器与CSS技巧,是一种非常有效的学习方法。我们不仅可以学会如何使用各种选择器,来控制页面元素,还能掌握一些实用的CSS技巧和概念。希望本文对您了解树形级联菜单、CSS选择器和CSS技巧有所帮助,并能为您在Web前端开发中的工作提供一些启发。
希望本文能够对您有所帮助,感谢您的阅读!
人人为我,我为人人,谢谢您的浏览,我们一起加油吧。