HTML原生<style scoped>早已失效,Chrome 120+、Firefox 115+已彻底移除支持;它从未真正工作,浏览器直接忽略该属性,样式仍全局生效;真隔离唯一路径是attachShadow()创建Shadow DOM边界。

HTML原生scoped属性早已失效,别再写它了
浏览器从 Chrome 120、Firefox 115 起已彻底移除对 <style scoped> 的支持——它从来就没真正工作过。你写 <style scoped>,浏览器直接忽略该属性,样式照常全局生效。这不是兼容性问题,是规范层面的删除。所有“纯 HTML + scoped”方案在现代浏览器里等于没写。
Vue 等框架的scoped和 HTML 的scoped不是一回事
框架里的 <style scoped> 是构建工具(如 Vue Loader)编译时做的手脚:给元素加 data-v-f3f3eg9 这类唯一属性,再重写 CSS 选择器为 .btn[data-v-f3f3eg9]。它依赖打包流程,不是浏览器能力。如果你把 .vue 文件直接扔进静态服务器不走构建,scoped 一样失效。
- 没构建工具 → 没
data-v-xxx属性 → 样式照样泄漏 - 手动克隆或
v-html插入的 DOM 不带这些属性 → 隔离完全失效 - SSR 渲染时服务端和客户端生成的哈希必须一致,否则 hydration 失败
真隔离只有一条路:attachShadow()
Shadow DOM 是目前唯一被浏览器原生支持、运行时生效的样式隔离机制。它不是“加个 class 前缀”或“拼个 data 属性”,而是让浏览器在样式计算阶段直接跳过跨 boundary 匹配——外部 CSS(含 !important)根本看不见 shadow 内部元素。
- 必须调用
element.attachShadow({ mode: 'closed' }),且只能在constructor中执行;延迟调用等于没隔离 -
mode: 'closed'才能防止外部 JS 通过el.shadowRoot修改样式表;'open'模式下隔离形同虚设 - 不能用
shadowRoot.innerHTML = '<style>...</style>'—— 内联<style>会被当普通 HTML 解析,不进 CSSOM,后续 JS 动态改样式会失效 - 正确做法是创建
<style>元素后用adoptedStyleSheets注入,或用DOMParser安全解析 HTML 片段
没 JS 或不想用 Shadow DOM?只能接受“模拟隔离”
纯静态页、微前端子应用、或需兼容老环境时,attachShadow() 不现实。此时只能退而求其次,靠构建时手段降低冲突概率:
立即学习“前端免费学习笔记(深入)”;
- CSS Modules:类名自动哈希(如
button_abc123),但无法防标签选择器(button { color: red })或属性选择器([data-theme])穿透 - BEM 命名:如
.card__title,仅靠命名约定,无技术强制力,第三方库或全局 reset 仍可覆盖 - @scope():CSS 新标准,2026 年起部分浏览器开始支持,但目前覆盖率极低,生产环境不可依赖
- iframe:隔离最强,但通信成本高、SEO 差、滚动/焦点管理复杂,属于重方案
真正麻烦的永远是 html 和 body 这两个全局节点——所有子应用的 body { margin: 0 } 都会互相覆盖,连 scoped 或 CSS Modules 都拦不住。这点最容易被忽略,直到微前端上线才暴雷。



















