0

Everytime I end up using style attribute beside className because none of the examples below apply styles to my react elements. Could you explain why this happens and how I can solve the issue?

I've read the docs (https://tailwindcss.com/docs/content-configuration#dynamic-class-names), but my use case is: user is choosing a color from color picker, then I change background according to that. I cannot pass "bg-[colorValue]" value to every single color, so I have to concatenate the value with "bg-[" afterwards.Because I cannot map all colors to full classnames.

const red500 = "red-500";
const red600Hex = "#dc2626";
const bgColor = "bg-[" + red600Hex + "]";
const bgColor2 = "bg-[" + "#dc2626" + "]";

function App() {
    return (
        <>
            <h1 className={` bg-${red500} `}>Hello</h1>
            <h1 className={` bg-[${red600Hex}] `}>Hello</h1>
            <h1 className={` bg-${`[${red600Hex}]`} `}>Hello</h1>
            <h1 className={` ${bgColor} `}>Hello</h1>
            <h1 className={` ${bgColor2} `}>Hello</h1>
        </>
    );
}
Terlan
  • 13
  • 3
  • What's the rendered output? – isherwood Jul 17 '23 at 13:44
  • i can see that correct classname is added to html element. but styles are not applied. so it never works – Terlan Jul 17 '23 at 14:15
  • 1
    I don't think concatenation is your problem; it's problematic characters in your class names. For instance, `#`, `[`, and `]` are all allowed in class names, but must be escaped to be valid. See [Which characters are valid in CSS class names/selectors?](https://stackoverflow.com/q/448981/215552) and especially [this answer](https://stackoverflow.com/a/6732899/215552) – Heretic Monkey Jul 17 '23 at 14:17
  • the issue is not with it. I can pass bg-[#151515] to className attribute as it is. But when I pass concatenated string variable name, it doesn't work. – Terlan Jul 17 '23 at 14:36

1 Answers1

0

You needn't worry about string concatenation when Template literal strings work just fine:

const red500 = 'red-500';
const red600Hex = '#dc2626';
const bgColor = `bg-[${red600Hex}]`;
const bgColor2 = `bg-[${'#dc2626'}]`;

export function App() {
  return (
    <>
      <h1 className={` bg-${red500} `}>Hello</h1>
      <h1 className={` bg-[${red600Hex}] `}>Hello</h1>
      <h1 className={` bg-${`[${red600Hex}]`} `}>Hello</h1>
      <h1 className={` ${bgColor} `}>Hello</h1>
      <h1 className={` ${bgColor2} `}>Hello</h1>
    </>
  );
}

Tailwind Playground

The above link did also give me a warning about concatenation: "Bug Finder: Unexpected string concatenation of literals.eslint" Warning message

Edit:

I even added an option to dynamically control the color of the last h1 from state:

const colors = [
  {value: "#dc2626"},
  {value: "#dc06e6"},
  {value: "#dce606"},
]


export function App() {
  const [color, setColor] = React.useState(colors[0].value)
  return (
    <>
      <h1 className={`text-green-500 bg-${red500} `}>Hello</h1>
      <h1 className={`bg-[${red600Hex}] `}>Hello</h1>
      <h1 className={`text-green-200 bg-${`[${red600Hex}]`} `}>Hello</h1>
      <h1 className={`${bgColor} `}>Hello</h1>
      <h1 className={`bg-[${color}]`}>Hello</h1>
      <select onChange={(e) => setColor(e.currentTarget.value)}>
        {colors.map(c => <option className={`bg-[${c.value}]`} value={c.value}>{c.value}</option>)}
      </select>
    </>
  );
}

Gif showing dynamically set color from Select

Harrison
  • 1,654
  • 6
  • 11
  • 19
  • It still doesnt work with template literals either. – Terlan Jul 17 '23 at 14:20
  • In that case I think you have a different issue and need to share more code, because your code in the Playground link I shared works fine (event the string concatenation). So for it to not be working, there's got to be a different issue somewhere else... – Harrison Jul 17 '23 at 14:26
  • Well, I've created my project with create-next-app and choose tw from cli when initializing. So there is nothing I changed in boilerplate next.js app. – Terlan Jul 17 '23 at 14:34
  • Did you follow the next steps regarding [installation](https://v2.tailwindcss.com/docs/guides/nextjs#install-tailwind-via-npm) and [including the tailwind css](https://v2.tailwindcss.com/docs/guides/nextjs#include-tailwind-in-your-css) – Harrison Jul 17 '23 at 14:38
  • Every tailwind code is working in my project actually. Except concatenated strings. – Terlan Jul 17 '23 at 14:40
  • I've updated the playground to include data from state – Harrison Jul 17 '23 at 15:07
  • I believe that playcode made some tweaks on how purgecss works to their tailwind react starter kit. Because even Tailwind docs says that dynamicly concatenated classnames will be ignored by purge and we should not try to do that. (https://tailwindcss.com/docs/content-configuration#dynamic-class-names) But that you for your effort trying to help. So yeah, my guess is that playcode did some hackings behind the scene, but I cannot be sure – Terlan Jul 17 '23 at 16:08