Vue 项目中全局样式的正确写法:不要把字体和主题写在 #app 上

一、问题背景

在 Vue 项目中,我们通常会在入口文件 App.vue 或根元素 #app 上编写样式。例如设置字体、主题色、背景色等。然而,许多开发者容易忽略一个细节:并不是所有的 DOM 元素都在 #app 内部渲染

这会导致一些组件(如使用 teleportbody 的弹窗、提示框、遮罩层等)无法继承到 #app 的样式,从而出现字体错乱、主题色不生效等问题。

二、teleport 导致的样式隔离问题

Vue 的 teleport 特性允许组件内容渲染到 #app 以外的节点中,例如:

html 复制代码
<teleport to="body">
  <div class="global-dialog">我是弹窗</div>
</teleport>

此时,这个弹窗的 DOM 实际上是直接插入到 <body> 下,而不是 Vue 挂载的 #app 内部。

如果我们之前把全局样式(如字体、颜色变量)都写在 #app 上,比如:

css 复制代码
#app {
  font-family: "PingFang SC", sans-serif;
  color: var(--font-color);
}

那么 teleport 到 body 的元素将无法继承这些样式 ,因为它并不在 #app 的作用范围中。

三、正确的全局样式写法

全局样式应当写在 htmlbody 上,而不是 #app

推荐写法:

css 复制代码
html,
body {
  font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
  color: var(--font-color, #333);
  background-color: var(--bg-color, #fff);
}

#app {
  min-height: 100%;
  display: flex;
  flex-direction: column;
}

这样,无论组件内容挂载在哪个节点下(包括 body#appteleport 节点),都能共享同样的全局主题样式。

四、实际项目中的应用建议

  1. 字体、颜色、主题变量统一写在 html, body 中。

    这样能确保任何层级的组件都能继承这些基础样式。

  2. #app 用于布局和结构控制。

    比如 display: flex;min-height: 100vh;overflow: hidden; 等结构性样式。

  3. 全局 CSS 变量放在 :root 或 html。

    示例:

    css 复制代码
    :root {
      --color-primary: #1677ff;
      --font-color: #333;
      --bg-color: #fff;
    }
  4. 重置样式或主题文件在入口处引入。

    如在 main.ts 中:

    css 复制代码
    import "@/styles/reset.scss"
    import "@/styles/theme.scss"

五、总结

Vue 项目中的全局样式不应依赖 #app,而应当绑定在 htmlbody 上。

这是因为部分组件(尤其是通过 teleport 实现的弹窗、浮层等)并不会在 #app 节点内渲染。

良好的样式结构分层能让整个项目在视觉和逻辑上更加统一,避免组件层级带来的样式继承问题。

相关推荐
进击的明明12 分钟前
闭包:JavaScript里的“随身背包” 🎒
前端·javascript·面试
紫幽1 小时前
从 0 用 Vue 做屏并生成 LVGL 单片机代码(完整源码备忘)
前端·单片机
郭邯1 小时前
用 AI 辅助开发一个文件大小转换工具:从需求到上线的完整过程
前端
勾勾圈圈蛋蛋1 小时前
前中台项目
前端
触底反弹1 小时前
🔐 前端鉴权不再难!手把手带你搞懂 JWT + Zustand + Axios 的完整登录方案
前端·axios
打呵欠的猫2 小时前
我用 AI 写了一个"需求翻译器",产品的 PRD 直接变成开发任务清单
前端·ai编程
fatcoder2 小时前
玩转Nginx 09 — 运维排障:三场"火灾"实战演练
前端·后端·nginx
前端玩坑坑2 小时前
View Transitions API 入门教程,优雅过度
前端
李高钢2 小时前
WPF MVVM Light(三):RelayCommand 命令与 Messenger 消息
前端·c#·wpf
lichenyang4533 小时前
Socket.IO 原理与技术选型
前端