☰
HTML菜单源码实战指南:从结构设计到响应式与避坑优化
2026/10/14 4:29:12 网站建设 项目流程

简介:面向网页开发者与前端初学者的HTML菜单源码集合,重点解决导航菜单的视觉呈现与交互反馈,可快速套用于企业官网、个人博客、管理后台以及活动专题页等常见场景。RAR压缩包共38个文件、约481KB,构成上包含13个LESS与13个SCSS样式源文件、2个CSS编译样式、3个JS脚本,以及OTF、WOFF2、TTF、EOT、SVG、WOFF等字体资源,既有可直接打开的示例页面,也保留了便于二次开发与重新编译的样式源文件。目前已有2595人浏览学习,说明这类菜单源码在组件设计层面具备不错的参考热度。示例HTML能直观展示菜单的层级结构与基本用法,JS和jQuery脚本则覆盖下拉、折叠、悬停、点击切换等常见交互逻辑;LESS和SCSS文件支持通过变量与混合宏统一调整风格、色彩和尺寸,字体文件对应菜单中的图标展示,整体代码组织清晰,便于嵌入现有项目或进一步拆分学习。对希望提升前端界面表现力、快速搭建带图标菜单的开发者而言,这套源码同时提供了设计思路和可直接复用的基础代码。

1. 超实用漂亮精美 HTML 菜单源码:别再把菜单做成没人点的摆设

做前端这么久,我见过太多产品死在不痛不痒的菜单上——信息层级混乱、动效僵硬、移动端点不准,用户进来三秒就退。你搜“超实用漂亮精美HTML菜单源码”,真正想要的不是一堆花架子 Demo,而是一套能直接塞进项目、能改参数、能扛住多端适配的菜单方案。这篇我按自己平时落地项目的习惯,把菜单从导航结构设计、样式动效、响应式处理到性能优化和踩坑排查完整过一遍,代码都能直接抄,参数含义和坑点我会讲透。不管你是新手照着改,还是熟手要找边界和优化思路,这篇文章都按一线项目的标准来写。


2. 菜单结构设计:先定信息架构,再谈漂亮与精美

2.1 为什么菜单第一步是分类,而不是写 CSS

拿到“HTML菜单源码”,很多人上来就翻 CSS 找渐变和阴影,这是本末倒置。菜单的本质是导航,导航的核心是让用户在三秒内知道“我在哪、能去哪”。如果栏目超过七个、命名含糊、层级超过三级,再漂亮的样式都是在给用户添堵。我一般会先拿一张纸,把产品的核心任务拆成主菜单项,主菜单项控制在五个到七个之间,每个项下的子菜单最多两级,再多就说明产品信息架构本身有问题,应该先做内容整合,而不是靠菜单硬塞。

这个阶段要用到的 HTML 结构非常简单,一个外层导航容器,内部是列表,列表项里可以嵌套子列表。语义化标签nav和ul/li是标配,既方便搜索引擎理解页面结构,也对屏幕阅读器友好。用一堆div拼菜单是新手常见做法,后期改样式和做无障碍适配都会很痛苦。注意菜单里的文字要短而准确,比如“产品中心”比“我们的产品与服务”好一百倍。

<nav class="main-nav"> <ul class="menu"> <li class="menu-item"> <a href="#">首页</a> </li> <li class="menu-item has-submenu"> <a href="#">产品</a> <ul class="submenu"> <li><a href="#">分类一</a></li> <li><a href="#">分类二</a></li> </ul> </li> <li class="menu-item"><a href="#">关于</a></li> <li class="menu-item"><a href="#">联系</a></li> </ul> </nav>

这段结构里has-submenu是给有子菜单的项加的标记类,CSS 和 JS 都要靠它来定位。子菜单的ul.submenu默认要隐藏,鼠标悬停或点击时再展开。这样写的好处是,即使 JS 加载失败,用户依然能看到完整的菜单列表,只是没有展开收起的功能,这在极端弱网环境下是个保底方案。很多源码直接把子菜单用display:none永久藏掉,JS 失效就彻底找不着入口,这属于典型翻车设计。

2.2 扁平菜单、下拉菜单、手风琴菜单:怎么选才不后悔

