nav和dropdown必须是两个独立block:nav仅负责语义结构与布局(nav__list、nav__item、nav__link),dropdown封装完整交互逻辑(dropdown__toggle、dropdown__menu),二者dom需紧邻或直接父子,禁止nav__dropdown等跨块命名。

nav 和 dropdown 必须是两个独立 block
复杂多级菜单命名混乱,根本不是类名不够长,而是把 nav 和 dropdown 当成一个东西在写。nav 只管语义结构和布局:nav__list、nav__item、nav__link;所有下拉交互(触发、面板、定位、过渡)必须由 dropdown 这个独立 block 承担。
常见错误现象:nav__item__dropdown、nav__submenu、nav__item__submenu__link——这类命名直接违反 BEM 职责边界,导致改一个动效就要重测整个导航结构。
-
nav__item内部只放一个<div class="dropdown"></div>,不写任何dropdown__相关样式规则 - 二级菜单不是“子项”,而是另一个
dropdown实例,直接嵌套在上层dropdown__menu里 - 差异靠修饰符解决:
dropdown--mega、dropdown--click、dropdown--secondary,而不是靠父级前缀模拟层级
.dropdown__toggle:hover + .dropdown__menu 失效怎么办
90% 的 hover 闪退或菜单消失快,不是 CSS 写错了,是 DOM 结构断链了。这个选择器要求两个元素必须是紧邻兄弟节点,而 Vue 的 <transition></transition>、React 的 <fragment></fragment> 或手写的 <div class="wrapper"> 都会插在中间,彻底破坏选择器匹配。
<p>确保以下任一结构成立:</p>
<ul>
<li>
<code><button class="dropdown__toggle"></button><div class="dropdown__menu"></div>(相邻兄弟)
<div class="dropdown">
<button class="dropdown__toggle"></button><div class="dropdown__menu"></div>
</div>(同父包裹)<div class="dropdown"><div class="dropdown__menu"><button class="dropdown__toggle"></button></div></div>(直接父子,需配合 :has(),注意 Safari 15.4+ / Chrome 105+ 才稳定)补救措施:dropdown__menu 加 min-width: max-content 防止内容收缩后鼠标移出热区;JS 控制显隐时用 display: none 或 visibility: hidden,别用 remove()。
多级嵌套时怎么避免命名爆炸
写到三级就开始出现 nav__item__submenu__link?这是结构失焦的明确信号。BEM 不允许跨 block 命名,“三级”这个概念根本不存在——只有多个 dropdown 实例依次嵌套在不同 nav__item 中。
- 一级菜单:
<li class="nav__item">产品<div class="dropdown"></div> </li> - 二级菜单:在上层
dropdown__menu里再放一个<div class="dropdown"></div>,不是dropdown__submenu - 所有
dropdown共享基础样式,差异走修饰符,比如dropdown--inline、dropdown--mega - 禁止使用
nav__dropdown--level-2这类伪层级命名,它会让样式逻辑无法解耦、无法单独测试
CSS 文件怎么拆才真模块化
模块化不是起个好名字就完事,关键是文件组织让人一眼看出“这个样式管哪块、能不能单独抽走”。nav.css 里不该塞任何和交互、皮肤、响应式相关的东西。
-
nav.css:只含nav、nav__list、nav__item等容器与布局规则,不含颜色、字体、hover、z-index -
nav-dropdown.css:仅当项目用到下拉时才引入,只定义dropdown块及其过渡、定位、z-index -
_nav-theme.css:抽成 CSS 自定义属性(--nav-bg、--nav-link-color),换肤不改结构 - 媒体查询统一交给
layout-responsive.css管理,否则响应式逻辑会和nav职责耦合
最易被忽略的一点:每个 dropdown 实例都应能独立配置触发方式(hover/focus/click)、动效、定位策略,而不是靠类名深度去“猜”它在哪一层。











