unocss 主题extendTheme 和theme的区别?

267 阅读3分钟

1. theme 和 extendTheme 区别

theme

  • 功能完全覆盖默认主题(不是“合并”或“扩展”)。
  • 用法:如果你在 theme: { ... } 里定义内容,UnoCSS 会只用你写的内容,默认主题的配置会丢失。
  • 适合场景:你想彻底自定义一套主题,不需要官方默认的所有颜色、间距、字体等。

例子:

TypeScript

theme: {
  colors: {
    primary: '#ff0000'
  }
}
// 此时只剩 primary,默认的如 blue, red, gray 等全没了

extendTheme

  • 功能:**在默认主题的基础上“扩展”或“覆盖”**部分配置,其他未改动的仍然保留官方默认。
  • 用法extendTheme: (defaultTheme) => { ... },你可以 return 一个合并的新对象。
  • 适合场景绝大多数业务项目推荐用,比如你只想加几个自定义色值、变量,其他用官方默认就行。

例子:

TypeScript

extendTheme: (defaultTheme) => ({
  ...defaultTheme,
  colors: {
    ...defaultTheme.colors,
    primary: 'var(--primary)',
    brand: '#123456'
  }
})
// 这样默认的所有色值都还在,只是多加了 primary 和 brand

2. 我的代码

import type { Theme } from '@unocss/preset-wind4'
import { createRemToPxProcessor } from '@unocss/preset-wind4/utils'
import {
  defineConfig,
  presetAttributify,
  presetIcons,
  presetTypography,
  presetWebFonts,
  presetWind4,
  transformerVariantGroup,
} from 'unocss'

// 自定义主题,变量到style/main.css中定义
const selfTheme: Theme['defaults'] = {
  // 这里的颜色,虽然写了--primary 但在main.css中使用记得写成--color-primary
  colors: {
    primary: "var(--primary)", // 只要你的class 中出现primary 就会被匹配,进而生成颜色
    secondary: 'var(--secondary)',
    background: 'var(--background)',
  },
}

export default defineConfig({
  shortcuts: [
    // 示例:定义一些快捷样式
    ['btn', 'px-4 py-2 rounded text-white bg-primary hover:bg-secondary'],
  ],
  // theme是完全覆盖unocss带的默认主题,一般使用extendTheme,theme可以不写。
  theme: {
  },
  // 继承默认主题,添加自定义主题去覆盖默认主题。定义主题使用css变量,这样跟换css 变量实现主题切换。
  extendTheme: (defaultTheme: Theme['defaults']) => {
    return {
      ...defaultTheme,//默认主题
      ...selfTheme, // 你设计的主题
    }
  },

  presets: [
    presetWind4({
      preflights: {
        reset: true,
        theme: {
          mode: true,
          process: createRemToPxProcessor(),

        },
      },
    }),
    presetAttributify(),
    presetIcons(),
    presetTypography(),
    presetWebFonts({
      themeKey: 'font',
    }),
  ],
  postprocess: [createRemToPxProcessor()],
  transformers: [
    transformerVariantGroup(),
  ],
})

//main.css
/* Light Theme */
body {
  /*  使用变量主题,只需要定义变量,在文件中使用就好 */
  --colors-primary: #3b82f6;
  /* 明亮蓝色 */
  --colors-opposite: #e0e7ef;
  /* 浅灰蓝,反差柔和 */
  --colors-secondary: #06b6d4;
  /* 青蓝色,点缀 */
  --background: #f9fafb;
  /* 亮白灰 */
  --text: #23272f;
  /* 深灰黑,主文字 */
  background-color: var(--background);
  color: var(--text);
}

/* Dark Theme */
.dark-mode body {
  --colors-primary: #60a5fa;
  /* 柔和亮蓝 */
  --colors-opposite: #1e293b;
  /* 深蓝灰,背景 */
  --colors-secondary: #38bdf8;
  /* 亮青蓝,点缀 */
  --background: #0f172a;
  /* 极深蓝灰,主背景 */
  --text: #e0e7ef;
  /* 明亮灰白,主文字 */
  background-color: var(--background);
  color: var(--text);
}

/* Sepia Theme */
.sepia-mode body {
  --colors-primary: #a5855b;
  /* 柔和棕金色 */
  --colors-opposite: #f4e9d8;
  /* 暖米色,背景 */
  --colors-secondary: #c9a66b;
  /* 浅金黄,点缀 */
  --background: #f4e9d8;
  /* 米色,主背景 */
  --text: #4b3f2a;
  /* 深棕色,主文字 */
  background-color: var(--background);
  color: var(--text);
}

  • theme 设成空对象,其实等价于不用 theme 字段。
  • 主要靠 extendTheme 去继承和扩展默认主题,这是推荐做法

3. 总结对比表

方式默认主题会保留吗?适合场景行为
theme❌ 不会全自定义新主题只用你给的内容,默认主题全部丢弃
extendTheme✅ 会继承加点自定义默认主题 + 你的自定义(合并/覆盖)

4. 推荐实践

  • 一般项目(建议) :用 extendTheme,这样不会丢失官方默认色、间距、字体,只增补你需要的。
  • 特殊项目(全部自定义) :用 theme,但要注意你需要把所有想要的属性都手动补齐。