Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React and Tailwind CSS: dynamically generated classes are not being applied

I'm just learning React and Tailwind CSS and had a strange experience with CSS grid using Tailwind classes. I've made the buttons for a calculator, with the last Button spanning two columns:

App.js:

export default function App() {
  return (
    <div className="flex min-h-screen items-center justify-center bg-blue-400">
      <Calculator />
    </div>
  );
}

Calculator.js

import { IoBackspaceOutline } from "react-icons/io5";

export const Calculator = () => {
  return (
    <div className="grid grid-cols-4 grid-rows-5 gap-2">
      <Button>AC</Button>
      <Button>
        <IoBackspaceOutline size={26} />
      </Button>
      <Button>%</Button>
      <Button>÷</Button>
      <Button>7</Button>
      <Button>8</Button>
      <Button>9</Button>
      <Button>x</Button>
      <Button>4</Button>
      <Button>5</Button>
      <Button>6</Button>
      <Button>-</Button>
      <Button>1</Button>
      <Button>2</Button>
      <Button>3</Button>
      <Button>+</Button>
      <Button>0</Button>
      <Button>.</Button>
      <Button colSpan={2}>=</Button>
    </div>
  );
};

const Button = ({ colSpan = 1, rowSpan = 1, children }) => {
  return (
    <div
      className={`col-span-${colSpan} row-span-${rowSpan} bg-white p-3 rounded`}
    >
      <div className="flex items-center justify-center">{children}</div>
    </div>
  );
};

This doesn't work (tested in Chrome): enter image description here

Now here comes the weird part. I replaced the returned JSX from the App component with HTML from a Tailwind tutorial and deleted it again.

<div className="bg-blue-400 text-blue-400 min-h-screen flex items-center justify-center">
  <div className="grid grid-cols-3 gap-2">
    <div className="col-span-2 bg-white p-10 rounded">1</div>
    <div className="bg-white p-10 rounded">2</div>
    <div className="row-span-3 bg-white p-10 rounded">3</div>
    <div className="bg-white p-10 rounded">4</div>
    <div className="bg-white p-10 rounded">5</div>
    <div className="bg-white p-10 rounded">6</div>
    <div className="col-span-2 bg-white p-10 rounded">7</div>
    <div className="bg-white p-10 rounded">8</div>
    <div className="bg-white p-10 rounded">9</div>
  </div>
</div>

After I Ctrl-Z'd a bunch of times, so I had only the previous code, my button suddenly spans two columns as intended:

enter image description here

I checked to make sure that there were no changes in the code:

enter image description here

My friend even cloned my repo, followed the same steps and got the same result. He suspects that it has something to do with the variable classNames in my Button component with regards to Tailwind's JIT compiler, but none of us can pinpoint the error.

Am I using variable CSS classes wrong?

This has been a WTF moment. What could be the reason for this?

like image 296
Asger Skov Velling Avatar asked Sep 11 '25 12:09

Asger Skov Velling


2 Answers

The CSS file generated by Tailwind will only include classes that it recognizes when it scans your code, which means that dynamically generated classes (e.g. col-span-${colSpan}) will not be included.

If you only need to span 2 columns, you could pass boolean values which will trigger the addition of a full col-span-2 or row-span-2 utility class to be added:

const Button = ({ colSpan = false, rowSpan = false, children }) => {
  return (
    <div
      className={`${colSpan ? 'col-span-2' : ''} ${rowSpan ? 'row-span-2' : ''} bg-white p-3 rounded`}
    >
      <div className="flex items-center justify-center">{children}</div>
    </div>
  );
};

Otherwise, you could pass the values as classes to the Button component:

<Button className='col-span-2 row-span-1'>=</Button>

const Button = ({ className, children }) => {
  return (
    <div
      className={`${className} bg-white p-3 rounded`}
    >
      <div className="flex items-center justify-center">{children}</div>
    </div>
  );
};

More information: https://tailwindcss.com/docs/content-configuration#dynamic-class-names

like image 123
Ed Lucas Avatar answered Sep 13 '25 04:09

Ed Lucas


As Ed Lucas said: The CSS file generated by Tailwind will only include classes that it recognizes when it scans your code, which means that dynamically generated classes (e.g. col-span-${colSpan}) will not be included

But now could use safeListing

and tailwind-safelist-generator package to "pregenerate" our dynamics styles.

With tailwind-safelist-generator, you can generate a safelist.txt file for your theme based on a set of patterns.

Tailwind's JIT mode scans your codebase for class names, and generates CSS based on what it finds. If a class name is not listed explicitly, like text-${error ? 'red' : 'green'}-500, Tailwind won't discover it. To ensure these utilities are generated, you can maintain a file that lists them explicitly, like a safelist.txt file in the root of your project.

like image 37
Daher Avatar answered Sep 13 '25 02:09

Daher