@scope规则需html属性与css选择器严格匹配才能生效,否则浏览器静默跳过;必须使用scope或scope-start属性(非class),且动态插入后不会重新计算。

@scope 目前不能直接“用”,它需要 HTML 和 CSS 两侧严格对齐,缺一不可;Chrome 125+ 默认启用,但写错 boundary 就静默失效,不报错也不渲染。
为什么写了 @scope 却完全没效果
浏览器根本不会报错,只会跳过整条规则——因为 @scope 不是选择器,而是作用域容器,必须有真实 DOM 节点作为边界起点。常见失效原因:
-
@scope (.card) { ... }要求对应 HTML 元素带scope属性(不是 class),比如<div class="card" scope>;写成 <code><div class="card"> 就无效 <li>用属性选择器匹配时,<code>@scope (section[scope])必须对应<section scope></section>,不能写成@scope (section.scope)(那是类名,不是属性) - 动态 JS 插入带
scope的元素后,已解析的@scope规则不会重新计算,得等样式表重载或用CSSStyleSheet.replace()手动触发 - DevTools Elements 面板里看不到 scoped 样式被折叠或高亮,只能靠手动检查目标元素是否命中规则
- HTML 中必须出现
scope或scope-start属性(如<article scope></article>或<main scope-start></main>) - CSS 中的
@scope第一个参数必须能精确匹配该属性节点,例如:@scope (article[scope])、@scope ([scope-start]) - 不支持嵌套
@scope块(规范明确禁止),也不能用:is()或:where()包裹 scope-root -
to <limit></limit>是可选终点,但<limit></limit>必须是 scope-root 的后代节点,且必须在 DOM 中真实存在 - CSS Modules:Webpack/Vite 默认支持
Button.module.css,编译后类名自动哈希,JS 中通过import styles from './Button.module.css'引用,零配置即隔离 - Vue/Svelte 的
<style scoped></style>:框架自动给元素加data-v-xxx属性,并重写选择器为.btn[data-v-xxx],开发体验最顺 - BEM 命名 + 唯一类前缀:如
.user-card__title,不依赖工具,适合老项目或静态页,但靠人守规范 - ID 前缀锁定(慎用):如
#user-card .title,权重高、难覆盖,仅适用于单实例页面区块
@scope 的写法和边界定义必须一一对应
它不是独立语法糖,而是依赖 HTML attribute + CSS 选择器双向绑定。关键约束:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
比 @scope 更可靠、更通用的替代方案
除非你明确需要原生、无构建、纯 HTML/CSS 的作用域控制,否则以下方式落地更稳:
别把 :where() 当作用域工具用
它只归零选择器权重,不改变匹配范围。例如:#container :where(.btn, .link) 仍会匹配所有在 #container 内的 .btn 和 .link,不管它们来自哪个组件——这跟作用域无关,只是优先级调节手段。
真正容易被忽略的点是:@scope 的边界必须是 attribute,不是 class,也不是伪类;而且一旦 DOM 没准备好,CSS 就永远不生效,连 warning 都没有。










