ProComponents, templates & AI tooling
HeroUI
27.7k

主题

使用 CSS 变量和全局样式自定义 HeroUI 的设计系统

HeroUI 使用 CSS 变量和 BEM 类来实现主题化。你可以使用标准 CSS 自定义从颜色到组件样式的所有内容。

想要创建你自己的主题? 试试 主题构建器,以可视化方式自定义颜色、圆角、字体等,然后导出 CSS 用于你的项目。

工作原理

HeroUI 的主题系统构建于 Tailwind CSS v4 的主题之上。当你导入 @heroui/styles 时,它会使用 Tailwind 的内置调色板,将其映射到语义化变量,自动在浅色和深色主题之间切换,并使用 CSS 层和 @theme 指令进行组织。

命名规则:

  • 不带后缀的颜色用作背景(例如 --accent
  • -foreground 后缀的颜色用于该背景上的文本(例如 --accent-foreground

快速开始

应用主题: 将主题类添加到 HTML 并将颜色应用到 body 上:

<html class="light" data-theme="light">
  <body class="bg-background text-foreground">
    <!-- Your app -->
  </body>
</html>

切换主题:

<!-- Light theme -->
<html class="light" data-theme="light">

<!-- Dark theme -->
<html class="dark" data-theme="dark">

使用 next-themes 以编程方式切换主题(适用于 Next.js):

首先,用 ThemeProvider 包装你的应用:

// app/providers.tsx
"use client";

import { ThemeProvider } from "next-themes";

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <ThemeProvider attribute="class" defaultTheme="light">
      {children}
    </ThemeProvider>
  );
}
// app/layout.tsx
import { Providers } from "./providers";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className="bg-background text-foreground">
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

然后使用 useTheme 在主题之间切换:

"use client";

import { useTheme } from "next-themes";

export function ThemeSwitch() {
  const { theme, setTheme } = useTheme();

  return (
    <button onClick={() => setTheme(theme === "dark" ? "light" : "dark")}>
      Toggle {theme === "dark" ? "Light" : "Dark"} Mode
    </button>
  );
}

覆盖颜色:

/* app/globals.css */
@import "tailwindcss";
@import "@heroui/styles";

:root {
  /* Override any color variable */
  --accent: oklch(0.7 0.25 260);
  --success: oklch(0.65 0.15 155);
}

注意:完整的调色板和视觉参考请参见 颜色

深色模式:如需基于 next-themes 与 HeroUI useTheme 钩子的完整配置指南,请参见 深色模式

创建你自己的主题:

