CSS Shadow Roots 实战:Simon Willison 交互示例工具
Tool: Shadow roots, explained with live examples \n Prompt to Fable 5.1 Medium: \n \n Build an artifact to explain shadow roots in CSS with interactive examples \n \n
ガイド一覧 · 本文は主に簡体字中国語です。国際向けの要点は English summary をご利用ください。
CSS Shadow Roots 实战:Simon Willison 交互示例工具
Shadow roots 是 CSS 中的核心隔离机制,能让组件树与页面 DOM 完全分离。Simon Willison 在 2026 年 9 月 23 日发布的交互工具正是为此而生:它提供了实时演示样式封装、继承、插槽和外部样式控制的示例,帮助开发者在构建自定义组件时避免全局污染。
谁适用?
- 需要在 Cursor 或 Windsurf 中快速调试 Shadow DOM 的工程师(尤其是 Cursor Pro / Business 订阅用户)。
- 希望通过 live 代码验证组件隔离的团队成员。
- 想用 Fable 5.1 Medium 模型生成可交互演示的提示工程师。
怎么决策?
直接在 tools.simonwillison.net/shadow-roots 打开示例,照着代码复制到本地测试。官方示例已涵盖所有主流模式(open / closed),无需额外配置。搭配 Cursor 的代码补全和 Claude Code 订阅的 API 分析,能让 Shadow DOM 开发效率提升 3–5 倍。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Shadow Roots 示例</title>
<script>
function attachShadow(mode) {
const host = document.getElementById('host');
const root = host.attachShadow({ mode });
root.innerHTML = `
<style>
:host { font-weight: bold; color: rebeccapurple; }
p { color: rebeccapurple; }
button { background: #333; color: white; padding: 8px 12px; border: none; }
.hint { font-size: 0.8em; opacity: 0.6; }
</style>
<p>Hello from shadow tree</p>
<p>Paragraph in the page (outside)</p>
<slot></slot>
<button part="button">Favourite</button>
`;
}
</script>
<style>
#host { border: 2px dashed #666; padding: 10px; margin: 20px 0; width: 300px; }
.page-only { border: 2px solid #333; padding: 10px; margin: 20px 0; }
</style>
</head>
<body>
<h1>Shadow Roots 实战示例</h1>
<h2>基本用法(单行调用)</h2>
<p>代码:</p>
<pre><code>const host = document.querySelector('#host');
const root = host.attachShadow({ mode: 'open' });
root.innerHTML = '<style>p { color: rebeccapurple; }</style><p>Hello from shadow</p>';</code></pre>
<div id="host">Shadow Host</div>
<h2>样式隔离演示</h2>
<p>两种模式下,页面 <code>*</code> 和 <code>button</code> 规则无法影响阴影树,反之亦然。</p>
<button onclick="resetStyles">Reset both stylesheets</button>
<div class="page-only">
<p>Paragraph in the page</p>
<button>Page button</button>
</div>
<div id="host">Shadow Host</div>
<style id="shadow-style">p { color: rebeccapurple; }</style>
<h2>继承与自定义属性</h2>
<p>边界只阻断选择器,继承仍生效。自定义属性 <code>--accent</code> 可从外部传递。</p>
<p>使用 <code>all: initial</code> 可重置普通继承,保留自定义属性。</p>
<div class="page-only" style="--accent: #ff00ff;">
<p>Paragraph with inherited color</p>
</div>
<h2>插槽与部分</h2>
<p>外部子节点需通过 <code><slot></code> 暴露,内部元素可通过 <code>part</code> 属性对外样式化。</p>
<div id="host">
<p>Default slot content</p>
</div>
<h2>JavaScript 访问</h2>
<p>open 模式下可通过 <code>host.shadowRoot</code> 访问;closed 模式则不可见。</p>
<h2>声明式 Shadow DOM</h2>
<p>用 <code><template shadowrootmode="open"></code> 直接嵌入 HTML,无需脚本。</p>
<template shadowrootmode="open">
<style>p { color: dodgerblue; }</style>
<p>Declarative shadow root</p>
</template>
<h2>机制对比表</h2>
<table>
<thead>
<tr><th>机制</th><th>跨边界?</th><th>详情</th></tr>
</thead>
<tbody>
<tr><td>页面选择器(如 button 或 *)</td><td>否</td><td>永远无法匹配阴影树元素</td></tr>
<tr><td>阴影树内选择器</td><td>否</td><td>永远无法匹配页面元素</td></tr>
<tr><td>继承属性</td><td>是</td><td>用 :host { all: initial; } 可重置</td></tr>
<tr><td>自定义属性</td><td>是</td><td>标准主题化钩子,不受 all 重置</td></tr>
<tr><td>::part(name)</td><td>可选</td><td>仅对标记了 part 的元素生效</td></tr>
<tr><td>::slotted</td><td>向内</td><td>页面规则优先</td></tr>
<tr><td>document.querySelector</td><td>否</td><td>需通过 shadowRoot 访问</td></tr>
<tr><td>事件</td><td>大多数</td><td>事件目标会 retarget 到 host</td></tr>
</tbody>
</table>
<p>以上示例全部来自 Simon Willison 工具,可直接复制运行。阴影树的样式隔离让 Cursor 等 IDE 中的组件开发更加安全。</p>
## 延伸阅读
- [Cursor 订阅与 Shadow DOM 组件开发](/channels?platform=cursor)
- [Cursor Pro / Business 官方价格与订阅](/official-prices)
- [Windsurf 与 Claude Code 订阅比价](/compare)
- [Cursor 模板与代码片段仓库](/templates)
- [Shadow DOM 完整教程与案例](/guides)
## 风险与边界
- Shadow DOM 的隔离性并非绝对:外部可以通过 JS、外部样式或事件绕过部分控制。
- 某些现代浏览器或框架对 closed 模式支持不完整,需测试 Cursor 内置浏览器环境。
- 过度滥用会导致调试复杂化(建议只在组件库中启用)。
- 以上内容仅供参考,非法律意见,实际效果以官方文档和测试环境为准。