市面上所谓“超实用漂亮精美HTML菜单源码”花样很多,但底层无非三种交互模式。扁平菜单适合栏目少、层级浅的官网首页,所有入口平铺,用户一眼扫完;下拉菜单适合信息量大、需要收纳二级或三级栏目的后台系统,鼠标悬停展开,节省水平空间;手风琴菜单适合移动端或侧边栏场景,点击展开一组、收起其他组,避免页面纵向过长。

我的选择逻辑很简单:看内容层级数量。层级不超过两层、栏目少于七个,选扁平;有三级以上内容,选下拉;需要在一屏内展示多个分组且空间紧张,选手风琴。硬要把后台系统的权限菜单做成扁平,结果是横向滚动条满天飞;把官网首页做成手风琴,用户根本不知道还有内容藏在折叠里。三种模式的 HTML 基础结构其实是同一套,只是 CSS 和 JS 的交互逻辑不同,所以抄源码时先分清它属于哪一类,再判断适不适合你的项目。

下拉菜单最常见的坑是鼠标从主菜单移到子菜单时,子菜单突然消失。原因是主菜单和子菜单之间存在空隙,鼠标一离开触发区域就触发mouseleave。解决思路是用 CSS 的:hover配合在子菜单上补一段透明的 padding 或者用 JS 加延迟关闭,后面排查章节我会给具体代码。手风琴菜单的坑是状态管理混乱——展开多个面板、或点击当前展开的面板不能正确收起,本质是没有维护好手风琴的“当前活跃项”标识。


3. 从零手写精美菜单:HTML + CSS + JS 完整方案与参数说明

3.1 基础样式:让菜单先“干净好看”

HTML 结构搭好后,下一步是样式。很多人直接找现成源码里的 CSS 大段粘贴,结果发现菜单和自家页面风格格格不入。我习惯从一份干净的基础样式开始,先定间距、字体、颜色、圆角和阴影,把菜单做成“中性好看”的状态,再根据项目视觉去微调。这样既不会让菜单显得突兀,改动成本也低。

