You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tailwind v4 @theme样式未在Storybook样式表中完整显示

问题

使用Tailwind v4时,大部分@theme自定义样式未出现在Storybook样式表中。已在/.storybook/preview.ts中引入/ui/src/styles/index.css,该文件通过@theme定义了近百个CSS变量及自定义字体,但浏览器仅加载少量变量,自定义字体未生效;添加普通CSS规则(如设置html背景为粉色)可正常生效。

相关代码

/.storybook/preview.ts

import type { Preview } from '@storybook/react'
import '../ui/src/styles/index.css'

const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
  tags: ['autodocs'],
}

export default preview

/ui/src/styles/index.css

@import 'tailwindcss';

@theme {
  --color-text-disabled: oklch(0.708 0 0);
  --color-text-muted: oklch(0.556 0 0);
  --color-text-default: oklch(0.439 0 0);
  --color-text-emphasis: oklch(0.371 0 0);
  --color-text-header: oklch(0.205 0 0);
  --color-text-link: oklch(0.205 0 0);

  --color-brand: oklch(0.4616 0.0757 170.11);
  --color-priority: oklch(0.7226 0.1352 50.08);
  --color-danger: oklch(0.5796 0.2219 19.61);

  --color-neutral-0: oklch(1 0 0);
  --color-neutral-25: oklch(0.9782 0.0035 39.48);
  --color-neutral-50: oklch(0.985 0 0);
  --color-neutral-100: oklch(0.97 0 0);
  --color-neutral-200: oklch(0.922 0 0);
  --color-neutral-300: oklch(0.87 0 0);
  --color-neutral-400: oklch(0.708 0 0);
  --color-neutral-500: oklch(0.556 0 0);
  --color-neutral-600: oklch(0.439 0 0);
  --color-neutral-700: oklch(0.371 0 0);
  --color-neutral-800: oklch(0.269 0 0);
  --color-neutral-900: oklch(0.205 0 0);


  /* 更多颜色变量... */
}

浏览器生成的样式表

<style type="text/css" data-vite-dev-id="/Users/johnlichty/code/heard-app/ui/src/styles/index.css">/*! tailwindcss v4.0.9 | MIT License | https://tailwindcss.com */
@layer theme, base, components, utilities;
@layer theme {
  :root, :host {
    --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
      "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
    --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
      "Courier New", monospace;
    --color-neutral-50: oklch(0.985 0 0);
    --color-neutral-100: oklch(0.97 0 0);
    --color-neutral-200: oklch(0.922 0 0);
    --color-neutral-700: oklch(0.371 0 0);
    --color-neutral-900: oklch(0.205 0 0);
    --spacing: 0.25rem;
    --text-xs: 0.75rem;
    --text-xs--line-height: calc(1 / 0.75);
    --text-sm: 0.875rem;
    --text-sm--line-height: calc(1.25 / 0.875);
    --text-base: 1rem;
    --text-base--line-height: calc(1.5 / 1);
    --font-weight-medium: 500;
    --radius-md: 0.375rem;
    --default-transition-duration: 150ms;
    --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
    --default-font-family: var(--font-sans);
    --default-font-feature-settings: var(--font-sans--font-feature-settings);
    --default-font-variation-settings: var(
      --font-sans--font-variation-settings
    );
    --default-mono-font-family: var(--font-mono);
    --default-mono-font-feature-settings: var(
      --font-mono--font-feature-settings
    );
    --default-mono-font-variation-settings: var(
      --font-mono--font-variation-settings
    );
    --color-danger: oklch(0.5796 0.2219 19.61);
    --color-neutral-0: oklch(1 0 0);
  }
}
@layer base {
  *, ::after, ::before, ::backdrop, ::file-selector-button {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    border: 0 solid;
  }
  html, :host {
    line-height: 1.5;
    -webkit-text-size-adjust: 100%;
    tab-size: 4;
    font-family: var( --default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" );
    font-feature-settings: var(--default-font-feature-settings, normal);
    font-variation-settings: var( --default-font-variation-settings, normal );
    -webkit-tap-highlight-color: transparent;
  }

  ...
</style>
解决方案

Tailwind v4的@theme采用按需生成机制,只有被实际使用的变量才会被注入到最终样式表中。针对问题可按以下步骤处理:

  • 确保变量被组件实际引用
    检查React组件代码,确认未加载的变量(如--color-text-default、--color-brand)已在样式中使用。示例:

    .text-default {
      color: var(--color-text-default);
    }
    

    或通过Tailwind的theme()函数在工具类中引用:

    @layer components {
      .btn-brand {
        background-color: theme('color-brand');
      }
    }
    
  • 临时禁用摇树优化(仅调试用)
    若需加载所有变量,可在Tailwind配置中关闭未使用变量的移除:

    // tailwind.config.js
    export default {
      content: ['./ui/src/**/*.{js,ts,jsx,tsx}', './stories/**/*.{js,ts,jsx,tsx}'],
      optimize: {
        unusedVariables: false,
      },
    }
    

    注意:生产环境不建议此操作,会增大样式体积。

  • 检查Storybook的Tailwind集成
    确保PostCSS配置正确:

    // postcss.config.js
    export default {
      plugins: {
        tailwindcss: {},
      },
    }
    

    同时确认.storybook/main.ts中的Vite配置未忽略CSS处理:

    // .storybook/main.ts
    import type { StorybookConfig } from '@storybook/react-vite';
    
    const config: StorybookConfig = {
      stories: ['../stories/**/*.mdx', '../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
      addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
      framework: {
        name: '@storybook/react-vite',
        options: {},
      },
    };
    export default config;
    
  • 自定义字体加载处理
    需先通过@font-face声明字体,再在@theme中引用:

    /* /ui/src/styles/index.css */
    @import 'tailwindcss';
    
    @font-face {
      font-family: 'CustomSans';
      src: url('../fonts/CustomSans-Regular.woff2') format('woff2');
      font-weight: 400;
      font-style: normal;
    }
    
    @theme {
      --font-sans: 'CustomSans', ui-sans-serif, system-ui, sans-serif;
      /* 其他变量... */
    }
    

    确保字体文件路径正确,且Storybook构建时可读取。


内容的提问来源于stack exchange,提问作者Jadam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:29:58