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

如何在React+TailwindCSS中动态切换组件背景色?

React + TailwindCSS 动态背景色不生效问题解决

问题描述

我是React和TailwindCSS新手,现在遇到一个问题:需要通过遍历categories.json文件动态设置组件背景色,但始终无法实现。已经在tailwind.config.cjs中自定义了相关颜色,但动态应用时没有效果。

代码文件

WeeklyCard.jsx

import ellipsis from '../assets/images/icon-ellipsis.svg';

export default function WeeklyCard({
  title,
  titleBackground,
  titleImage,
  previousTime,
  currentTime,
}) {
  return (
    <div
      className={`relative overflow-hidden flex justify-end ${titleBackground} mb-5 h-[150px] w-[290px] rounded-[10px]`}
    >
      <img
        className='w-[65px] h-[65px] absolute -top-2 right-3 '
        src={titleImage}
      />

      <div className='relative top-8 flex flex-col items-center justify-center h-[120px] w-[290px] rounded-[10px] p-6 bg-dark-blue'>
        <div className='flex items-center justify-between w-full text-pale-blue'>
          <div className='text-lg'>{title}</div>
          <img className='w-[20px] h-[5px] cursor-pointer' src={ellipsis} />
        </div>
        <div className='flex items-center justify-between w-full text-pale-blue'>
          <div className='text-[28px] font-[300]'>{currentTime}hrs</div>
          <div className='text-[14px] text-desaturated-blue'>
            Last week - {previousTime}hrs
          </div>
        </div>
      </div>
    </div>
  );
}

App.jsx

import ProfileCard from './components/ProfileCard';
import WeeklyCard from './components/WeeklyCard';
import categories from './categories.json';

export default function App() {
  const weeklyCards = categories.map((category) => (
    <WeeklyCard
      key={category.title}
      title={category.title}
      titleBackground={category.titleBackground}
      titleImage={category.titleImage}
      previousTime={category.timeframes.weekly.previous}
      currentTime={category.timeframes.weekly.current}
    />
  ));

  return (
    <div className={`h-min w-screen flex flex-col items-center justify-center bg-very-dark-blue`}>
      <ProfileCard
        profilePicture={'./src/assets/images/image-jeremy.png'}
        name='Jeremy Robson'
      />
      {weeklyCards}
    </div>
  );
}

categories.json

[
  {
    "title": "Work",
    "titleImage": "../src/assets/images/icon-work.svg",
    "titleBackground": "bg-Work",
    "timeframes": {
      "daily": {
        "current": 5,
        "previous": 7
      },
      "weekly": {
        "current": 32,
        "previous": 36
      },
      "monthly": {
        "current": 103,
        "previous": 128
      }
    }
  },
  {
    "title": "Play",
    "titleImage": "../src/assets/images/icon-play.svg",
    "titleBackground": "bg-Play",
    "timeframes": {
      "daily": {
        "current": 1,
        "previous": 2
      },
      "weekly": {
        "current": 10,
        "previous": 8
      },
      "monthly": {
        "current": 23,
        "previous": 29
      }
    }
  },
  {
    "title": "Study",
    "titleImage": "../src/assets/images/icon-study.svg",
    "titleBackground": "bg-Study",
    "timeframes": {
      "daily": {
        "current": 0,
        "previous": 1
      },
      "weekly": {
        "current": 4,
        "previous": 7
      },
      "monthly": {
        "current": 13,
        "previous": 19
      }
    }
  },
  {
    "title": "Exercise",
    "titleImage": "../src/assets/images/icon-exercise.svg",
    "titleBackground": "bg-Exercise",
    "timeframes": {
      "daily": {
        "current": 1,
        "previous": 1
      },
      "weekly": {
        "current": 4,
        "previous": 5
      },
      "monthly": {
        "current": 11,
        "previous": 18
      }
    }
  },
  {
    "title": "Social",
    "titleImage": "../src/assets/images/icon-social.svg",
    "titleBackground": "bg-Social",
    "timeframes": {
      "daily": {
        "current": 1,
        "previous": 3
      },
      "weekly": {
        "current": 5,
        "previous": 10
      },
      "monthly": {
        "current": 21,
        "previous": 23
      }
    }
  },
  {
    "title": "Self Care",
    "titleImage": "../src/assets/images/icon-self-care.svg",
    "titleBackground": "bg-SelfCare",
    "timeframes": {
      "daily": {
        "current": 0,
        "previous": 1
      },
      "weekly": {
        "current": 2,
        "previous": 2
      },
      "monthly": {
        "current": 7,
        "previous": 11
      }
    }
  }
]

