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

Tailwind动态类名问题:带数字的颜色类(如bg-red-400)无法生效

问题:React + Tailwind 动态颜色类(带数字/连字符)不生效

我用React结合Tailwind开发可复用卡片组件,希望通过props动态修改按钮、背景和内容的颜色。目前不带数字的基础颜色类(如black、white)能正常生效,但带连字符和数字的颜色类(如red-400、neutral-100)无法生效,问题集中在bgColor参数的传递上。

组件代码

import React from 'react'
import classnames from 'classnames';

export default function PriceCards ({textColor, heading, text, price,occurence, bgColor, buttonText, buttonColor,buttonTextColor}) {
    return (  
        <div className={classnames(`text-${textColor} bg-${bgColor} flex flex-col justify-center items-center w-10/12`)}>
            <h1 className={classnames(`text-2xl font-bold pt-14`)}>{heading}</h1>
            <p className={classnames(`text-sm font-normal opacity-60 pt-4 text-center w-5/6`)}>{text}</p>
            <h2 className={classnames(`text-4xl font-bold pt-10`)}>{price}</h2>
            <p className={classnames(`text-sm font-normal opacity-60 `)}>{occurence}</p>
            <button className={classnames(`cursor-pointer w-60 h-10 bg-${buttonColor} text-${buttonTextColor} font-bold text-xs mt-10 mb-10`)}>{buttonText}</button>
        </div>
    );
}

页面使用代码

import React from 'react'
import { Switch } from "@material-tailwind/react";
import Header from '../components/navbar.js'
import Footer from '../components/footer.js'
import Woman from '../assets/pricing/mobile/hero.jpg'
import { useState } from 'react';
import Card from '../components/priceCards.js'

const Price = () => {
    const [toggle,setToggle] = useState(false)
    return (
        <main className='flex flex-col h-screen w-full overflow-x-hidden overflow-scroll'>
            <Header/>
            <div className='grid grid-cols-8 auto-rows-min'>
                <img src={Woman} alt='woman with camera' className='col-start-1 col-end-9'/>
                <div className='col-start-1 col-end-9 lg:col-end-4 md:col-end-6 pl-7 pr-7 md:pl-14 md:pr-14 lg:pl-20 lg:pr-20 bg-black text-white '>
                    <h1 className='text-3xl md:text-4xl font-bold pt-16 md:mt-44 md:pt-0 lg:pt-20'>PRICING</h1>
                    <p className='font-normal text-base md:text-lg opacity-60 pt-4 md:pt-5 lg:pt-7 lg:w-full pb-16 md:pb-0 md:mb-44'>Create a your stories, Photosnap is a platform for photographers and visual storytellers. It’s the simple way to create and share your photos.</p>
                </div>
                <div className='col-start-1 col-end-9 bg-white'>
                {toggle? <section className='flex items-center gap-8 pt-16 pb-10 justify-center'>
                        <p className='text-lg font-bold opacity-50'>Monthly</p>
                        <Switch defaultChecked onClick={()=>setToggle(!toggle)} ripple={false} color="brown" />
                        <p className='text-lg font-bold'>Yearly</p>
                    </section>  : 
                    <section className='flex items-center gap-8 pt-16 pb-10 justify-center'>
                        <p className='text-lg font-bold'>Monthly</p>
                        <Switch onClick={()=>setToggle(!toggle)} ripple={false} color="brown" />
                        <p className='text-lg font-bold opacity-50'>Yearly</p>
                    </section>  }
                </div>
                {toggle?
                    <div className='col-start-1 col-end-9 flex flex-col items-center gap-6'>
                        <Card
                        heading='Basic'
                        text='Includes basic usage of our platform. Recommended for new and aspiring photographers.'
                        price='$190.00'
                        occurence='per year'
                        bgColor='neutral-100'
                        buttonText='PICK PLAN' 
                        buttonColor='black'
                        buttonTextColor='white'
                        textColor='black'
                        />
                        <Card
                        heading='Pro'
                        text='More advanced features available. Recommended for photography veterans and professionals.'
                        price='$390.00'
                        occurence='per year'
                        bgColor='black'
                        buttonText='PICK PLAN' 
                        buttonColor='white'
                        buttonTextColor='black'
                        textColor='white'
                        />
                        <Card
                        heading='Business'
                        text='Additional features available such as more detailed metrics. Recommended for business owners.'
                        price='$990.00'
                        occurence='per year'
                        bgColor='neutral-100'
                        buttonText='PICK PLAN' 
                        buttonColor='black'
                        buttonTextColor='white'
                        textColor='black'
                        />
                </div> :
                <div className='col-start-1 col-end-9 flex flex-col items-center gap-6'>
                        <Card
                        heading='Basic'
                        text='Includes basic usage of our platform. Recommended for new and aspiring photographers.'
                        price='$19.00'
                        occurence='per month'
                        bgColor='neutral-100'
                        buttonText='PICK PLAN' 
                        buttonColor='black'
                        buttonTextColor='white'
                        textColor='black'
                        />
                        <Card
                        heading='Pro'
                        text='More advanced features available. Recommended for photography veterans and professionals.'
                        price='$39.00'
                        occurence='per month'
                        bgColor='black'
                        buttonText='PICK PLAN' 
                        buttonColor='white'
                        buttonTextColor='black'
                        textColor='white'
                        />
                        <Card
                        heading='Business'
                        text='Additional features available such as more detailed metrics. Recommended for business owners.'
                        price='$99.00'
                        occurence='per month'
                        bgColor='neutral-100'
                        buttonText='PICK PLAN' 
                        buttonColor='black'
                        buttonTextColor='white'
                        textColor='black'
                        />
                </div>}
                <Footer/>
            </div>
        </main>
    );
}
 
