在Tailwind中创建基础颜色工具类

前端开发 2026-07-09

基于Tailwind 4的 源代码--value(--color-*-50) 不是一个有效的语法。但我真的想做出类似这样的东西:

@import "tailwindcss";

@utility base-* {
  --base-50: --value(--color-*-50);
  --base-100: --value(--color-*-100);
  --base-200: --value(--color-*-200);
  --base-300: --value(--color-*-300);
  --base-400: --value(--color-*-400);
  --base-500: --value(--color-*-500);
  --base-600: --value(--color-*-600);
  --base-700: --value(--color-*-700);
  --base-800: --value(--color-*-800);
  --base-900: --value(--color-*-900);
  --base-950: --value(--color-*-950);
}

@theme {
  --color-base-50: var(--base-50);
  --color-base-100: var(--base-100);
  --color-base-200: var(--base-200);
  --color-base-300: var(--base-300);
  --color-base-400: var(--base-400);
  --color-base-500: var(--base-500);
  --color-base-600: var(--base-600);
  --color-base-700: var(--base-700);
  --color-base-800: var(--base-800);
  --color-base-900: var(--base-900);
  --color-base-950: var(--base-950);
}

这样我就可以在组件中使用 base 颜色:

<div class="base-amber">
<h1 class="base-950">Lorem Ipsum</h1>
</div>

我不想把大约20种有效的Tailwind颜色硬编码到CSS中。

解决方案

仅CSS优先的配置

目前还没有原生的方法来实现这一点。你的请求是合理的,之前也曾向Tailwind CSS团队提出过,但目前似乎不是优先事项。

基于JavaScript的插件

你可以用一个JavaScript插件来解决。

我个人会将base一致地定义为一个单一颜色:

const shades = [
  '50',
  '100',
  '200',
  '300',
  '400',
  '500',
  '600',
  '700',
  '800',
  '900',
  '950',
]

tailwind.config = {
  theme: {
    extend: {
      colors: {
        base: tailwind.colors.sky,
      },
    },
  },
}
<script src="https://cdn.tailwindcss.com"></script>

<div class="size-32 bg-base-500"></div>

不过,如果你需要一个能够处理这种动态 --base-* 变量的工具,你的思路也可以实现:

const shades = [
  '50',
  '100',
  '200',
  '300',
  '400',
  '500',
  '600',
  '700',
  '800',
  '900',
  '950',
]

function isColorScale(value) {
  return (
    value &&
    typeof value === 'object' &&
    shades.every((shade) => Object.prototype.hasOwnProperty.call(value, shade))
  )
}

tailwind.config = {
  theme: {
    extend: {
      colors: {
        base: Object.fromEntries(
          shades.map((shade) => [shade, `var(--base-${shade})`])
        ),
      },
    },
  },
  plugins: [
    tailwind.plugin(function ({ matchUtilities, theme }) {
      const colors = theme('colors')

      const colorNames = Object.fromEntries(
        Object.entries(colors)
          .filter(([name, value]) => name !== 'base' && isColorScale(value))
          .map(([name]) => [name, name])
      )

      matchUtilities(
        {
          base: function (value) {
            const colorScale = theme(`colors.${value}`)

            if (!isColorScale(colorScale)) {
              return {}
            }

            return Object.fromEntries(
              shades.map((shade) => [`--base-${shade}`, colorScale[shade]])
            )
          },
        },
        {
          values: colorNames,
        }
      )
    }),
  ],
}
<script src="https://cdn.tailwindcss.com"></script>

<div class="m-4 flex gap-4">
  <div class="base-amber">
    <div class="size-32 bg-base-500"></div>
  </div>
  <div class="base-emerald">
    <div class="size-32 bg-base-500">
      <div class="base-purple size-16 bg-base-500"></div>
    </div>
  </div>
</div>

当然,这些示例是为v3而写,在该版本中你可以通过CDN直接实现按需的JavaScript插件。

在v4中,你需要创建一个JavaScript文件,并通过 @plugin 指令将其加入:

myplugin.mjs

import plugin from 'tailwindcss/plugin'
import colors from 'tailwindcss/colors'

const shades = [
  '50',
  '100',
  '200',
  '300',
  '400',
  '500',
  '600',
  '700',
  '800',
  '900',
  '950',
]

function isColorScale(value) {
  return (
    value &&
    typeof value === 'object' &&
    shades.every((shade) => Object.prototype.hasOwnProperty.call(value, shade))
  )
}

function normalizeColorName(value) {
  const colorName = String(value ?? '').trim()

  if (!/^[a-zA-Z0-9_-]+$/.test(colorName)) {
    return null
  }

  return colorName
}

function createBaseVariables(value) {
  const colorName = normalizeColorName(value)

  if (!colorName) {
    return {}
  }

  return Object.fromEntries(
    shades.map((shade) => [
      `--base-${shade}`,
      `var(--color-${colorName}-${shade})`,
    ]),
  )
}

const colorNames = Object.fromEntries(
  Object.entries(colors)
    .filter(([, value]) => isColorScale(value))
    .map(([name]) => [name, name]),
)

export default plugin(
  function ({ matchUtilities }) {
    matchUtilities(
      {
        base: createBaseVariables,
      },
      {
        values: colorNames,
        type: ['any'],
      },
    )
  },
  {
    theme: {
      extend: {
        colors: {
          base: Object.fromEntries(
            shades.map((shade) => [shade, `var(--base-${shade})`]),
          ),
        },
      },
    },
  },
)

app.css

@import "tailwindcss";

@plugin "./myplugin.mjs";
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。