下拉菜单用display控制显隐的核心是默认子菜单display: none,悬停父级时设为display: block;但需父li加position: relative,子ul用position: absolute+top: 100%对齐,避免定位偏移。

下拉菜单怎么用 display 控制显隐
核心就一条:默认把子菜单设为 display: none,鼠标悬停父级时设为 display: block。但要注意,display 切换会触发重排(reflow),如果菜单里有动画或过渡效果,它不支持,得换 visibility 或 opacity 配合 pointer-events。
常见错误是直接对 ul 子菜单写 display: none,但没给父 li 设 position: relative,导致下拉项定位飘走。
- 父级
li必须加position: relative - 子菜单
ul用position: absolute+top: 100%对齐父项底部 - 避免在
:hover里只改opacity,否则仍可点击——要同步加pointer-events: none / auto
为什么 visibility 比 display 更适合带过渡的下拉
display 是离线属性,无法过渡;而 visibility: hidden 和 visibility: visible 虽也不支持过渡,但可以和 opacity、transform 组合实现平滑进出效果,且保持文档流占位(避免页面抖动)。
典型写法是:初始状态设 visibility: hidden; opacity: 0; transform: scaleY(0.8),:hover 时全改为 visible/1/scaleY(1),再加 transition: all 0.2s ease。
立即学习“前端免费学习笔记(深入)”;
- 必须配
transform-origin: top,否则缩放中心偏移 - 若子菜单高度不固定,慎用
max-height过渡——它在0 → auto时无效,得用 JS 或固定值模拟 - 移动端需额外处理
:focus-within或 JS 点击切换,因为:hover不稳定
position: absolute 定位下拉项时的常见偏移问题
下拉菜单错位,90% 出在定位参考点没对齐。绝对定位默认以最近的 position: relative/absolute/fixed 祖先为参考,不是以父 li 文字为基准。
比如父 li 有 padding 或 line-height,子菜单顶部容易高出一截;或者导航栏用了 flex 布局,父 li 没设 position,子菜单就相对 body 定位了。
- 统一给导航项
li加position: relative - 子菜单
ul写top: 100%; left: 0;,而不是top: 0 - 若父项有边框或内边距,用
box-sizing: border-box避免计算偏差 - 调试时临时加
outline: 1px solid red查看定位容器范围
移动端点击展开需要绕开 :hover 的限制
CSS 原生 :hover 在触摸设备上行为不可靠:第一次点击可能触发,第二次又不响应,或误触其他区域。纯 CSS 方案只能退而求其次用 :focus-within(需点击后元素获得焦点),但兼容性要求 Chrome 67+、Firefox 61+。
更稳妥的做法是用极简 JS 控制 class 切换,CSS 只负责样式:
.dropdown:hover .dropdown-menu,
.dropdown:focus-within .dropdown-menu,
.dropdown.active .dropdown-menu {
display: block;
}
然后用 document.querySelectorAll('.dropdown') 绑定 click,切换 active 类。注意加 tabindex="0" 让非可聚焦元素支持 focus。
容易被忽略的是:没阻止事件冒泡,导致点击子菜单项时父级收起;或没处理 ESC 键关闭逻辑。