export default Price;

解决方案

原因说明

Tailwind的JIT编译器只会编译源码中明确写死的类名,动态拼接的类(如bg-${bgColor})在编译阶段无法被识别,因此不会生成对应的CSS规则。基础色能生效是因为这些类可能在项目其他位置被直接使用过,被Tailwind收录进了编译列表。

方法一:传递完整的Tailwind类名(推荐)

不再拆分颜色前缀和颜色值,直接传递完整的类名给组件:

  1. 修改组件参数,替换拆分的颜色props为完整类名:
export default function PriceCards ({ textClass, heading, text, price, occurence, bgClass, buttonText, buttonBgClass, buttonTextClass }) {
    return (  
        <div className={classnames(`${textClass} ${bgClass} flex flex-col justify-center items-center w-10/12`)}>
            <h1 className={classnames(`text-2xl font-bold pt-14`)}>{heading}</h1>
            <p className={classnames(`text-sm font-normal opacity-60 pt-4 text-center w-5/6`)}>{text}</p>
            <h2 className={classnames(`text-4xl font-bold pt-10`)}>{price}</h2>
            <p className={classnames(`text-sm font-normal opacity-60 `)}>{occurence}</p>
            <button className={classnames(`cursor-pointer w-60 h-10 ${buttonBgClass} ${buttonTextClass} font-bold text-xs mt-10 mb-10`)}>{buttonText}</button>
        </div>
    );
}
  1. 使用组件时传递完整类名:
<Card
    heading='Basic'
    text='Includes basic usage of our platform. Recommended for new and aspiring photographers.'
    price='$190.00'
    occurence='per year'
    bgClass='bg-neutral-100'
    buttonText='PICK PLAN' 
    buttonBgClass='bg-black'
    buttonTextClass='text-white'
    textClass='text-black'
/>

方法二:配置Tailwind安全列表

如果必须保留拆分传递的方式,可以在tailwind.config.js中把需要动态使用的类加入安全列表,强制Tailwind编译这些类:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{js,jsx,ts,tsx}",
  ],
  safelist: [
    'bg-neutral-100',
    'bg-black',
    'bg-white',
    'text-black',
    'text-white',
    // 添加所有需要动态使用的类
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

注意:此方法适合颜色类固定的场景,过多的安全列表会增加编译后CSS体积。

方法三:内联样式(不推荐)

通过props传递颜色值,用内联样式设置颜色,但会丢失Tailwind的hover、响应式等特性,仅作备选:

// 组件内修改
<div style={{ backgroundColor: bgColor, color: textColor }} className='flex flex-col justify-center items-center w-10/12'>
    {/* ...其他元素... */}
    <button style={{ backgroundColor: buttonColor, color: buttonTextColor }} className='cursor-pointer w-60 h-10 font-bold text-xs mt-10 mb-10'>{buttonText}</button>
</div>

// 使用时传递颜色值
<Card
    // ...其他props
    bgColor='#f5f5f5' // neutral-100的十六进制值
    buttonColor='black'
    buttonTextColor='white'
    textColor='black'
/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:50:25