应使用 CSS Modules、CSS-in-JS 或 Shadow DOM 实现样式作用域隔离;CSS Modules 通过哈希类名局部化样式,CSS-in-JS 运行时动态生成唯一 class,Shadow DOM 提供原生强隔离,而 BEM 等命名规范无法防止样式污染。
直接在组件里写 .btn { color: red; },很可能影响其他地方同名类。CSS 本身没有天然作用域,必须靠约定或工具机制隔离。
.my-comp-btn),手动维护易出错、命名冗长button.module.css 中的 .primary 编译成类似 Button_primary__abc123 的唯一哈希类名scoped 或 css modules 配置后,样式只会作用于当前组件 DOM 节点(含子组件需显式穿透)@keyframes、@font-face 等规则默认不局部化,需用 :global() 显式包裹像 styled-components 或 emotion 把样式写在 JS 里,本质是运行时动态生成带哈希的 class 并注入 标签,天然隔离。
styled.button 创建的组件自带唯一 class,即使多个组件都叫 Button,样式也不会冲突color: ${props => props.theme.color};),但过度嵌套会导致生成大量重复 class,影响复用性emotion 需配 CacheProvider,styled-components 需 ServerStyleSheet
Web Components 原生方案,attachShadow({ mode: 'closed' }) 后,内部样式完全无法被外部 CSS 选中,外部样式也无法穿透进来。
createRoot + shadowRoot;Vue 用 defineCustomElement)::part() 和 ::theme() 等新伪类尚未广泛支持BEM(block__element--modifier)是命名规范,不是作用域机制。它不阻止样式泄漏,只靠人遵守约定。
.header__title 仍可能被另一个组件的 .header__title 覆盖(尤其是权重相同、顺序靠后)normalize.css 或 antd,它们的 .btn 会污染你的 .btn)
// 示例:CSS Modules 中正确导出与使用
// Button.module.css
.primary {
background: #007bff;
}
.primary:hover {
background: #0056b3;
}
// Button.jsx
import styles from './Button.module.css';
export default function Button() {
return ;
}
真正的作用域隔离必须由构建阶段(CSS Modules)、运行时(CSS-in-JS)或渲染层(Shadow DOM)介入,仅靠命名或人力约定,迟早会在迭代中破防。