当前位置: 首页 > Web前端 > CSS

CSS如何处理多级菜单的内边距

时间:2023-03-31 13:52:59 CSS

原文地址,排版更好https://blog.codelabo.cn/article/5ce4f0eb8aab210ff34d0150https://xboxyan.codelabo.cn/post/css-tree-padding/中平时的项目,我们经常会遇到这样的布局,姑且称之为多级菜单吧(截图来自ant-design)。这种布局也很容易,大概是这样的,ul和li是嵌套的,如下

  • Navigation01
    • Option01
    • Option02
    • 子菜单
      • Option03
      • Option04
  • Navigation02
  • 所以你得到以下非常原始的风格。经过简单的修改,就可以达到上面的效果。当然,这很容易。一般来说,我们通过设置内边距来实现。例如,默认为ul{padding-left:40px;}。然后每一层都随着父层逐渐积累,然后实现。层次越深,从左边缩进的效果越多。通过上面的布局和样式,可以明显看出每一项的选择范围是逐渐缩进的。但是,设计者可能觉得不好看,所以往往设计成栏目形式,比如上面的ant-design那么,如何处理呢?首先,一个很自然的想法是去掉ul的padding,而是为每个子项指定paddingul.parent{padding:0;},然后直接在html上写内边距,如下
  • Navigation01
    • Option01
  • Option02
  • 子菜单
  • Navigation02</div>
  • 如果菜单层级比较多,我们一般会使用js来辅助生成。请注意,为每个循环指定不同的内边距就足够了。ant-design也采用了这种方式。可以自己打开控制台查看,记得刚进入前端时采用了这个方法,效果就出来了。不过,现在看来,在html中使用内联样式总是不雅的,数量多的时候,就需要跟js相关了。你能优化它吗?这里有两种css方法:1.我们可以在上面使用子选择器的基础上,分别控制每一层的padding,这里我们可以先使用子选择器>ul.parent>li>div{/**level**/padding-left:40px;}ul.parent>li>ul>li>div{/**secondlevel**/padding-left:80px;}ul.parent>li>ul>li>ul>li>div{/**thirdlevel**/padding-left:120px;}/**...**/通常在层数不多的时候,我们可以一层一层的列出来,使用选择器即可ul>li来叠加,是不是比style维护方便很多?2.absolute半依赖定位在说这个方法之前,先搞清楚一个问题,当absolute没有设置方向属性left,top,right,bottom时,默认位置在哪里?在我的学习过程中,很多地方都说absolute就是绝对定位,相对于第一个有定位属性的parent,所以基本都是和relative一起使用的,反正不管发生什么一个,给parent加上position:relative就可以了直接说,有靠谱的父母,就更靠谱了不是吗?事实上,当元素设置了absolute属性而没有设置方向属性时,元素仍然在原来的位置,但不占用空间。比如我给上面的每一项都加了一个角标。ul.parentdiv:after{content:'new';字体大小:10px;位置:绝对;边距顶部:-5px;color:red}可以看出,虽然设置了absolute属性,但是元素还是保持在原来的位置。一旦设置了方向属性(例如左),就会找到具有定位属性的第一个父级。现在,我们把css恢复到默认状态,即ul{padding-left:40px;}现在情况和初始状态一致,选中范围逐层递减。那么,如何将选中的范围实现为一列呢?我们可以给最外层parent设置position:relative,因为banner的宽度是相对于最外层的,然后设置ul.parentdiv:hover:before{content:'';位置:绝对;左:0;right:0代表被选元素;高度:21px;背景:紫色;z-index:-1;}这里只设置了水平左右,没有设置垂直属性,所以水平位置会跟随父定位元素(这里是最外层的Layer),垂直位置还是以当前父级(这里是父级li元素)。注意这里的高度是基于最外层元素的,所以这里不能设置height:100%,那么怎么解决这个小瑕疵呢,毕竟这里写一个固定的高度不是很合适。这里有两种优化方式。方法一如果上面的方法没有指定高度,既然没有内容,高度自然为0,解决方法也很简单,在内容ul.parentdiv中插入一个空字符或者透明字符即可:hover:before{content:'\A0';}或者ul.parentdiv:hover:before{content:'anycharacter';color:transparent;}方法二通常子项的高度是固定的,可以手动给子项指定一个高度,然后选择要继承的项高度可以是ul.parentdiv{height:24px;line-height:24px;}ul.parentdiv:hover:before{content:'';height:inherit}注意这里的height:inherit是继承自直接父Height,有兴趣的可以看看张新旭的这篇文章,同样实现了banner的效果https://codepen.io/xboxyan/pe...上一节介绍了实现banner的两种方法。相比较而言,absolute的效果更好,而且易于维护。可能是一个不太起眼的属性,有时候却能起到意想不到的效果。这里有一个案例,纯css实现,可以查看https://codepen.io/xboxyan/pe...