状态类必须用独立class而非:hover,因后者无法被js控制且ssr不支持;应通过mixin封装可复用的状态样式,绑定到语义明确的节点,遵循bem规范并确保权重可控。

状态类必须用独立 class,别依赖 &:hover
用户交互态(如 hover、focus)和逻辑态(如 .is-active、.is-disabled)在 CSS 层面是两类东西,混用会出问题。浏览器里 &:hover 无法被 JS 控制,SSR 渲染时也拿不到;而组件库或框架(Vue/React)靠 class 控制状态,样式必须对齐。常见错误是写成:
.tab {
&__item {
&:hover { color: @primary-color; }
&.is-active { color: @primary-color; }
}
}
结果是:鼠标悬停时变色,但 JS 激活后没反应——因为 &:hover 和 .is-active 是两套不互通的触发机制。
-
.is-active这类状态类必须由调用方显式添加,CSS 只负责定义它长什么样 - 混入(mixin)里禁止写
&:hover,只输出声明块,比如.state-active()应该只包含color、font-weight等属性,不带选择器 - 若需 hover + active 共存(比如激活态下还支持悬停微调),用嵌套显式覆盖:
.tab__item.is-active:hover { opacity: 0.9; }
用带默认参数的 mixin 封装状态样式
重复写 .is-active { color: @primary-color; font-weight: 600; } 很容易漏掉某处。把状态样式抽成可复用的 mixin,参数按常用程度排序,并设合理默认值:
.state-active(
@color: @primary-color,
@weight: 600,
@bg: transparent
) {
color: @color;
font-weight: @weight;
background-color: @bg;
}
调用时干净利落:
.tab__item.is-active {
.state-active();
}
.btn--primary.is-active {
.state-active(@color: #fff, @bg: darken(@primary-color, 10%));
}
- 参数默认值必须是字面量或内置函数结果(如
@color: #007bff或@color: lighten(@primary-color, 20%)),避免依赖全局变量导致行为漂移 - 不要在 mixin 里硬编码前缀,比如写死
.is-active;前缀由调用者决定,项目换命名规范(如改用.u-active)时无需改 mixin - 如果某状态需要伪元素(如
.is-loading::after),另建专用 mixin,不塞进通用.state-active()
嵌套中控制状态类权重,避免被意外覆盖
编译后 .is-active 单独出现时权重太低,很容易被后面更具体的选择器压掉。比如:
.card .title { color: #333; }
.is-active { color: @primary-color; } // 被上面那条盖掉了
解决方法不是加 !important,而是让状态类天然带上下文:
- 在组件嵌套内调用状态 mixin,例如
.btn.is-active { .state-active(); }→ 编译为.btn.is-active,权重高于单独的.is-active - 遵循 BEM,把状态作为修饰符:
.btn--active,这样.btn--active天然比.btn权重高 - 检查构建流程:某些 CSS 压缩工具会重排规则顺序,导致状态类编译后位置靠前,务必确认最终 CSS 中状态规则在基础样式之后
- 多状态叠加(如
.btn--active.is-disabled)时,优先级由调用顺序决定,混入不自动合并,需手动写覆盖规则
嵌套层级别超 3 层,否则状态类生成的选择器太长
像这样写:
.sidebar {
.nav {
.item {
.link {
&.is-active { color: @primary-color; }
}
}
}
}
会编译出 .sidebar .nav .item .link.is-active,4 层后代选择器,权重高、难覆盖、调试时定位困难。更糟的是,一旦 DOM 结构微调(比如中间加个 wrapper),样式就失效。
- 状态类应绑定到语义最明确的节点上,比如
.nav-item.is-active,而不是深埋在嵌套里 - 组件主选择器下直接处理状态:
.nav-item { &.is-active { ... } },最多 2 层嵌套 - 如果状态涉及跨区域联动(如菜单激活影响侧边栏图标),用独立 class + 全局状态 mixin,别靠嵌套传递上下文
真正难的不是写对一个 .is-active,而是确保它在所有组件里含义一致、权重可控、不随 DOM 深度变化而失效。状态样式的生命力,取决于你有没有把它从“视觉反馈”还原成“逻辑标识”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











