纯 css 下拉菜单需满足:子菜单必须嵌套在父 li 内;父 li 设 position: relative;子菜单设 position: absolute、top: 100%、left: 0 和 display: none;通过 li:hover .submenu 控制显隐,否则易错位或不显示。

纯 CSS 实现导航栏下拉菜单,不需要 JavaScript 就能工作,但必须注意几个关键点::hover 只对鼠标悬停有效、子菜单必须嵌套在父 li 内、position: absolute 必须配合 position: relative 才能准确定位。否则菜单会飘走或不显示。
HTML 结构必须嵌套正确
下拉菜单依赖 DOM 层级关系,ul 子菜单必须直接放在父 li 里,不能提级到外层或用兄弟元素模拟:
<nav><ul class="navbar">
<li><a href="#">首页</a></li>
<li>
<a href="#">产品</a>
<ul class="submenu">
<!-- ✅ 正确:子菜单是当前 li 的直接子元素 --><li><a href="#">Web 端</a></li>
<li><a href="#">移动端</a></li>
</ul>
</li>
</ul></nav>
- 如果把
submenu提到navbar下(和一级li并列),:hover就无法触发它显示 -
a标签不是必须的,但若用button或span,需确保它可聚焦且无障碍支持更弱 - 多级菜单(三级及以上)同理,每一级
ul都得嵌在上一级li里
CSS 定位和显隐控制的核心写法
关键不是“怎么让它出现”,而是“怎么让它出现在正确位置且不破坏布局”:
- 父级
li必须设position: relative,否则absolute子菜单会相对于最近的定位祖先偏移,常导致错位 - 子菜单
ul.submenu设position: absolute; top: 100%; left: 0;,这样它才会紧贴父菜单下方展开 - 用
display: none / block最简单,但动画受限;若要过渡效果,改用visibility: hidden / visible+opacity,或max-height: 0 / 200px+overflow: hidden -
z-index至少设为10以上,避免被其他浮动元素或 banner 遮挡
常见错误:菜单闪退或错位
鼠标一移就消失,或下拉项跑到屏幕左边/顶部,基本都是以下原因:
-
.submenu没加min-width,内容窄时宽度塌缩,悬停区域变小 → 鼠标离开父li就触发:hover失效 - 父
li用了float: left却没清除浮动,导致父容器高度坍塌 →relative失效,absolute定位基准丢失 - 子菜单里
a标签默认有text-decoration: underline或display: inline,造成点击区域过小 → 建议统一设display: block; padding: 8px 16px; - 移动端 Safari 对
:hover支持不稳定,首次点击才触发,后续才模拟悬停 → 真实项目中必须搭配@media (hover: hover)做兼容判断
最简可用组合就是:li { position: relative; } + .submenu { position: absolute; top: 100%; left: 0; display: none; } + li:hover .submenu { display: block; }。其余样式(圆角、阴影、过渡)都是锦上添花,但定位逻辑错了,再好看的动画也白搭。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











