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,但要注意你需要把所有想要的属性都手动补齐。