全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明

全局样式变量文件

src\assets\style\variables.scss

复制代码
/* 
CSS 自定义属性(--border-color)
- 定义位置:定义位置:通常放在一个全局样式文件中(例如 variables.scss),使用 :root 选择器定义,如 :root { --border-color: #ebeef5; }。
- 引入方式:该全局样式文件必须在应用入口(如 main.ts 或 App.vue)中引入一次,例如 import '@/assets/style/variables.scss',这样变量才会在整个应用生效。
- 使用方式:在任意组件的 <style> 中直接使用 var(--border-color),无需再导入该变量文件(因为已经全局引入过了)。
- 特点:运行时解析、可继承、支持动态修改,适合全局主题变量。
*/
:root {
  // ========== 颜色变量 ==========
  // 当前选中目标的背景色
  --current-selected-color: #daeafb;
  // 边框颜色
  // --border-color: #ebeef5;
  --border-color: #000;
  
  // ========== 尺寸变量 ==========
  // 短宽按钮,两个汉字,预留加载空间
  --short-btn-width: 70px;
  // 长宽按钮,四个汉字,预留加载空间
  --long-btn-width: 107px;
  // 表格行内短宽按钮,两个汉字,预留加载空间
  --table-row-short-btn-width: 50px;
  // 表格行内长宽按钮,四个汉字,预留加载空间
  --table-row-long-btn-width: 80px;
  // 对话框按钮
  --dialog-btn-width: 100px;
  // 阴影
  --box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  // 内阴影(inset),模糊半径20px(无偏移)
  --box-shadow-inset: inset 0 0 20px #d4def6;
}

/*
SCSS 变量($border-color)
- 定义位置:同样放在变量文件中,但无需 :root,直接 $border-color: #ebeef5;。
- 使用方式:如果通过构建工具(如 Vite 的 additionalData)全局注入,则组件中也无需手动导入;否则需要在每个组件的 <style lang="scss"> 中通过 @import 引入变量文件。
- 特点:编译时替换,不保留运行时变量。
- 缺点:如果多个组件都要使用,每个组件都要导入变量文件,稍微麻烦。
- 建议:如果坚持使用 SCSS 变量,推荐采用 Vite 的 additionalData 配置,实现全局注入,避免每个组件导入
*/
// ========== 颜色变量 ==========
// 边框颜色
$border-color: #000;

/*
【总结】两种方式都需要一次全局引入(CSS 变量是引入定义文件,SCSS 变量是引入变量文件或构建注入)。
关键区别在于:
- CSS 变量定义一次,运行时全局可用,组件使用时不需额外导入。
- SCSS 变量默认需要按需导入(除非配置全局注入),但编译后无运行时开销。
*/

应用示例

全局导入

src\main.ts

TypeScript 复制代码
// 使用侧效应导入,使用别名 @(相当于./src)全局引入自定义样式变量
import "@/assets/style/variables.scss";

组件使用

src\components\layout\LayoutBasePage.vue

html 复制代码
<script setup lang="ts">
/**
 * 基础页面布局: 头部、主内容、底部
 */
defineOptions({
  name: "LayoutBasePage"
});
</script>

<template>
  <el-container class="container">
    <el-header class="header">
      <!-- 头部区域 -->
      <slot name="header" />
    </el-header>

    <el-main class="main">
      <!-- 主要区域 -->
      <slot name="main" />
    </el-main>

    <el-footer class="footer">
      <!-- 底部区域 -->
      <slot name="footer" />
    </el-footer>
  </el-container>
</template>

<style scoped lang="scss">
// SCSS 变量,如果没有配置全局注入,每个组件都要手动导入
@import "@/assets/style/variables.scss";

// 选择 container 所有直接子元素(不包括孙级)
.container > * {
  margin: 0;
  padding: 0;
}

.container {
  height: 100%;
  border: 1px solid $border-color; // SCSS 变量($border-color)

  .header {
    height: auto;
  }

  .main {
    border-top: 1px solid var(--border-color); // CSS 自定义属性(--border-color)
  }

  .footer {
    height: auto;
    padding: 0 10px;
  }
}
</style>

详细讲解