.main-nav { background: #fff; border-bottom: 1px solid #e8e8e8; padding: 0 24px; } .menu { list-style: none; margin: 0; padding: 0; display: flex; gap: 8px; } .menu-item { position: relative; } .menu-item > a { display: block; padding: 14px 16px; color: #333; text-decoration: none; font-size: 15px; transition: color 0.2s ease; } .menu-item > a:hover, .menu-item > a:focus-visible { color: #1677ff; } .submenu { position: absolute; top: 100%; left: 0; min-width: 180px; background: #fff; border: 1px solid #e8e8e8; border-radius: 8px; box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08); padding: 6px 0; list-style: none; opacity: 0; transform: translateY(8px); transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s; z-index: 10; }

上面用flex让菜单项横向排列,gap控制项间距,position: relative给子菜单做绝对定位的参照。子菜单用了opacity、transform和visibility三个属性组合实现淡入加轻微位移效果,位移 8px 是视觉上比较舒服的量,太小没动感,太大显得拖沓。z-index: 10防止子菜单被页面其他定位元素盖住,这个参数在实际项目中经常要调,页面里有弹窗、轮播图时很容易踩坑,后文排查部分会展开说。

3.2 悬停与点击展开:给菜单注入交互灵魂

只用 CSS 的:hover就能实现下拉菜单的基本展开收起,这也是最简单可靠的做法。推荐在子菜单上预先加一段透明的padding-top或者用::before伪元素做成桥梁,消除鼠标移动路径上的空隙。

.menu-item:hover > .submenu { opacity: 1; transform: translateY(0); visibility: visible; } .submenu::before { content: ""; position: absolute; top: -12px; left: 0; right: 0; height: 12px; }

注意submenu用了visibility: hidden而不是display: none,这是关键细节。visibility: hidden保留元素占位且无法响应鼠标事件,配合transition可以做出平滑的淡入淡出;display: none则无法过渡,会出现生硬的闪现。伪元素::before是透明热区,鼠标从主菜单斜向移入子菜单时,经过这块区域不会触发mouseleave,这个技巧能解决掉一大半菜单“悬停断连”的槽点。缺陷是触摸屏上:hover点一下会触发,再点也不会收起,所以移动端需要 JS 配合。

下面是点击展开的优化版,用少量 JS 控制.has-submenu的open类,实现移动端友好且支持键盘操作。核心是事件代理,避免给每个菜单项单独绑定多个监听器,页面菜单项多时性能差异明显。

document.addEventListener("DOMContentLoaded", () => { const nav = document.querySelector(".main-nav"); nav.addEventListener("click", (e) => { const target = e.target.closest(".has-submenu > a"); if (!target) return; const item = target.parentElement; const isOpen = item.classList.contains("open"); // 关闭所有的展开项 nav.querySelectorAll(".has-submenu.open").forEach((el) => { el.classList.remove("open"); }); if (!isOpen) { item.classList.add("open"); } e.preventDefault(); }); });

这段逻辑是:点击带子菜单的主菜单项,先关掉所有已展开的项,再切换当前项,从而实现手风琴效果。用closest是为了兼容点击到<a>内部的子元素时也能正确找到菜单项。preventDefault阻止了链接跳转,因为这里展开菜单本身就是主任务。如果你希望点击菜单项直接跳转而不是展开,就不要用这个逻辑,把这个点击写在子菜单项的<a>上而不是主菜单项上。

3.3 移动端适配:让菜单从横排变成抽屉

移动端最通用的做法是汉堡菜单加抽屉侧滑。你需要一个按钮作为开关,以及一个遮罩层防止用户误点背后的内容。很多源码在这里做得不彻底,要么遮罩盖不住滚动条,要么侧滑时页面还能滚动,体验很差。

<button class="nav-toggle" aria-label="切换菜单" aria-expanded="false"> <span></span> <span></span> <span></span> </button> <div class="nav-overlay"></div>
.nav-toggle { display: none; flex-direction: column; gap: 5px; background: none; border: 0; cursor: pointer; } .nav-overlay { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.4); z-index: 9; } @media (max-width: 768px) { .nav-toggle { display: flex; } .main-nav { position: fixed; top: 0; left: 0; bottom: 0; width: 260px; background: #fff; transform: translateX(-100%); transition: transform 0.3s ease; z-index: 20; padding: 48px 24px; } .main-nav.open { transform: translateX(0); } .main-nav.open + .nav-overlay { display: block; } .menu { flex-direction: column; gap: 0; } .submenu { position: static; opacity: 1; transform: none; visibility: visible; box-shadow: none; border: 0; border-left: 2px solid #e8e8e8; margin-left: 16px; } }

这里用position: fixed把导航钉在屏幕左侧,translateX(-100%)让它藏在屏幕外,.open类把它拉回来。transition确保滑动顺滑。子菜单在移动端改成静态展开,不再做悬浮定位,这样用户点击主菜单项后,子菜单直接以缩进样式展示在下方,逻辑简单且适合触摸操作。断点值 768px 是大多数移动端源码采用的分界,但具体项目需要看你自己的页面布局在哪一宽度开始变形,灵活调整,不要死守这个数。

3.4 JS 开关与状态同步

抽屉菜单除了样式,还需要 JS 控制open类和aria-expanded属性。无障碍不是加分项,是必须项。很多人忽略aria-expanded,屏幕阅读器用户完全不知道这个按钮当前是展开还是收起。

const toggle = document.querySelector(".nav-toggle"); const nav = document.querySelector(".main-nav"); const overlay = document.querySelector(".nav-overlay"); function openMenu() { nav.classList.add("open"); overlay.classList.add("active"); toggle.setAttribute("aria-expanded", "true"); document.body.style.overflow = "hidden"; } function closeMenu() { nav.classList.remove("open"); overlay.classList.remove("active"); toggle.setAttribute("aria-expanded", "false"); document.body.style.overflow = ""; } toggle.addEventListener("click", () => { if (nav.classList.contains("open")) { closeMenu(); } else { openMenu(); } }); overlay.addEventListener("click", closeMenu);

document.body.style.overflow = "hidden"是为了在抽屉打开时锁住背景页面滚动,关闭时恢复。如果不做这一步,用户滑到底部时背景页面会跟着滚动,遮罩形同虚设。移动端还需要注意一点:点击子菜单的链接跳转页面时,如果项目是单页应用,需要手动调用closeMenu()把抽屉收回去,否则新页面顶部会残留一个展开的菜单。


4. 6 个必调参数:间距、层级、动效、断点、阴影与状态

4.1 间距与字号:阅读节奏的起点

菜单项之间的间距直接决定视觉密度。我习惯用gap统一管理主菜单项间距,不使用margin是避免首尾项产生多余空隙。桌面端gap: 8px是紧凑感,适合后台;gap: 24px是通透感,适合品牌官网。子菜单内部用padding: 6px 0让上下留白,每项<a>用padding: 10px 16px保证可点击高度不小于 44px,这是移动端触控标准。

字号上,主菜单用 15px 最中性,14px 偏紧凑,16px 偏大;子菜单字号比主菜单小 1px 即可形成层级,同时颜色从#333降到#666。所有文字不要用纯黑#000,在浅色背景下纯黑会显得生硬,#333或#222即可。颜色传递的信息层级比字号更直观,用户扫一眼就能分辨主次。

4.2 层级与级联:z-index 与定位上下文

子菜单是绝对定位元素,它的z-index只有在父级没有创建层叠上下文时才有效。如果某个菜单项父级被加上了transform、opacity或filter这些属性,就会自动创建层叠上下文,子菜单的z-index会被限制在父级内部,无法和页面其他元素比较层级。常见翻车场景是轮播图组件自带transform,菜单悬停弹出后子菜单被轮播图盖住一半。

解决办法有两个,要么给菜单容器 .main-nav 直接设置一个较高z-index并配合position: relative,要么避免在菜单父级上使用这些创建层叠上下文的属性。我推荐前者,省心且可控:

.main-nav { position: relative; z-index: 100; }

具体数值不固定,只要高于页面其他定位组件即可。这个值的成本几乎为零,优先级在项目里属于第一梯队,值得养成习惯。

4.3 动效时长与缓动函数

动效时长控制在 200ms 到 300ms 之间最舒适。低于 150ms 显得生硬,高于 400ms 会让操作等待感明显。transition里缓动函数我常用ease或cubic-bezier(0.25, 0.1, 0.25, 1),后者更顺滑但代码稍长。在交互上,展开比收起快一点,也就是展开 200ms、收起 250ms,会让视觉反馈更自然。

.menu-item:hover > .submenu { transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s; }

抽屉侧滑的时长可以到 300ms,因为移动距离更大,太短会有拖拽撕裂感。阴影出现的时间可以和透明度同步,避免阴影先亮、菜单后到。

4.4 断点策略:不要只设一个屏幕宽度

菜单响应式断点至少设两个档:一个给平板,一个给手机。768px 是手机与平板的常见分界,但很多后台系统在 1024px 就已经拥挤,此时横向菜单应该切换成抽屉。我的做法是看内容何时开始溢出——打开浏览器开发者工具,拖动窗口宽度,观察菜单项的链接文本是否开始折行或者按钮间距过小,在那个宽度附近设置断点。

@media (max-width: 1024px) { /* 平板及以下切换为抽屉 */ } @media (max-width: 768px) { /* 手机上进一步压缩间距、调整字号 */ }

断点不是越多越好,两个档位覆盖绝大多数场景。如果你服务的用户大量使用特定设备,可以用一段测试代码统计窗口宽度分布,再针对性优化断点。

4.5 阴影与边框:层次感的双保险

子菜单用box-shadow能从背景中跳出来,但阴影太深会有脏脏的感觉。推荐数值是0 6px 16px rgba(0, 0, 0, 0.08);展开时阴影可以略微加重到0 8px 24px rgba(0, 0, 0, 0.12),给用户一种菜单“浮起来”的反馈。细边框1px solid #e8e8e8在浅色背景下能加强边缘识别,在深色背景下阴影作用更明显,边框可以去掉。

box-shadow主要影响性能的表现,页面里同时有几十个阴影元素时,滚动和动画会有可感知的卡顿。菜单这种数量很少的组件影响不大,但如果你在页面里到处用大范围阴影,还是需要注意滚动优化。

4.6 状态管理:选中、悬停、焦点、禁用

菜单要有清晰的四个状态:普通、悬停、选中、键盘焦点。很多人只做了悬停,忘记选中态,用户进入某个页面后无法从菜单看出当前位置。选中态用当前页面对应的菜单项,加一个高亮背景或下划线。

.menu-item > a.active { color: #1677ff; font-weight: 500; } .menu-item > a.active::after { content: ""; position: absolute; left: 16px; right: 16px; bottom: 0; height: 2px; background: #1677ff; border-radius: 2px; }

键盘焦点态是给 Tab 键盘操作的用户看的。:focus-visible会在键盘导航时显示焦点框,鼠标点击时不显示,比直接用:focus更合理,避免鼠标点击后出现难看的焦点框残留。禁用状态的菜单项要降低透明度并用cursor: not-allowed,同时移除 hover 效果。


5. 菜单美化进阶:图标、徽标与关键帧动效的合理使用

5.1 图标和徽标:让菜单有表情也有信息

纯文字菜单在视觉上容易显得单调,适当地加图标和徽标能提升可读性和美观度。图标放在文字左侧,大小建议 16px 到 18px,用inline-flex对齐保持图标和文字垂直居中。徽标用来提示新消息、版本更新或数量,常见在“消息中心”上放一个红色圆点或数字,位置在文字右上角,需要绝对定位。

<li class="menu-item"> <a href="#"> <svg class="menu-icon" viewBox="0 0 16 16" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.5"> <path d="M2 2h12v12H2z" /> <path d="M2 6h12" /> </svg> 仪表盘 <span class="menu-badge">3</span> </a> </li>
.menu-icon { margin-right: 8px; vertical-align: middle; } .menu-badge { position: absolute; top: 6px; right: 8px; min-width: 18px; height: 18px; line-height: 18px; padding: 0 5px; border-radius: 9px; background: #ff4d4f; color: #fff; font-size: 12px; text-align: center; }

图标内联的stroke="currentColor"让图标颜色跟随文字颜色,主菜单变色时图标自动跟着变。徽标用border-radius: 9px是因为 18px 高度的一半是 9px,数学上刚好形成胶囊形状;数字超过两位时会自然拉长为椭圆,视觉上仍正常。徽标数量建议上线做封顶,比如超过 99 显示99+,否则三位数会撑破样式。

5.2 关键帧动效:小成本高质感

悬停图标微微摆动或下划线从左侧生长,这些动效可以让菜单显得精致。用 CSS 关键帧要克制,动效幅度小、频率低,避免用户视觉疲劳。最常用的是下划线从左侧生长:

.menu-item > a::after { content: ""; position: absolute; left: 16px; right: 16px; bottom: 0; height: 2px; background: currentColor; transform: scaleX(0); transform-origin: left center; transition: transform 0.25s ease; } .menu-item > a:hover::after, .menu-item > a.active::after { transform: scaleX(1); }

transform-origin: left center让线条从左侧向右展开,scaleX比直接改变宽度性能更好,因为缩放由 GPU 合成,不会触发重排。动效时长和前面提到的展开时间保持一致,用户手感才统一。慎用上下跳动或左右摇摆的动效,除非是儿童类产品,否则会显得廉价。

5.3 深色模式适配

越来越多的项目需要深色模式。菜单在深色背景下需要调整背景色、文字色、边框和阴影。用 CSS 变量统一管理是最省心的方式:

:root { --menu-bg: #ffffff; --menu-text: #333333; --menu-border: #e8e8e8; } @media (prefers-color-scheme: dark) { :root { --menu-bg: #1f1f1f; --menu-text: #e8e8e8; --menu-border: #3a3a3a; } } .main-nav { background: var(--menu-bg); color: var(--menu-text); border-color: var(--menu-border); }

这样只需改变量值,所有使用了变量处自动生效。注意深色模式下阴影应该改为存在感更弱的黑色阴影,或者干脆去掉,因为深色背景下阴影几乎不可见,反而显得背景脏。同理边框颜色在深色模式下要用浅色描边(比如#3a3a3a),用浅色边框勾勒出菜单边界。别把子菜单也套用变量,单独设置。


6. 菜单源码避坑指南:5 个高频翻车点与排查步骤

6.1 现象:子菜单一闪就没,鼠标根本移不过去

这个是最常见的翻车现场。鼠标从主菜单往下移动到子菜单的路径中,子菜单就消失了。原因是主菜单和子菜单之间存在间隙,鼠标离开主菜单触发mouseleave,然后子菜单被关掉。即使视觉上两个块贴在一起,padding、边框或定位偏移都可能造成几像素的空隙。

解决方式:在子菜单上增加透明热区,推荐用::before伪元素覆盖从主菜单底部到子菜单顶部之间的空隙。如果没有间隙但仍有问题,检查子菜单的top值是否和主菜单高度有偏差。也可以用 JS 的延迟关闭,鼠标离开主菜单后等 150ms 再关闭,如果在这段时间内鼠标进入子菜单就取消关闭,这是一种更稳妥的交互兜底。

6.2 现象:子菜单被轮播图或弹窗盖住

设置了很高的z-index还是被盖住,这是新手最容易困惑的 CSS 玄学。原因多半是某个父级元素创建了层叠上下文,子菜单的z-index实际上参与的是这个父级内部的层叠比较,而不是和页面全局比较。常见的触发属性是transform、opacity、filter、will-change。

排查步骤:打开开发者工具,选中子菜单元素,看它的z-index是否生效;然后逐级向上查看父元素是否有transform或opacity,找到第一个创建层叠上下文的父级。解决方式是在该父级上增加更高的z-index,或者移除不必要的transform属性。例如轮播图的滑动动画通常会让transform常驻,此时给菜单容器设置一个全局较高的position: relative; z-index: 100即可。

6.3 现象:移动端点击主菜单项,子菜单展开,但页面跳到了别的地方

这是交互逻辑冲突。主菜单项<a href="#">的默认行为是跳转当前页顶部,点击展开子菜单的同时页面跳转,看起来像菜单“失灵”。本质是事件没有切断默认行为。在 JS 的点击处理函数里调用e.preventDefault()就能阻止跳转。

另一个相关场景是移动端子菜单的“手风琴”行为:点击主菜单项展开子菜单,再点其他项时应该自动收拢前一项。如果没做统一关闭逻辑,就会出现多个子菜单同时展开。回到前面第 3.2 节的代码,nav.querySelectorAll(".has-submenu.open")就是负责干这件事的。

6.4 现象:菜单动画在低端手机上卡顿

过渡动画卡顿通常是因为 CSS 动画属性触发重排。transform和opacity可以交给 GPU 合成,不触发重排;而left、top、width、margin这些属性变化会导致重排和重绘,每帧都要重新计算布局,在低端设备上掉帧是可感知的。

优化方案是改成transform: translateX(...)或scaleX(...)实现位置和尺寸变化。抽屉侧滑用translateX,下划线生长用scaleX,子菜单用opacity+transform: translateY。排查时打开性能监控面板,看动画期间是否出现大量 Layout 事件。如果出现,检查动画属性是不是用错了。

6.5 现象:键盘用户 Tab 不到子菜单项

用键盘 Tab 键操作时,visibility: hidden的子菜单项无法被聚焦,这是正确的行为,但问题是用户想展开子菜单时压根不知道该按什么。本质上还是状态没有正确交给键盘控制。键盘可访问的下拉菜单有标准交互模式:主菜单项可 Tab 聚焦,按 Enter 或空格展开子菜单,此时子菜单项应该变为可见且可聚焦。

实现思路:在 JS 键盘事件中监听keydown,当焦点在主菜单项且按下 Enter 时,动态移除子菜单的visibility: hidden,并让第一个子菜单项获得焦点。这个改动工作量不大,但对无障碍的价值很高。很多现成源码都没有处理这一层,如果你服务的产品有大量键盘用户或需要符合无障碍标准,这部分值得补上。


7. 把菜单源码变成自己风格的组件:封装与验证技巧

拿到任意一份菜单源码,我建议你先别急着复制粘贴,而是花半小时做三件事:拆解结构、替换颜色变量、验证边界行为。

第一步,把源码的 HTML 结构复制到一个空白页面,然后截个图,看风格是否符合目标项目;第二步,全局搜索颜色值#,把所有硬编码替换成项目已有的 CSS 变量;第三步,开着开发者工具,从 320px 宽度一路拖到 1920px,观察菜单在 480px、768px、1024px、1366px 这几个常用宽度点的表现,哪个宽度出现错位或溢出,就在哪附近补断点。

养成一个习惯:为菜单组件写一段最小测试代码,覆盖三个场景——桌面端悬停展开子菜单、移动端点击展开并切换、键盘 Tab 操作可见性。这三个场景通过后,这个菜单源码才算真正可用。有个小技巧是给主菜单项和子菜单项各加一个style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;" />

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询