:host 必须写在 shadow dom 内部的 中,外部 css、 样式或内联 style 均无效;需动态创建 插入 shadowroot,且 :host() 括号内必须为合法选择器,如 :host([disabled]) 或 :host(.primary),空括号或错误语法将被静默忽略。

:host 必须写在 Shadow DOM 内部的 <style></style> 里
外部 CSS 文件、 中的 <style></style>,甚至宿主元素上的 style 属性,对 :host 都无效。浏览器不会报错,也不会警告,只是静默忽略整条规则。
正确做法是:在调用 attachShadow({ mode: 'open' }) 后,动态创建 <style></style> 元素并插入到 shadowRoot:
const shadow = this.attachShadow({ mode: 'open' });
const style = document.createElement('style');
style.textContent = `
:host {
display: block;
font-family: system-ui, sans-serif;
}
`;
shadow.appendChild(style);
-
mode: 'closed'时shadowRoot不可访问,无法注入 —— 开发阶段请固定用'open' - 不能用
shadow.innerHTML = '<style>...</style>'—— 多数浏览器会忽略其中的样式内容 - 避免依赖
<link rel="stylesheet">—— 它在 Shadow DOM 中不解析,除非用adoptedStyleSheets(更重,且需手动管理)
:host() 括号里必须填合法选择器,空括号无效
:host() 不是函数调用,而是接受一个完整选择器作为参数。写成 :host()、:host("primary") 或 :host(primary) 全部非法,整条规则被跳过,无提示。
真正有效的写法只有:
-
:host([disabled])—— 匹配宿主存在disabled布尔属性 -
:host([size="large"])—— 属性值必须字面量完全一致(含引号、大小写) -
:host(.primary)—— 匹配宿主class中包含primary -
:host(#my-btn)—— 极少用,语义弱,仅匹配id为my-btn的宿主
复合写法也支持,比如 :host(.btn[variant="outline"]),但注意属性值必须严格匹配。
:host 后跟子选择器,只作用于 Shadow DOM 内部节点
:host .header 并不是“宿主元素下的 .header”,而是:宿主自身满足 :host 条件,且其 Shadow DOM 内部有后代节点 .header。它不会穿透到 <slot></slot> 投影进来的内容里。
投影内容(light DOM 子节点)需用 ::slotted(.header) 控制,而不是 :host .header。
-
:host > .header只匹配shadowRoot直接子元素,不包括<slot></slot>分发后的位置 - 若想同时控制宿主和 slot 内容,得组合使用
:host+::slotted(*)+::part(xxx)(后者需组件内显式标记part)
继承属性会“漏入”,但 :host 不负责控制继承
宿主上定义的 font-size、color、line-height 等可继承属性,会自然影响 Shadow DOM 内未显式重置的子元素 —— 这是 CSS 继承机制本身的行为,不是 :host 的功能。
:host 只控制宿主自身的样式,不开启/关闭继承。如果组件需要字体完全独立,就得在 shadowRoot 的 <style></style> 中对根节点或具体元素显式重置,比如:
:host { font-size: 1rem; }
* { font-size: inherit; }
容易被忽略的是:你写的 :host 规则,哪怕只设了 display,也得意识到宿主上已有的 color 或 font-family 依然会向下渗透 —— 这种“漏入”不是 bug,是设计使然,但常被当成样式失控。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











