全局样式必须统一入口管理,即仅通过src/app.css和+layout.svelte中的引入;其他方式会导致热更新失效、覆盖不可控、复用困难。

全局样式必须统一入口管理,否则热更新失效、覆盖不可控、复用困难——src/app.css + +layout.svelte 中的 <style global></style> 是唯一可靠路径。
全局样式该放哪,而不是怎么放
别在任意组件里写 :global(body) 或重置规则。它会生效,但下次热更新可能丢样式;多处定义时覆盖顺序难预测;想复用还得复制粘贴。真正该全局的(字体、间距、CSS Reset、主题变量),全塞进 src/app.css。然后在 src/routes/+layout.svelte 顶部加:
<style global>
@import url('/app.css');
</style>
这样既走 Svelte 生命周期,又支持 PostCSS、HMR 正常、构建时可提取。
:global() 不是全局开关,是选择器穿透器
:global() 只放行括号内那一段选择器,且不能嵌套。写错就等于没写:
-
:global(.a .b)→ 整个选择器被放行,有效 -
:global(.a) .b→.a全局匹配,.b仍被局部化,大概率不生效 -
div :global(strong)→ 只影响本组件内<div> 下的 <code><strong></strong>,安全 -
:global(.third-party) button→ 想改第三方按钮?先确认它真渲染了带.third-party的容器,且没用$$props.class却没绑定到根节点 - 用 wrapper 包一层:
<div class="rich-content">{@html unsafeHtml}</div> - 在组件
<style></style>中写:.rich-content :global(h1) { font-size: 2.4rem; } - 别写
:global(.rich-content h1)——.rich-content是局部类,会被哈希化,:global()不处理它 -
<slot></slot>内容默认属于父组件作用域,子组件无法用普通选择器控制;要么父组件透传class,要么用:global()显式穿透,但要注意异步渲染时机 - 抽成
src/lib/styles/components.css - 再通过
<style global></style>引入布局文件 - 或者在
main.js里import '$lib/styles/components.css'—— 仅限极简项目,且你明确接受 HMR 失效风险
{@html} 和 <slot></slot> 里的样式怎么管
{@html} 插入的内容不带作用域属性,.content h1 这种写法无效:
什么时候该放弃 :global(),直接上外部 CSS 文件
如果你在三个以上组件里重复写 :global(.btn)、:global(.card),说明这些规则本就不该分散在组件中:
真正难的不是让样式“生效”,而是让变更、复用、调试都可预期。:global() 是手术刀,不是胶水;用错位置,比不用还危险。