tailwind.config.cjs

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  theme: {
    extend: {
      colors: {
        'blue-primary': 'hsl(246, 80%, 60%)',
        Work: 'hsl(15, 100%, 70%)',
        Play: 'hsl(195, 74%, 62%)',
        Study: 'hsl(348, 100%, 68%)',
        Exercise: 'hsl(145, 58%, 55%)',
        Social: 'hsl(264, 64%, 52%)',
        SelfCare: ' hsl(43, 84%, 65%)',
        'very-dark-blue': ' hsl(226, 43%, 10%)',
        'dark-blue': ' hsl(235, 46%, 20%)',
        'desaturated-blue': ' hsl(235, 45%, 61%)',
        'pale-blue': ' hsl(236, 100%, 87%)',
      },
    },
  },
  plugins: [],
};

解决方案

问题根源

  1. Tailwind类名格式不匹配:你在tailwind.config.cjs中定义的颜色键(如Work)是大写开头,但Tailwind生成的类名默认使用小写短横线格式(kebab-case),bg-Work不会被识别为有效的Tailwind类。
  2. 动态类名未被扫描:categories.json中的类名不在Tailwind的扫描范围内,JIT编译器无法生成对应的样式。

具体修复步骤

1. 统一Tailwind颜色键和类名为kebab-case

修改tailwind.config.cjs中的颜色配置,将大写开头的键改为小写短横线格式:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,json}'], // 加入json文件扫描
  theme: {
    extend: {
      colors: {
        'blue-primary': 'hsl(246, 80%, 60%)',
        'work': 'hsl(15, 100%, 70%)',
        'play': 'hsl(195, 74%, 62%)',
        'study': 'hsl(348, 100%, 68%)',
        'exercise': 'hsl(145, 58%, 55%)',
        'social': 'hsl(264, 64%, 52%)',
        'self-care': 'hsl(43, 84%, 65%)',
        'very-dark-blue': 'hsl(226, 43%, 10%)',
        'dark-blue': 'hsl(235, 46%, 20%)',
        'desaturated-blue': 'hsl(235, 45%, 61%)',
        'pale-blue': 'hsl(236, 100%, 87%)',
      },
    },
  },
  plugins: [],
};

2. 更新categories.json中的类名

将每个对象的titleBackground改为对应的kebab-case类名:

[
  {
    "title": "Work",
    "titleImage": "../src/assets/images/icon-work.svg",
    "titleBackground": "bg-work",
    // ...其他内容不变
  },
  {
    "title": "Play",
    "titleImage": "../src/assets/images/icon-play.svg",
    "titleBackground": "bg-play",
    // ...其他内容不变
  },
  {
    "title": "Study",
    "titleImage": "../src/assets/images/icon-study.svg",
    "titleBackground": "bg-study",
    // ...其他内容不变
  },
  {
    "title": "Exercise",
    "titleImage": "../src/assets/images/icon-exercise.svg",
    "titleBackground": "bg-exercise",
    // ...其他内容不变
  },
  {
    "title": "Social",
    "titleImage": "../src/assets/images/icon-social.svg",
    "titleBackground": "bg-social",
    // ...其他内容不变
  },
  {
    "title": "Self Care",
    "titleImage": "../src/assets/images/icon-self-care.svg",
    "titleBackground": "bg-self-care",
    // ...其他内容不变
  }
]

3. 确保Tailwind扫描到JSON文件中的类名

在tailwind.config.cjs的content数组中添加./src/**/*.json,这样JIT编译器会扫描JSON文件里的类名并生成对应样式。

可选方案:使用style属性动态设置

如果不想修改类名格式,也可以直接传递颜色值到组件,通过style属性设置背景色:

  1. 修改categories.json,将titleBackground改为颜色值:
"titleBackground": "hsl(15, 100%, 70%)"
  1. 在WeeklyCard组件中用style属性替换类名:
<div
  className={`relative overflow-hidden flex justify-end mb-5 h-[150px] w-[290px] rounded-[10px]`}
  style={{ backgroundColor: titleBackground }}
>

额外提示

  • React中图片路径建议使用import方式引入,避免相对路径问题:
    // 在categories.json中存图片文件名,然后在组件中动态import
    import iconWork from '../assets/images/icon-work.svg';
    
  • 重启开发服务器,确保Tailwind配置生效。

内容的提问来源于stack exchange,提问作者Ender Çelik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 10:50:25