CSS 自定义属性(--border-color

  • 定义位置 :通常放在一个全局样式文件中(例如 variables.scss),使用 :root 选择器定义,如 :root { --border-color: #ebeef5; }

  • 引入方式 :该全局样式文件必须在应用入口(如 main.tsApp.vue)中引入一次,例如 import '@/assets/style/variables.scss',这样变量才会在整个应用生效。

  • 使用方式 :在任意组件的 <style> 中直接使用 var(--border-color)无需再导入该变量文件(因为已经全局引入过了)。

  • 特点:运行时解析、可继承、支持动态修改,适合全局主题变量。


对比 SCSS 变量($border-color

  • 定义位置 :同样放在变量文件中,但无需 :root,直接 $border-color: #ebeef5;

  • 使用方式 :如果通过构建工具(如 Vite 的 additionalData)全局注入,则组件中也无需手动导入;否则需要在每个组件的 <style lang="scss"> 中通过 @import 引入变量文件。

  • 特点:编译时替换,不保留运行时变量。


总结

两种方式都需要一次全局引入(CSS 变量是引入定义文件,SCSS 变量是引入变量文件或构建注入)。关键区别在于:

  • CSS 变量定义一次,运行时全局可用,组件使用时不需额外导入。

  • SCSS 变量默认需要按需导入(除非配置全局注入),但编译后无运行时开销。


方案一:使用 CSS 自定义属性(推荐)

1. 定义全局变量文件 src/assets/style/variables.scss

scss

复制代码
// variables.scss
:root {
  /* 边框颜色 */
  --border-color: #ebeef5;
}

2. 在应用入口 main.ts 中全局引入

ts

复制代码
// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import '@/assets/style/variables.scss'; // 全局引入一次

createApp(App).mount('#app');

3. 在任意组件中使用

vue

复制代码
<!-- LayoutBasePage.vue -->
<style scoped lang="scss">
.container {
  border: 1px solid var(--border-color); /* 使用 CSS 变量 */
}
</style>

vue

复制代码
<!-- AcceptQuery.vue -->
<style scoped lang="scss">
.aside {
  border-right: 1px solid var(--border-color);
}
</style>

优点 :组件无需导入变量文件,因为变量已在全局 :root 中定义并随入口文件加载。


方案二:使用 SCSS 变量(需配置全局注入)

1. 定义 SCSS 变量文件 src/assets/style/variables.scss

scss

复制代码
// variables.scss
$border-color: #ebeef5;

2. 配置构建工具全局注入(Vite 示例)

ts

复制代码
// vite.config.ts
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
  plugins: [vue()],
  css: {
    preprocessorOptions: {
      scss: {
        // 全局注入,每个组件的 <style lang="scss"> 自动添加此导入
        additionalData: `@import "@/assets/style/variables.scss";`
      }
    }
  }
});

3. 组件中直接使用(无需手动导入)

vue

复制代码
<!-- LayoutBasePage.vue -->
<style scoped lang="scss">
.container {
  border: 1px solid $border-color; /* 直接使用 SCSS 变量 */
}
</style>

两个方案对比

方案 定义方式 组件使用 是否需要额外导入/配置
CSS 变量 :root { --border-color: #ebeef5; } var(--border-color) 只需在入口 main.ts 导入一次
SCSS 变量 $border-color: #ebeef5; $border-color 需通过构建工具全局注入,或每个组件手动 @import

实际替换示例

假设你要统一替换 LayoutBasePage.vueAcceptQuery.vue 中的边框颜色:

LayoutBasePage.vue(使用 CSS 变量)

scss

复制代码
.container {
  height: 100%;
  border: 1px solid var(--border-color);

  .main {
    border-top: 1px solid var(--border-color);
  }
}

AcceptQuery.vue(使用 CSS 变量)

scss

复制代码
.layout-container {
  height: 100%;
}

.aside {
  width: 150px;
  border-right: 1px solid var(--border-color);
}

.footer {
  height: 42px;
  padding: 5px;
  border-top: 1px solid var(--border-color);
}

总结 :推荐使用 CSS 自定义属性,因为引入一次即可全局使用,无需关心组件导入问题,且未来换肤更灵活。如果团队更习惯 SCSS 变量,则建议配合 Vite 全局注入减少重复导入。


下面是使用 SCSS 变量但未配置全局注入 时的示例,即需要手动在每个组件的 <style lang="scss"> 中导入变量文件。


1. 定义 SCSS 变量文件

创建 src/assets/style/variables.scss

scss

复制代码
// variables.scss
$border-color: #ebeef5;
$border-width: 1px;
$border-style: solid;

2. 在组件中手动导入并使用

示例:LayoutBasePage.vue

vue

复制代码
<style scoped lang="scss">
// 手动导入变量文件(路径根据项目调整)
@import "@/assets/style/variables.scss";

.container {
  height: 100%;
  border: $border-width $border-style $border-color; // 使用变量
  .main {
    border-top: $border-width $border-style $border-color;
  }
}
</style>
示例:AcceptQuery.vue

vue

复制代码
<style scoped lang="scss">
@import "@/assets/style/variables.scss"; // 每个组件都要写这一行

.aside {
  width: 150px;
  border-right: $border-width $border-style $border-color;
}

.footer {
  border-top: $border-width $border-style $border-color;
}
</style>
示例:AcceptModify.vue

vue

复制代码
<style scoped lang="scss">
@import "@/assets/style/variables.scss"; // 同样需要导入

.layout-container {
  border: $border-width $border-style $border-color;
}
</style>

3. 缺点与解决方案

缺点

  • 每个使用 SCSS 变量的组件都必须手动 @import 变量文件,当组件数量多时,重复导入显得繁琐,且容易遗漏。

解决方案

  • 使用构建工具(如 Vite 的 additionalData)全局注入变量文件,从而避免在每个组件中重复导入。

  • 或改用 CSS 自定义属性(--border-color),在入口文件全局引入一次,组件中直接使用 var(),无需导入。


总结

未配置全局注入时,SCSS 变量需要手动导入,虽然可行但不够便捷。如果项目开始时就计划大量使用 SCSS 变量,建议尽早配置全局注入,以提升开发体验。

相关推荐
默_笙2 小时前
❗ 给金鱼装记忆(上):从白板到笔记本,AI 的短期记忆生存指南
前端·javascript
兜里只有三分钱~2 小时前
翻卡_3D 的仪式感,和三个让它穿帮的写法
javascript·css·3d
mayaairi3 小时前
Vue2 组件通讯(四):v-model、scoped样式、mixins与plugins
前端·javascript·vue.js
前端炒粉3 小时前
DOM 常用 API 速查表
开发语言·javascript·ecmascript
星云API技术支持3 小时前
企业微信二次开发:如何建立统一的错误处理、日志与请求追踪机制
javascript·企业微信·ruby
mayaairi6 小时前
Vue2 组件通讯(二):ref、自定义事件与provide/inject实战
前端·javascript·vue.js
开开心心就好6 小时前
PDF图片去水印软件,支持批量处理页面
前端·javascript·人工智能·智能手机·pdf·语音识别
我的世界洛天依7 小时前
【胡桃讲编程】JS 入门第 1 课:Hello World,开启你的 JavaScript 编程之旅
javascript
是立不是利7 小时前
深入理解JavaScript事件委托
开发语言·前端·javascript