最推荐在 main.ts 或 main.js 中 import 全局 css 文件,因其同步执行、优先注入、确保 :root 变量全局可用,且避免组件级样式加载时机与覆盖问题。

在 main.ts 或 main.js 中直接 import 全局 CSS 文件
这是最稳定、最推荐的方式,适用于 reset、字体定义、CSS 变量声明等真正需要全局生效的基础样式。
Vue 构建过程会把这类 import 的 CSS 打包进最终的 style.css,浏览器加载时即全局可用,不依赖组件挂载顺序或作用域机制。
- 必须放在
createApp(App)调用之前,否则部分样式(尤其是:root变量)可能在组件渲染时还未注入 - 路径需正确,推荐使用
@/styles/vars.css这类别名写法(确保 Vite 或 Vue CLI 已配置@指向src) - 避免在
App.vue的<style></style>里@import,它会被视为组件级样式,无法保证全局优先级和解析时机
为什么不用 <style></style> 标签在 App.vue 里写全局样式
<style></style>(无属性)确实会生成全局 CSS,但它仍受组件编译顺序和打包 chunk 分割影响。尤其当项目启用 code-splitting 时,App.vue 的样式可能晚于某些子组件渲染,导致初始 DOM 缺失预期样式(比如 body 背景没生效)。
更隐蔽的问题是:如果多个组件都写了同名 <style></style> 块,它们会按引入顺序合并,容易被后加载的样式意外覆盖。
- 例如
App.vue里写body { margin: 0 },但某个路由组件也带<style></style>且含body { margin: 8px },后者可能因模块加载时机靠后而生效 - 而
main.ts的 import 是同步、确定、最先执行的,无此风险
如何让全局样式中的 CSS 变量在所有组件中可用
CSS 变量(--xxx)必须声明在 :root 或 html 选择器下才具有真正的全局作用域。仅靠 <style></style> 标签不够,关键看声明位置是否能被所有元素继承。
典型错误是把变量写在 .container 这类局部类名下,结果只有该类后代才能读取 var(--xxx)。
- 正确写法:
:root { --primary-color: #1890ff; },然后在任意组件 template 中用style="color: var(--primary-color)"或 CSS 里写color: var(--primary-color) - 务必确认该 CSS 文件被
main.ts同步导入,且未被任何构建插件误删(如 purgecss 配置不当会清掉未显式使用的:root变量) - 不要依赖
<style scoped></style>或<style module></style>里的:root—— scoped 会加属性选择器,module 会哈希类名,都会破坏变量的全局性
避免在组件内用 :global() 替代全局引入
:global() 是为了解决 scoped 样式“漏出”问题而设的临时手段,比如想让某个按钮样式穿透到子组件内部。它不是全局样式的替代方案。
滥用 :global() 会导致样式分散、维护困难,且无法享受 CSS tree-shaking 和变量复用等构建优化。
- 例如在 20 个组件里都写
:global(body) { background: #fff },最终打包会重复 20 次,而非合并为一条规则 - 它也不支持
@import、@layer等现代 CSS 特性,纯属运行时模拟,语义和性能都不如真实全局引入 - 真正需要全局基础样式的地方,就该回归
main.ts+import这一明确、可控、可调试的路径
@import 语句(比如引入第三方 reset 或字体)是否被构建工具正确解析。Vite 默认支持,但 Webpack 需要 css-loader 配置 importLoaders,否则 @import 会被当作普通字符串忽略。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