/* src/themes/ocean.css */
@layer base {
  /* Ocean Light */
  [data-theme="ocean"] {
    color-scheme: light;

使用你的主题:

/* app/globals.css */
@layer theme, base, components, utilities;

@import "tailwindcss";
@import "@heroui/styles";

@import "./src/themes/ocean.css" layer(theme); 

应用你的主题:

<!-- index.html -->

<!-- Light ocean -->
<html data-theme="ocean">

<!-- Dark ocean -->
<html data-theme="ocean-dark">

自定义组件

全局组件样式: 使用 BEM 类覆盖任何组件:

@layer components {
  /* Customize buttons */
  .button {
    @apply font-semibold tracking-wide;
  }

  .button--primary {
    @apply bg-blue-600 hover:bg-blue-700;
  }

  /* Customize accordions */
  .accordion__trigger {
    @apply text-lg font-bold;
  }
}

注意:完整的样式参考请参见 样式

查找组件类名: 每个组件文档页面都会列出所有可用的类名(基类、修饰符、元素、状态)。示例:Button 类名

导入策略

完整导入(推荐): 两行代码即可获得全部内容:

@import "tailwindcss";
@import "@heroui/styles";

按需导入: 只导入你需要的内容:

/* Define layers */
@layer theme, base, components, utilities;

/* Base requirements */
@import "tailwindcss";
@import "@heroui/styles/base" layer(base);
/* OR specific base file */
@import "@heroui/styles/base/base.css" layer(base);

/* Theme variables */
@import "@heroui/styles/themes/shared/theme.css" layer(theme);
@import "@heroui/styles/themes/default" layer(theme);
/* OR specific theme files */
@import "@heroui/styles/themes/default/index.css" layer(theme);
@import "@heroui/styles/themes/default/variables.css" layer(theme);

/* Components (all components) */
@import "@heroui/styles/components" layer(components);
/* OR specific component files */
@import "@heroui/styles/components/index.css" layer(components);
@import "@heroui/styles/components/button.css" layer(components);
@import "@heroui/styles/components/accordion.css" layer(components);

/* Utilities (optional) */
@import "@heroui/styles/utilities" layer(utilities);

/* Variants (optional) */
@import "@heroui/styles/variants" layer(utilities);

注意:目录导入(例如 @heroui/styles/components)会自动解析为其对应的 index.css 文件。使用显式文件路径(例如 @heroui/styles/components/button.css)来导入单个组件的样式。

Headless 模式: 从头开始构建你自己的样式:

@import "tailwindcss";
@import "@heroui/styles/base/base.css";

/* Your custom styles */
.button {
  /* Your button styles */
}

添加自定义颜色

将你自己的语义化颜色添加到主题中:

/* Define in both light and dark themes */
:root,
[data-theme="light"] {
  --info: oklch(0.6 0.15 210);
  --info-foreground: oklch(0.98 0 0);
}

.dark,
[data-theme="dark"] {
  --info: oklch(0.7 0.12 210);
  --info-foreground: oklch(0.15 0 0);
}

/* Make the color available to Tailwind */
@theme inline {
  --color-info: var(--info);
  --color-info-foreground: var(--info-foreground);
}

现在你可以在组件中使用它:

<div className="bg-info text-info-foreground">Info message</div>

变量参考

HeroUI 在 variables.css 中定义了三种类型的变量:

  1. 基础变量(Base Variables) — 不会变化的值,例如 --white--black、间距以及排版
  2. 主题变量(Theme Variables) — 在浅色 / 深色主题之间切换的颜色,以及滚动条令牌(--scrollbar-thumb--scrollbar-width 等)
  3. 计算变量(Calculated Variables) — 悬停状态、柔和(soft)变体以及边框 / 分隔线层级(每个浅色 / 深色主题中的 Calculated Colors 区块,使用 color-mix() 计算)

如需完整参考,请查阅:颜色文档默认主题变量共享主题工具

Tailwind 主题桥接(@theme inline):

themes/shared/theme.css 将语义化变量映射为 Tailwind 令牌(--color-*--radius-*--ease-*)。计算颜色引用的是 variables.css 中的底层变量(例如 --surface-hover--accent-soft)—— 它们并不会在该文件中通过 color-mix() 内联展开:

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);

  --color-surface: var(--surface);

表单控件依赖 --field-* 主题变量。悬停、聚焦及边框变体定义于 variables.cssCalculated Colors 区块中,并在 theme.css 中映射到 Tailwind 令牌(例如 --color-field-hover: var(--field-hover))。在你的主题中覆盖 --field-background--field-hover 及相关令牌,即可重新设计输入框、复选框、单选框和 OTP 输入槽的样式,而不会影响按钮或卡片等表面(surface)。

滚动条

HeroUI 为组件中的滚动区域(表格、弹出框、抽屉等)应用统一的滚动条样式。滚动条使用标准 CSS 属性(scrollbar-widthscrollbar-colorscrollbar-gutter),不再依赖 ::-webkit-scrollbar 覆盖。

模式 — 在 <html>、组件根元素或滚动插槽上设置 data-scrollbar

模式data-scrollbar行为
HeroUI 纤细(未设置)thin使用主题令牌呈现的纤细滑块
操作系统 / 浏览器default原生滚动条(auto
隐藏none不显示滚动条(scrollbar-width: none
<!-- 全局使用原生滚动条 -->
<html data-scrollbar="default">

<!-- 在某个子树中恢复 HeroUI 滚动条 -->
<main data-scrollbar="thin">
  ...
</main>

<!-- 在某个子树中隐藏滚动条(例如弹出框) -->
<div data-scrollbar="none">
  ...
</div>

主题变量 — 在 variables.css 的浅色与深色主题区块中定义:

变量描述
--scrollbar-thumb滑块颜色(默认通过 color-mix 混入 15% 的 --foreground
--scrollbar-track轨道颜色(默认 transparent
--scrollbar-gutter滚动条间隙(默认 auto
--scrollbar-widthscrollbar-width 属性(默认 thin
--scrollbar-colorscrollbar-color 属性(默认为滑块颜色 + 轨道颜色)
--scrollbar--scrollbar-thumb 的旧版别名

全局自定义:

/* app/globals.css */
:root {
  --scrollbar-thumb: color-mix(in oklch, var(--accent) 30%, transparent);
  --scrollbar-gutter: auto;
}

按滚动插槽 — 在组件上传入 data-scrollbar,或在外层包裹元素上覆盖相关令牌:

<Table data-scrollbar="default">
  ...
</Table>

<Drawer.Content data-scrollbar="thin" />

<Calendar.YearPickerGrid data-scrollbar="none" />

自定义溢出区域 — 在自己的元素上使用 @heroui/styles 提供的 scrollbarscrollbar-thinscrollbar-defaultscrollbar-none 工具类。基于类的覆盖方式详见 样式

注意:部分组件默认隐藏滚动条(日期选择器弹出框、颜色选择器、次级标签页)。嵌套的滚动插槽(例如日期选择器内部的日历年份选择器)会保留 HeroUI 滚动条,因为 scrollbar-none 只作用于其所在的元素本身,不会影响使用 @apply scrollbar 的后代元素。

资源

本页目录