.fade-in错误是因为它被识别为独立block而非修饰符,导致工具链失效、样式覆盖、语义缺失;.card--fade-in正确因其符合bem规范,明确绑定组件、支持工具识别、确保动画逻辑精准锚定。

动画类名必须是 BEM 修饰符(--modifier),绑定到具体 Block 或 Element,不能独立存在,也不能脱离语义上下文。
为什么 .fade-in 是错的,而 .card--fade-in 才对
直接写 .fade-in 会被工具链(如 Stylelint)识别为新 Block,不是修饰符,导致自动检查失败、IDE 类名跳转失效;CSS 选择器权重也压不过 .card__content 这类元素选择器,样式大概率被覆盖。更关键的是,它没说明“谁在淡入”——加在 .modal 上可能漏位移起点,加在 .toast 上又可能缺 z-index 控制。
正确做法是让修饰符和组件强绑定:.card--fade-in 表示「这张卡片正处于淡入流程中」,所有动画逻辑(起点、时长、硬件加速)都围绕这个语义展开。
-
.card--fade-in✅ 工具可识别为 card 块的状态,CSS 和 JS 都能精准锚定 -
.fade-in❌ 全局类,无上下文,复用即冲突 -
.card-fade-in❌ 单横线被解析为新 Block,BEM 解析器不认 -
.cardFadeIn❌ 驼峰不符合 CSS 语法,也无法被 PostCSS 插件处理
animation 和 transition 必须显式写在修饰符规则里
只加 .button--loading-spin 类,但 CSS 中没声明 animation 或 transition,动画永远不会触发。浏览器不会继承父级的 transition: all,也不会自动补全属性。
常见错误是基础类 .drawer 没定义 transition: max-height 0.3s ease,只在 .drawer--expanded 里写了 max-height: 500px ——结果展开有动画,收起直接跳变。
- 用
animation(如 loading 循环):修饰符里必须完整写animation: loading-spin 0.4s linear infinite - 用
transition(如 hover 缩放):基础类就得先定义transition: transform 0.2s ease,否则加了--hover-scale也没反应 - 禁用
* { transition: all .2s }:它会让color、margin等非预期属性也过渡,且阻断will-change优化
多个动画状态怎么共存,又不嵌套修饰符
BEM 不允许 .modal--fade-in--scale 或 .card--loading--disabled 这种链式修饰符。它们不是父子关系,而是并列布尔开关,必须平级添加、独立控制。
例如模态框同时需要淡入 + 缩放入场,就该写:class="modal modal--fade-in modal--scale",CSS 中分别定义两个修饰符的效果:
.modal--fade-in .modal__overlay { animation: modal-fade-in 0.25s ease; }
.modal--scale .modal__content { animation: modal-scale-in 0.25s ease; }
- JS 控制用
el.classList.toggle('modal--fade-in')和el.classList.toggle('modal--scale')分开调用 - 避免竞态:切换前先执行
el.getAnimations().forEach(a => a.cancel())清理旧动画 - 入场/退出需分步:先
add('card--fade-out')→ 监听animationend且过滤event.animationName === 'fade-out'→ 再remove('card--fade-in')
动画关键帧名和 BEM 类名要分离,但语义要对齐
别把 @keyframes 名和 BEM 类名混用,比如定义 @keyframes slideIn,又写 .carousel__track--slideIn ——前者是时间轴描述,后者是状态标识,职责完全不同。
正确方式是严格分离:
-
@keyframes carousel-slide-in✅ 小写+连字符,动宾结构,符合 CSS 标准 -
.carousel--sliding✅ BEM 修饰符,表达“当前处于滑动流程中” - CSS 中绑定:
.carousel--sliding .carousel__track { animation: carousel-slide-in 0.3s ease; } - 禁止在修饰符里写
animation: none来“关闭”动画——这会覆盖所有继承的动画规则
最易被忽略的是:修饰符语义一旦绑定组件,就不能挪用。.card--fade-in 的动画起点、transform 是否启用硬件加速、取消逻辑是否调用 getAnimations(),全都依赖它只出现在 .card 上这个前提。换到 .modal 上,哪怕 CSS 规则一模一样,也可能因上下文缺失而失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











