nav和dropdown必须是两个独立block,因bem强调职责分离:nav只管语义布局,dropdown专责交互逻辑;混用会导致hover失效、菜单错位、样式污染及命名爆炸。

直接重构电商导航栏,不能只改类名,必须先拆出 nav 和 dropdown 两个独立 block——否则所有 hover 闪退、多级菜单错位、样式污染问题都会持续复现。
为什么 nav 和 dropdown 必须是两个独立 block
电商导航常有「分类 → 品牌墙 → 热销榜」三级结构,但 BEM 不承认“三级”,只认职责边界:nav 只管语义与布局(nav__list、nav__item、nav__link),所有下拉交互(触发、面板定位、显隐过渡)必须由独立的 dropdown 承担。
- 写
nav__item__dropdown或nav__submenu是典型错误:它把布局逻辑和交互逻辑硬捆在一起,改个二级菜单动效就得重测整个导航 -
nav__item内部只放一个<div class="dropdown"></div>,不写任何dropdown__相关样式规则 - 二级菜单不是“子项”,而是嵌套在上层
dropdown__menu中的另一个<div class="dropdown"></div> - 若需区分形态(如 mega-menu vs inline-dropdown),用修饰符:
dropdown--mega、dropdown--inline,而非父级前缀
DOM 结构怎么写才不破坏 .dropdown__toggle:hover + .dropdown__menu
这个选择器失效,90% 不是 CSS 写错了,而是 DOM 断链了。Vue 的 <transition></transition>、React 的 <fragment></fragment>、甚至手写的 <div class="wrapper"> 都可能插在中间,导致兄弟关系断裂。
<ul>
<li>必须确保 <code>dropdown__toggle 和 dropdown__menu 是相邻兄弟节点,或 dropdown__menu 是其直接子/父节点
<div class="dropdown"> <button class="dropdown__toggle">分类</button> <div class="dropdown__menu">...</div> </div>
min-width: max-content 到 dropdown__menu,防止内容收缩后鼠标移出热区display: none 或 visibility: hidden,别用 remove()——否则 BEM 类还在,结构已断裂如何避免命名爆炸(比如出现 nav__item__submenu__link)
一写到三级就开始拼接长类名,说明结构已经失焦。BEM 不允许跨 block 命名,“三级”本质是多个 dropdown 实例按需嵌套的结果,不是层级深度。
- 禁止
nav__item__submenu、dropdown__menu__submenu、nav__dropdown--level-2这类伪层级命名 - 每个下拉菜单都应是完整
dropdownblock,哪怕它出现在nav__item内部 - 电商中常见差异(如品牌墙带图片、热销榜带角标),用修饰符解决:
dropdown--with-images、dropdown--with-badges - 如果某个下拉足够复杂(如支持搜索+分页+加载状态),它就该升格为独立 block:
category-selector,而非塞进dropdown
最易被忽略的是:block 名称必须绑定具体业务语义,不能是泛义词。电商首页顶部导航叫 header-nav,后台管理侧边栏叫 admin-sidebar-nav,商品详情页的“同店热卖”叫 related-products-nav——名字越具体,后续复用、覆盖、调试时的心智负担越小。











