核心概念
理解 Shadow DOM 与 Slot:为什么模板和内容可以互不干扰。
一个页面,两个世界
注入模板后,每个页面的 <body> 会变成 Shadow Host,页面里出现两个互不干扰的世界:
- Light DOM:你(或 AI)写的内容,即
<main class="content">及其样式。 - Shadow DOM:模板里的 header、侧边栏、footer 及其样式。
<body> ← Shadow Host
├── #shadow-root (open) ← 模板世界
│ ├── <style> … </style>
│ ├── <header>站点标题</header>
│ ├── <nav>侧边栏导航</nav>
│ ├── <slot></slot> ← 内容投影口
│ └── <footer>版权</footer>
└── <main class="content"> ← 你的世界(被投影进 slot)
└── …页面内容…
样式为什么不会互相污染
Shadow DOM 提供的是双向样式隔离:
- 模板里
<style>写的选择器,只作用于 Shadow DOM 内部,出不来。 - 页面
<head>里的样式,只作用于 Light DOM,进不去。
这意味着:AI 在页面里写
nav { color: red },也不会影响模板里的导航栏。反过来,模板里重置 * { margin: 0 },也不会打乱正文的排版。
内容如何被"投影"进模板
关键在 <slot>。模板里的 <slot> 是一个占位符,浏览器会把 Light DOM 里没有被其它 slot 认领的顶层节点,全部投影到这里。
所以页面作者不需要知道模板长什么样,只要把内容放在 <body> 的顶层就行。
样式隔离的边界
有两个地方需要注意:
- 继承类属性会穿透:
color、font-family、line-height等可继承属性,会从 Host 继承进 Shadow DOM。若模板希望完全自主,需显式重置。 - CSS 自定义属性会穿透:
--var是设计令牌,能穿透 Shadow 边界。这正是"换肤"的钩子——模板可暴露--brand-color之类的变量供整站统一。
为什么不用 iframe
iframe 也能隔离,但代价大:SEO 不友好、无法共享字体与滚动、通信要 postMessage、每个页面都要多发一次请求。声明式 Shadow DOM 在同一个文档内完成隔离,没有这些负担。
下一步 → 页面怎么写