0

0

使用原生 JavaScript 实现响应式多级下拉菜单(悬停与点击切换)

DDD

DDD

发布时间:2025-09-09 18:37:43

|

568人浏览过

|

来源于php中文网

原创

使用原生 javascript 实现响应式多级下拉菜单(悬停与点击切换)

本文旨在指导开发者使用原生 JavaScript、HTML 和 CSS 构建一个响应式的多级下拉菜单。该菜单在桌面端通过鼠标悬停展开,在移动端则通过点击展开。文章将详细介绍实现思路、代码示例以及注意事项,帮助读者理解并掌握如何在不同设备上提供最佳的用户体验。

HTML 结构

首先,我们需要构建 HTML 结构。一个典型的多级下拉菜单包含一个 div 容器,内部包含一个无序列表 ul,列表项 li 可能包含嵌套的 ul 列表,形成多级菜单。

建议使用 标签包裹菜单项文本,以便添加链接。对于顶级 li 标签,可以考虑使用 标签包裹文本,方便样式控制和语义化。例如:

  • Link
    • Child Link
    • Child Link
  • CSS 样式

    CSS 负责菜单的布局和外观。关键点在于如何实现悬停效果和媒体查询,以便在不同屏幕尺寸下应用不同的样式。

    .menu {
      --menu-height: 40px;
      box-sizing: border-box;
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
    }
    .menu ul {
      list-style: none;
      padding: 16px;
      margin: 0;
    }
    .menu ul li,
    .menu ul li a {
      opacity: 0.8;
      color: #ffffff;
      cursor: pointer;
      transition: 200ms;
      text-decoration: none;
      white-space: nowrap;
      font-weight: 700;
    }
    .menu ul li a,
    .menu ul li a a {
      display: flex;
      align-items: center;
      height: 100%;
      width: 100%;
    }
    .menu ul li {
      padding-right: 36px;
    }
    .menu ul li::before {
      content: "";
      width: 0;
      height: 0;
      border-left: 5px solid transparent;
      border-right: 5px solid transparent;
      border-top: 5px solid #ffa500;
      position: absolute;
      right: 8px;
      top: 50%;
      transform: translateY(-50%);
    }
    .menu ul .link::before {
      padding-right: 0;
      display: none;
    }
    .menu > ul {
      display: flex;
      height: var(--menu-height);
      align-items: center;
      background-color: #000000;
    }
    .menu > ul li {
      position: relative;
      margin: 0 8px;
    }
    .menu > ul li ul {
      visibility: hidden;
      opacity: 0;
      padding: 0;
      min-width: 160px;
      background-color: #333;
      position: absolute;
      top: 45px;
      left: 50%;
      transform: translateX(-50%);
      transition: 200ms;
      transition-delay: 200ms;
    }
    .menu > ul li ul li {
      margin: 0;
      padding: 8px 16px;
      display: flex;
      align-items: center;
      justify-content: flex-start;
      height: 30px;
      padding-right: 40px;
    }
    .menu > ul li ul li::before {
      width: 0;
      height: 0;
      border-top: 5px solid transparent;
      border-bottom: 5px solid transparent;
      border-left: 5px solid #ffa500;
    }
    .menu > ul li ul li ul {
      top: -2%;
      left: 100%;
      transform: translate(0);
    }
    
    .show {
      display: flex;
    }
    
    .hide {
      display: none;
    }
    
    @media screen and (min-width: 1200px) {
      .menu ul li:hover,
      .menu ul li a:hover {
        opacity: 1;
      }
      .menu > ul li ul li:hover {
        background: black;
      }
      .menu > ul li:hover > ul {
        opacity: 1;
        visibility: visible;
        transition-delay: 0ms;
      }
    }
    
    @media screen and (max-width: 1200px) {
      .menu {
        height: 100vh;
        top: 0;
        left: 0;
        width: 20vw;
      }
      .menu ul {
        flex-direction: column;
        height: 100vh;
      }
      .menu ul li {
        margin: 1rem 0;
      }
      .menu ul li ul {
        visibility: hidden;
        opacity: 0;
        padding: 0;
        min-width: 160px;
        background-color: #333;
        position: absolute;
        top: 0px;
        left: 200%;
        transform: translateX(-50%);
        transition: 200ms;
        transition-delay: 200ms;
        height: fit-content;
      }
    }
    
    .menu ul.show { /* 关键代码 */
        visibility: visible;
        opacity: 1;
    }

    关键点:

    立即学习Java免费学习笔记(深入)”;

    • 隐藏子菜单: 默认情况下,使用 visibility: hidden; 和 opacity: 0; 隐藏子菜单。
    • 悬停效果: 在桌面端媒体查询中,使用 :hover 伪类来改变子菜单的 visibility 和 opacity,实现悬停展开效果。
    • 移动端样式: 在移动端媒体查询中,可以调整菜单的布局,例如将其设置为垂直排列
    • .menu ul.show: 这个CSS规则是解决问题的关键。它确保当 show 类被添加到 ul 元素时,该元素的 visibility 和 opacity 属性被正确设置,从而显示子菜单。

    JavaScript 交互

    JavaScript 用于处理移动端的点击事件,实现点击展开/收起子菜单的功能。

    WordAi
    WordAi

    WordAI是一个AI驱动的内容重写平台

    下载
    let menu = document.querySelector(".menu ul");
    menu = menu.children;
    
    for (let i = 0; i < menu.length; i++) {
      console.log(menu[i]);
      menu[i].addEventListener("click", function() {
        menu[i].firstElementChild.classList.toggle("show");
        console.log(menu[i].firstElementChild);
      });
    }

    这段代码遍历顶级菜单项,并为每个菜单项添加点击事件监听器。当点击菜单项时,它会切换其第一个子元素(通常是子菜单 ul)的 show 类。

    改进建议:

    1. 更精确的选择器: 使用更精确的选择器来避免潜在的问题。例如,可以使用 document.querySelectorAll(".menu > ul > li") 来选择顶级菜单项。
    2. 事件委托: 使用事件委托可以提高性能,尤其是在菜单项数量较多时。将事件监听器添加到父元素(例如 .menu ul),然后根据点击的目标元素来判断是否需要展开/收起子菜单。
    3. 判断屏幕尺寸: 在 JavaScript 中判断当前屏幕尺寸,只在移动端应用点击事件处理程序,避免与桌面端的悬停效果冲突。可以使用 window.innerWidth 或 window.matchMedia 来判断屏幕尺寸。

    示例代码(包含改进):

    document.addEventListener('DOMContentLoaded', function() {
        const menu = document.querySelector('.menu ul');
    
        // 仅在移动设备上启用点击事件
        if (window.innerWidth <= 1200) { // 假设1200px是移动端和桌面端的分割点
            menu.addEventListener('click', function(event) {
                const target = event.target;
    
                // 检查点击的是否是顶级菜单项
                if (target.tagName === 'LI' && target.parentElement === menu) {
                    const subMenu = target.querySelector('ul'); // 查找子菜单
    
                    if (subMenu) {
                        event.preventDefault(); // 阻止默认行为(例如,如果菜单项是链接)
                        subMenu.classList.toggle('show'); // 切换 show 类
                    }
                }
            });
        }
    });

    代码解释:

    • document.addEventListener('DOMContentLoaded', function() { ... });:确保在DOM加载完成后执行JavaScript代码。
    • window.innerWidth
    • target.tagName === 'LI' && target.parentElement === menu:检查点击的元素是否是顶级菜单项。
    • target.querySelector('ul'):查找当前菜单项的子菜单。
    • event.preventDefault():阻止默认行为,例如,如果菜单项是一个链接,阻止页面跳转。
    • subMenu.classList.toggle('show'):切换子菜单的 show 类,从而显示或隐藏子菜单。

    总结

    通过 HTML 构建菜单结构,CSS 控制菜单样式和响应式布局,JavaScript 处理移动端的点击交互,我们可以实现一个功能完善、用户体验良好的响应式多级下拉菜单。记住,清晰的结构、合理的样式和简洁的 JavaScript 代码是构建高质量 Web 应用的关键。根据实际需求,你可以进一步优化代码,例如添加动画效果、自定义样式等。

    相关专题

    更多
    js获取数组长度的方法
    js获取数组长度的方法

    在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

    552

    2023.06.20

    js刷新当前页面
    js刷新当前页面

    js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

    374

    2023.07.04

    js四舍五入
    js四舍五入

    js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

    731

    2023.07.04

    js删除节点的方法
    js删除节点的方法

    js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

    476

    2023.09.01

    JavaScript转义字符
    JavaScript转义字符

    JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

    394

    2023.09.04

    js生成随机数的方法
    js生成随机数的方法

    js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

    990

    2023.09.04

    如何启用JavaScript
    如何启用JavaScript

    JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

    656

    2023.09.12

    Js中Symbol类详解
    Js中Symbol类详解

    javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

    551

    2023.09.20

    php与html混编教程大全
    php与html混编教程大全

    本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

    1

    2026.01.13

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    Sass 教程
    Sass 教程

    共14课时 | 0.8万人学习

    Bootstrap 5教程
    Bootstrap 5教程

    共46课时 | 2.9万人学习

    CSS教程
    CSS教程

    共754课时 | 18.7万人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号