自定义主题

Uniboot UI 采用 BEM 风格的 CSS,便于覆盖样式。若需要大规模替换样式(例如将主题色由蓝改为橙或绿),逐个覆盖往往效率不高。

我们提供四种调整样式变量的方式。

修改主题色

自定义主题示例:

通过 SCSS 变量

theme-chalk 使用 SCSS 编写。可在 packages/theme-chalk/src/common/var.scss 查看变量定义。

WARNING

我们已使用 Sass 模块(sass:map 等)与 @use 重构全部 SCSS 变量,并借此解决 @import 带来的重复输出问题。

延伸阅读:Introducing Sass Modules | CSS-TRICKS

例如使用 $colors 这一 map 保存多种颜色;$notification 则保存 notification 组件相关变量。

后续会补充各组件可定制变量的文档;也可直接阅读源码 var.scss

scss
$colors: () !default;
$colors: map.deep-merge(
  (
    'white': #ffffff,
    'black': #000000,
    'primary': (
      'base': #2f54eb,
    ),
    'success': (
      'base': #67c23a,
    ),
    'warning': (
      'base': #e6a23c,
    ),
    'danger': (
      'base': #f56c6c,
    ),
    'error': (
      'base': #f56c6c,
    ),
    'info': (
      'base': #909399,
    ),
  ),
  $colors
);

如何覆盖?

若项目同样使用 SCSS,可直接覆盖 Uniboot UI 的样式变量。新建样式文件,例如 styles/element/index.scss

WARNING

请使用 @use 'xxx.scss' as *;,不要使用 @import 'xxx.scss';

Sass 团队计划在未来移除 @import

Sass: @useSass: @import

styles/element/index.scss
scss
/* 按需覆盖 */
@forward 'uniboot-ui/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': (
      'base': green,
    ),
  )
);

// 若仅为按需引入,可忽略下文
// 若要引入全部样式:
// @use "uniboot-ui/theme-chalk/src/index.scss" as *;

然后在项目入口引入该样式文件,而不是使用内置 CSS:

TIP

请在 uniboot-ui 的 scss 之前引入 element/index.scss,以免 Sass 混合变量时出现问题——需要先根据你的自定义变量生成 light-x 等。

请创建 element/index.scss,将你的变量与 uniboot-ui 变量合并。(若在 ts 中分别引入,将无法合并。)

TIP

此外,请把你的业务 scss 与 element 变量 scss 区分开。若混在一起,每次热更新 uniboot-ui 都会编译大量 scss,速度会变慢。

main.ts
ts
import { createApp } from 'vue'
import './styles/element/index.scss'
import UnibootUI from 'uniboot-ui'
import App from './App.vue'

const app = createApp(App)
app.use(UnibootUI)

若使用 Vite,且希望在按需引入时自定义主题,可使用 scss.additionalData,让每个组件的 scss 编译时都带上变量文件。

vite.config.ts
ts
import path from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// 也可使用 unplugin-vue-components
// import Components from 'unplugin-vue-components/vite'
// import { UnibootUIResolver } from 'uniboot-ui/resolver'
// 或使用 unplugin-uniboot-ui
import UnibootUI from 'unplugin-uniboot-ui/vite'

export default defineConfig({
  resolve: {
    alias: {
      '~/': `${path.resolve(__dirname, 'src')}/`,
    },
  },
  css: {
    preprocessorOptions: {
      scss: {
        additionalData: `@use "~/styles/element/index.scss" as *;`,
      },
    },
  },
  plugins: [
    vue(),
    // 使用 unplugin-vue-components
    // Components({
    //   resolvers: [
    //     UnibootUIResolver({
    //       importStyle: "sass",
    //       // directives: true,
    //       // version: "2.1.5",
    //     }),
    //   ],
    // }),
    // 或使用 unplugin-uniboot-ui
    UnibootUI({
      useSource: true,
    }),
  ],
})

若使用 Webpack,且希望在按需引入时自定义主题:

webpack.config.js
js
// 使用 unplugin-uniboot-ui

import UnibootUI from 'unplugin-uniboot-ui/webpack'

export default defineConfig({
  css: {
    loaderOptions: {
      scss: {
        additionalData: `@use "~/styles/element/index.scss" as *;`,
      },
    },
  },
  plugins: [
    UnibootUI({
      useSource: true,
    }),
  ],
})

通过 CSS 变量

CSS 变量已被几乎所有现代浏览器支持。(IE:?)

详见 MDN:Using CSS custom properties (variables)

我们已用 CSS 变量重构了几乎全部组件的样式体系。

TIP

它与 SCSS 变量体系兼容:通过 SCSS 函数自动生成供运行时使用的 CSS 变量。

这意味着可以动态修改组件内单个变量,实现更细粒度定制,而无需改 scss 并重新编译。

后续会在各组件文档中补充 CSS 变量命名与作用说明。

示例:

css
:root {
  --u-color-primary: green;
}

若只想定制某个组件,可为该组件添加行内样式:

html
<u-tag style="--u-tag-bg-color: red">Tag</u-tag>

出于性能考虑,更推荐在某一 class 下设置 CSS 变量,而不是全局 :root

css
.custom-class {
  --u-tag-bg-color: red;
}

若希望通过脚本控制 CSS 变量,可参考:

ts
// document.documentElement 为全局
const el = document.documentElement
// const el = document.getElementById('xxx')

// 读取
getComputedStyle(el).getPropertyValue(`--u-color-primary`)

// 设置
el.style['--u-color-primary'] = 'red'

更优雅的方式见 useCssVar | VueUse