前端左侧菜单列表怎么写
这里给大家分享一个一级和一个二级菜单路径的实现,一般工作只就够用了,多级菜单就是在二级菜单的基础上再写一层。并且实际开发中不可能当你再菜单路径上无限扩展,这又不是短视频的评论,就算短视频的评论也只是以二级路径一级展示父子关系实现而已
一级基础菜单
html代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><!-- 自动适配页面宽度,初始可视化比例为正常的原始大小--><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>基础左侧菜单</title><link rel="stylesheet" href="../css/bash_list.css"><!-- 使用Font Awesome图标 --><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
</head>
<body><div class="sidebar"><div class="menu-title"><i class="fas fa-bars"></i><span>导航菜单</span></div><ul class="menu-list"><li class="menu-item active"><i class="fas fa-home"></i><span>首页</span></li><li class="menu-item"><i class="fas fa-user"></i><span>个人中心</span></li><li class="menu-item"><i class="fas fa-envelope"></i><span>消息</span></li><li class="menu-item"><i class="fas fa-cog"></i><span>设置</span></li><li class="menu-item"><i class="fas fa-chart-bar"></i><span>数据分析</span></li><li class="menu-item"><i class="fas fa-shopping-cart"></i><span>购物车</span></li><li class="menu-item"><i class="fas fa-history"></i><span>历史记录</span></li><li class="menu-item"><i class="fas fa-question-circle"></i><span>帮助中心</span></li></ul>
</div><!-- 内容区域 -->
<main class="content"><h1>左侧菜单实现示例</h1><p>这是一个基础左侧菜单的实现,适合前端初学者学习。菜单项使用Font Awesome图标增强视觉效果,并添加了悬停高亮效果。</p><p>点击左侧菜单项可以查看交互效果(当前已选中"首页")。</p>
</main><script>// 用原生语法给所有li标签一个点击事件,删除现在的active标签,给当前对象的class数据加上activedocument.querySelectorAll('.menu-item').forEach(item => {item.addEventListener('click', function() {// 移除所有active类document.querySelectorAll('.menu-item').forEach(i => {i.classList.remove('active');});// 为当前项添加active类this.classList.add('active');});});
</script>
</body>
</html>
css样式
/*
取消页面上的默认内、外边距
box-sizing: border-box; 设置所有元素的宽高尺寸在设置是包含了内外边距的大小,无需额外操心计算
font-family 设置字体*/
* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Microsoft YaHei', sans-serif;
}/*
给 body 整体设置为弹性布局盒子,因为菜单和主内容是两个要同行展示的块内容
就不需要旧标准的浮动了,而且弹性布局下它们已经失效了
给一个初始状态的最小高度为当前可视化视图的100%(vh意思是当前可视化视图的对象单位),不然页面就塌掉了
默认给一个偏乳白色的背景*/
body {display: flex;min-height: 100vh;background-color: #f5f7fa;
}/* 菜单容器样式
背景色设置为偏藏青的颜色
文字为白色
box-shadow给了一个阴影效果,垂直和水平不偏移,模糊15像素,扩展也为0,颜色轻度灰色
但其实这个效果不细看不明显,主要是防止边缘太硬
对 y 轴的内容溢出展示进度条
*/
.sidebar {width: 30vh;background: linear-gradient(135deg, #2c3e50, #1a2530);color: #fff;box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.1);overflow-y: auto;
}/* 菜单标题 , 是一个单独的div
设置文字大小、加粗、标题盒子的内边距
下边框做分界线
随后设置为弹性布局,并设置弹性布局子元素垂直方向居中,好处是不会出现山坡状的上下抖动*/
.menu-title {padding: 20px;font-size: 18px;font-weight: bold;border-bottom: 1px solid rgba(255, 255, 255, 0.1);display: flex;align-items: center;
}/*
Font Awesome图标 的大小以及左侧留白*/
.menu-title i {margin-right: 10px;font-size: 20px;
}/* 菜单列表
主体是一个无序列表,设置list-style把默认的所有样式取消
给上下内边距为10px 和标题的盒子隔开
*/
.menu-list {list-style: none;padding: 10px 0;
}/* 菜单项本身是ul 中的 li内边距控制舒适的视觉位置和菜单标题一样用弹性盒子居中transition用来设置所有状态的变化以匀速的动画效果运行,过渡用时0.3秒,而不是硬性的直接改变给一个4px的左侧完全透明的边框,这里是为了占位,你可以调大这个边框大小,配合激活时在减小,做一个突出效果cursor: pointer; 是鼠标放上去变小手*/
.menu-item {padding: 14px 20px;display: flex;align-items: center;transition: all 0.3s ease;cursor: pointer;border-left: 4px solid transparent;
}/*
所有菜单项的图标给一个视觉效果*/
.menu-item i {margin-right: 12px;font-size: 18px;width: 24px;text-align: center;
}/* 菜单项悬停效果背景和左侧边框变色*/
.menu-item:hover {background-color: rgba(255, 255, 255, 0.1);border-left: 4px solid #3498db;
}/* 激活状态
这里的active并不是一个单独的子类选择器
而是一个复合选择器,表示li自身为active的标签
*/
.menu-item.active {background-color: rgba(52, 152, 219, 0.2);border-left: 4px solid #3498db;
}/* 内容区域
这里的flex并不是弹性盒子的意思
而是让内容的盒子,直接占据剩余的空间,就达到了body弹性布局的背景下
渲染完主菜单盒子,其他的可视化大小都给主内容盒子*/
.content {flex: 1;padding: 30px;
}h1 {color: #2c3e50;margin-bottom: 20px;
}p {line-height: 1.6;color: #555;
}
二级菜单
html代码
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>可展开式菜单</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css"><link rel="stylesheet" href="../css/bash_list_clid.css">
</head>
<body>
<!-- 左侧菜单 -->
<nav class="sidebar"><div class="menu-title"><i class="fas fa-bars"></i><span>导航菜单</span></div><ul class="menu-list"><li class="menu-item no-clid active"><div class="menu-item-content"><i class="fas fa-home"></i><span>首页</span></div></li><li class="menu-item have-clid" onclick="toggleSubmenu(this)"><div class="menu-item-content"><i class="fas fa-user"></i><span>用户管理</span></div><i class="fas fa-chevron-right arrow"></i></li><ul class="submenu"><li class="submenu-item no-clid"><i class="fas fa-user-plus"></i><span>添加用户</span></li><li class="submenu-item no-clid"><i class="fas fa-users"></i><span>用户列表</span></li><li class="submenu-item no-clid"><i class="fas fa-user-cog"></i><span>权限设置</span></li><li class="submenu-item no-clid"><i class="fas fa-user-shield"></i><span>管理员</span></li><li class="submenu-item no-clid"><i class="fas fa-user-times"></i><span>禁用用户</span></li></ul><li class="menu-item have-clid" onclick="toggleSubmenu(this)"><div class="menu-item-content"><i class="fas fa-shopping-cart"></i><span>商品管理</span></div><i class="fas fa-chevron-right arrow"></i></li><ul class="submenu"><li class="submenu-item no-clid"><i class="fas fa-box-open"></i><span>商品列表</span></li><li class="submenu-item no-clid"><i class="fas fa-tags"></i><span>分类管理</span></li><li class="submenu-item no-clid"><i class="fas fa-chart-line"></i><span>销售统计</span></li></ul><li class="menu-item have-clid" onclick="toggleSubmenu(this)"><div class="menu-item-content"><i class="fas fa-cog"></i><span>系统设置</span></div><i class="fas fa-chevron-right arrow"></i></li><ul class="submenu"><li class="submenu-item no-clid"><i class="fas fa-sliders-h"></i><span>基本设置</span></li><li class="submenu-item no-clid"><i class="fas fa-database"></i><span>数据管理</span></li><li class="submenu-item no-clid"><i class="fas fa-shield-alt"></i><span>安全设置</span></li></ul></ul>
</nav><!-- 内容区域 -->
<main class="content"><h1>平滑展开菜单解决方案</h1><p>这里只展示了二级路径的菜单,一般都够用了,实际开发中也不可能无限的扩展下去,最多三级</p><p>多级目录就是把 submenu 属性涉及到的样式在写一套,用submenu1、submenu2这种方式区分开就行</p>
</main><script>/*有二级路径的父路径,展开时的点击事件*/function toggleSubmenu(element) {//获取下一个同位元素,也就是同一级别的下一个,正好时子路径列表的 ulconst submenu = element.nextElementSibling;//获取当前菜单路径所在li中的箭头const arrow = element.querySelector('.arrow');//如果携带有expanded属性,意味着当前点击的是一个展开的路径,则移除展开属性if (submenu.classList.contains('expanded')) {/*必须手动先让最大高为 0不然直接删除expanded其实状态就丢了,动画效果也就不触发了,结果就是子路径收不回去css的动画讲究的是可见且有不一样的起始和结束值所以如果直接删除expanded,动画看到的就是起始0px,结束也是0px,添加也是同样的道理说白了,这里的expanded就相当于只是个标记而已,css那些定义的没有实际作用*/submenu.style.maxHeight = '0';submenu.classList.remove('expanded');} else {// 反之展开菜单submenu.classList.add('expanded');// scrollHeight 可以获取到元素不受隐藏时的最大高宽度submenu.style.maxHeight = submenu.scrollHeight + 'px';}//toggle的作用是如有属性则删除,没有则添加arrow.classList.toggle('rotated');element.classList.toggle('active');}/*所有无子菜单的 li 标签 的点击事件*/document.querySelectorAll('.no-clid').forEach(item => {item.addEventListener('click',function () {// 移除所有无子路径的目录,他们的active属性document.querySelectorAll('.no-clid').forEach(i => {i.classList.remove('active');});// 为当前项添加active类this.classList.add('active');})})</script>
</body>
</html>
css样式
* {margin: 0;padding: 0;box-sizing: border-box;font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}body {display: flex;min-height: 100vh;background-color: #f5f7fa;
}/* 菜单样式 */
.sidebar {width: 30vh;background: linear-gradient(135deg, #2c3e50, #1a2530);color: #fff;box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.1);overflow-y: auto;
}/*
justify-content: center; 是x轴水平居中,按需加
一般有align-items: center; 基础的y轴上水平居中就可以了,没有这个图标和文字会出现高低肩*/
.menu-title {padding: 20px;font-size: 18px;font-weight: bold;border-bottom: 1px solid rgba(255, 255, 255, 0.1);display: flex;align-items: center;justify-content: center;
}.menu-title i {margin-right: 10px;margin-top: 2px;font-size: 20px;
}.menu-list {list-style: none;padding: 10px 0;
}.menu-item {padding: 14px 20px;display: flex;align-items: center;justify-content: space-between;transition: all 0.3s ease;cursor: pointer;border-left: 4px solid transparent;
}.menu-item:hover {background-color: rgba(255, 255, 255, 0.1);border-left: 4px solid #3498db;
}.menu-item.active {background-color: rgba(52, 152, 219, 0.2);border-left: 4px solid #3498db;
}/*
和基础一级菜单目录不一样的是,二级菜单内部是一个弹性布局盒子
不过这个盒子不用设置宽高*/
.menu-item-content {display: flex;align-items: center;
}/*
所有li中所有的i标签和基础的菜单一样,给一个合适的宽和右外边距
这个外边距其实不给,只用弹性布局下所有子元素都变成行内块元素后的宽加上文字水平(x轴)水平对其也可以*/
.menu-item i {margin-right: 12px;font-size: 18px;width: 24px;text-align: center;
}/*
重置展开箭头的 transform 属性动画,这里实际属性还是和父li中的一样
如果有需要可以自己该*/
.arrow {transition: transform 0.3s ease;font-size: 14px;
}/*
这里准备一个点击当前目录展开时的箭头动作,顺时针旋转90度*/
.arrow.rotated {transform: rotate(90deg);
}/* 子菜单样式,注意-子菜单本身是个 ul 收到父 ul 的影响继承里默认样式为空的css属性max-height: 0;使得子菜单默认不占位置高度空间
overflow: hidden;配合这个可以让最大高度为零时,舍弃超出部分,达到默认隐藏子路径的效果
transition重置定义最大高度变化效果,使用了贝塞尔曲线
*/
.submenu {max-height: 0;overflow: hidden;transition: max-height 0.4s cubic-bezier(0.4, 0, 0.2, 1);background: rgba(0, 0, 0, 0.15);
}/* 和上面展开箭头一样这里准备一个当前目录展开时的子目录最大高度注意这里的500px没有实际作用,js代码里你会知道为什么的*/
.submenu.expanded {max-height: 500px;
}/*
和父 ul 的所有 li 一样,子菜单的 li 也要有合理的类似属性*/
.submenu-item {padding: 12px 20px 12px 50px;display: flex;align-items: center;transition: all 0.3s ease;cursor: pointer;border-left: 4px solid transparent;
}/*
子菜单鼠标悬浮和选择样式一致*/
.submenu-item:hover,.submenu-item.active {background-color: rgba(255, 255, 255, 0.08);border-left: 4px solid #2ecc71;
}/*
opacity: 0.7; 的目的是让子菜单的图标透明30%,显得有层次感*/
.submenu-item i {margin-right: 10px;font-size: 14px;opacity: 0.7;
}/* 内容区域 */
.content {flex: 1;padding: 30px;
}h1 {color: #2c3e50;margin-bottom: 20px;padding-bottom: 15px;border-bottom: 2px solid #f1f1f1;
}p {line-height: 1.6;color: #555;margin-bottom: 15px;
}