应使用 js- 前缀类供 JS 定位元素、is- 前缀类表达运行时状态,CSS 仅定义样式,实现行为与表现的彻底解耦。

为什么不能用 card--active 让 JS 直接操作这个类
JS 操作 card--active 看似简洁,但会把行为语义(“当前被选中”)和视觉表现(“高亮边框、阴影”)混在一起。一旦设计改版要取消高亮,你得同时改 CSS 和所有 JS 里对 card--active 的引用;更麻烦的是,服务端渲染或 SSR 首屏 HTML 若误带了 card--active,JS 初始化时就可能状态错乱。
真正需要解耦的不是“能不能用”,而是“谁该负责什么”:CSS 定义样式,JS 只管状态流转,中间靠明确的契约连接。
js- 前缀类只用于 JS 获取与触发,不写任何样式
给需要 JS 干预的元素加 js-card-toggle、js-sidebar-close 这类类名,目的只有一个:让 JS 快速定位目标,不参与样式逻辑。
-
js-类名必须在 HTML 中静态存在,不能由 JS 动态添加——否则就成了“用 JS 找 JS 添加的类”,不可靠且难调试 - CSS 文件里禁止出现
.js-*选择器,哪怕只写display: none也不行;它不是样式钩子,是纯 DOM 标识 - 一个元素可以同时有
card__trigger(样式类)和js-card-toggle(行为类),互不干扰
状态类必须用 is-,且只由 JS 控制
视觉变化靠 is-card-active、is-sidebar-open 这类类名,它们只出现在 JS 的 classList.add() / toggle() 中,CSS 里只定义效果:
立即学习“前端免费学习笔记(深入)”;
.card { border: 1px solid #eee; }
.is-card-active .card { border-color: #007bff; box-shadow: 0 0 8px rgba(0,123,255,0.2); }
关键点:
- 不要在 HTML 初始结构里写
is-类——它代表运行时状态,非初始配置 - 避免
.card.is-card-active这种写法,用父容器控制更稳定(如.page.is-cart-open .cart-panel) - 多个状态共存时,比如
is-card-active is-card-pinned,CSS 规则彼此正交,不互相覆盖
容易被忽略的构建与协作陷阱
团队里最常出问题的不是命名规则本身,而是上下游工具链没对齐:
- Webpack 的
css-loader开启modules后,.is-card-active会被重命名为局部作用域类,JS 就找不到它了——此时必须用:global(.is-card-active)或关闭 modules - Vue 单文件组件中,
<style scoped></style>同样会让is-类失效,需显式写<style module></style>或:global(.is-*) - 测试代码(如 Cypress)若用
[class*="is-card"]断言状态,要意识到它依赖类名字符串,比data-testid更脆弱,仅适合快速验证
真正难的不是记住 js- 和 is- 的区别,而是在组件封装、SSR 渲染、构建配置、E2E 测试多个环节里,保持这一层语义不被意外穿透或覆盖。


















