在前端开发中,实现响应式多级菜单是一个常见需求,通常可以用于导航栏、下拉菜单、侧边栏等场景。在本文中,我们将介绍如何使用 JavaScript 实现一个简单的多级菜单,并实现响应式效果,让菜单适应不同设备的屏幕尺寸。
基本结构
在开始编写 JavaScript 代码之前,我们需要先了解多级菜单的基本结构。一个简单的垂直多级菜单通常由以下结构组成:
// www.javascriptcn.com code example
<nav>
<ul>
<li><a href="#">菜单项 1</a>
<ul>
<li><a href="#">子菜单项 1.1</a></li>
<li><a href="#">子菜单项 1.2</a></li>
<li><a href="#">子菜单项 1.3</a></li>
</ul>
</li>
<li><a href="#">菜单项 2</a>
<ul>
<li><a href="#">子菜单项 2.1</a></li>
<li><a href="#">子菜单项 2.2</a></li>
<li><a href="#">子菜单项 2.3</a></li>
</ul>
</li>
<li><a href="#">菜单项 3</a>
<ul>
<li><a href="#">子菜单项 3.1</a></li>
<li><a href="#">子菜单项 3.2</a></li>
<li><a href="#">子菜单项 3.3</a></li>
</ul>
</li>
</ul>
</nav>其中,nav 是一个语义化标签,用于表示页面的导航部分。ul 和 li 标签用于创建有序或无序列表,a 标签则用于表示菜单项和子菜单项的链接。
实现方法
显示与隐藏子菜单
要实现多级菜单,我们需要为菜单项和子菜单项分别添加事件监听器,让菜单在用户触发事件时显示或隐藏对应的子菜单。
在 JavaScript 中,我们可以使用 querySelectorAll 方法选中需要添加事件监听器的元素,然后使用 addEventListener 方法为其添加事件监听器。为了实现多级菜单,我们可以在事件监听器中让子菜单的 display 属性从 none 变为 block,实现子菜单的显示功能。
// www.javascriptcn.com code example
const navItems = document.querySelectorAll('.nav-item')
navItems.forEach((navItem) => {
const subNav = navItem.querySelector('.sub-nav')
navItem.addEventListener('mouseenter', () => {
subNav.style.display = 'block'
})
navItem.addEventListener('mouseleave', () => {
subNav.style.display = 'none'
})
})在上述代码中,我们通过 querySelectorAll 方法选中了所有类名为 .nav-item 的菜单项,然后为其添加了 mouseenter 和 mouseleave 事件监听器。当用户将鼠标悬停在菜单项上时,子菜单的 display 属性为 block,子菜单就会被显示出来。当用户将鼠标离开菜单项时,子菜单的 display 属性又变为 none,子菜单就会被隐藏起来。
响应式布局
在现代 Web 开发中,响应式布局已经成为了标配,因此我们需要让多级菜单能够适应不同的屏幕尺寸。在实现响应式布局时,我们可以使用 CSS 媒体查询,根据不同的屏幕尺寸设置不同的样式。
具体来说,在本例中,我们可以在屏幕宽度小于一定值时隐藏菜单项和子菜单项之间的箭头符号,从而提高菜单的可读性和易用性。以下是示例代码:
@media screen and (max-width: 1200px) {
.nav-item > a:after {
content: none;
}
}在上述代码中,我们使用 @media 媒体查询选择屏幕宽度小于 1200 像素的设备,并对 .nav-item 类下的 a:after 伪元素设置了 content: none;,从而隐藏了箭头符号。
完整代码
以下是本例的完整代码,包括 HTML、CSS 和 JavaScript 部分:
// www.javascriptcn.com code example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Responsive Multilevel Dropdown Menu | HTML & CSS</title>
<style>
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
}
nav {
background-color: #333;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
position: relative;
}
nav ul li {
display: inline-block;
background-color: #333;
}
nav a {
display: block;
padding: 10px 20px;
color: #fff;
font-size: 18px;
text-decoration: none;
font-weight: normal;
}
nav ul ul {
position: absolute;
top: 100%;
left: 0;
background-color: #333;
display: none;
padding: 0;
}
nav ul ul li {
display: block;
width: 100%;
}
nav ul ul a {
padding: 10px 20px;
color: #fff;
font-size: 16px;
text-decoration: none;
font-weight: normal;
}
nav ul ul ul {
position: absolute;
left: 100%;
top: 0;
display: none;
}
.nav-item > a:after {
content: ' ▾';
}
@media screen and (max-width: 1200px) {
.nav-item > a:after {
content: none;
}
nav ul li {
display: block;
}
nav ul ul {
position: static;
background-color: #444;
display: none;
/* Hide the arrows on the second level */
}
nav ul ul li {
display: block;
width: 100%;
}
nav ul ul a {
display: block;
width: 100%;
padding: 0 20px;
}
nav ul ul ul {
position: static;
}
}
/* Hover state for top level links */
nav ul li:hover > a {
background-color: #444;
}
/* Hover state for dropdown links */
.nav-item:hover > .sub-nav li a:hover,
.sub-nav li:hover > a {
background-color: #555 !important;
color: #fff;
}
</style>
</head>
<body>
<nav>
<ul>
<li class="nav-item"><a href="#">Home</a></li>
<li class="nav-item">
<a href="#">Products</a>
<ul class="sub-nav">
<li><a href="#">Product 1</a></li>
<li><a href="#">Product 2</a></li>
<li><a href="#">Product 3</a></li>
<li><a href="#">Product 4</a></li>
<li><a href="#">Product 5</a></li>
</ul>
</li>
<li class="nav-item">
<a href="#">Services</a>
<ul class="sub-nav">
<li><a href="#">Service 1</a></li>
<li>
<a href="#">Service 2</a>
<ul class="sub-nav">
<li><a href="#">Service 2.1</a></li>
<li><a href="#">Service 2.2</a></li>
<li><a href="#">Service 2.3</a></li>
</ul>
</li>
<li><a href="#">Service 3</a></li>
<li><a href="#">Service 4</a></li>
</ul>
</li>
<li class="nav-item"><a href="#">About Us</a></li>
<li class="nav-item"><a href="#">Contact Us</a></li>
</ul>
</nav>
<script>
const navItems = document.querySelectorAll('.nav-item')
navItems.forEach((navItem) => {
const subNav = navItem.querySelector('.sub-nav')
if (subNav) {
navItem.addEventListener('mouseenter', () => {
subNav.style.display = 'block'
})
navItem.addEventListener('mouseleave', () => {
subNav.style.display = 'none'
})
}
})
</script>
</body>
</html>结语
通过本文的介绍,我们了解了如何使用 JavaScript 实现一个简单的响应式多级菜单,并掌握了菜单显示与隐藏、响应式布局等常见技术。希望本文能对你的前端开发实践有所帮助,让你更加熟练地运用 JavaScript 和 CSS 实现更加优雅和实用的 Web 界面。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/6782622e935627c900055a99