tailwindlabs / tailwindcss

A utility-first CSS framework for rapid UI development.
https://tailwindcss.com/
MIT License
82.95k stars 4.2k forks source link

Dynamic Class Name Not Applying CSS on Front-End #14209

Closed rohit-ghoghari closed 2 months ago

rohit-ghoghari commented 2 months ago

// Fetching dynamic class not working in taiwind css

Right now, I am working with my project laravel as backend and next.js (App router) as frontend technology. for frontend i have use taiwind css. I have some functionality in my project in which css need to dynamic assign from backend side and need to display in frontend side.

This is my about page:

I have TRY IT in multiple ways:

// ----------------------------------------First Option------------------------------------------------------------//

// app/about.js

/*

Issue: Dynamic Class Name Not Applying CSS on Front-End

Description: We are using a class name that is partially dynamic. The base part of the class name, "text-", is static, while the second part, "green", is dynamic and comes from a variable ${item.class}. The expected output is "text-green", but the CSS associated with this class is not being applied on the front-end.

Example:

let colorClass = text-${item.class}; // where item.class could be 'green'

Expected Output:

The class "text-green" should be applied to the element, but the corresponding CSS is not working as expected.

Question: Why is the "text-green" class not applying its CSS on the front-end, and how can we ensure that dynamically generated classes like this are correctly rendered with their associated styles?

*/

export default async function About() {

//API Call to get header icon data
 const res = await fetch('https://api.example.com/colour/data');
 const { icons } = res.data

 //icons data recieved

 const icons = [
    {
        'icon' : 'Bookmarks',
        'class' : 'green',
    },
    {
        'icon' : 'FilterIcon',
        'class' : 'blue',
    },
    {
        'icon' : 'ShareIcon',
        'class' : 'yellow',
    }
 ];

  return (
    <>
      {/* Header icons */}
      <div className="flex items-center gap-1">
        {icons && icons.map((item, index) => {
            return (
              <button
                className={`text-${item.class} bg-${item.class}`}
              >
              <GlobalIcon value={item.icon} />
              </button>
            );
          })}
      </div>
    </>
  );

};

// tailwind.config.js

const { nextui } = require("@nextui-org/react"); module.exports = { content: [ "./src/pages//*.{js,ts,jsx,tsx,mdx}", "./src/components/*/.{js,ts,jsx,tsx,mdx}", "./src/app//*.{js,ts,jsx,tsx,mdx}", "./node_modules/@nextui-org/theme/dist/*/.{js,ts,jsx,tsx}", ], theme: { extend: { colors: { white: "#ffffff", green: "#189775", blue: "#0000FF", yellow: "#EFE89B", },

  fontFamily: {
    geist: [
      "geist"
    ],
  },
},

}, plugins: [ nextui({ layout: { ariaLabel: "NextUI Layout", }, }), ], };

// ----------------------------------------Second Option------------------------------------------------------------//

/*

Issue: Dynamic Color code Not Applying CSS on Front-End

Description: We are using a Color code that is partially dynamic. The base part of the color code, "text-", is static, while the second part, "#189775", is dynamic and comes from a variable ${item.class}. The expected output is "text-[#189775]", but the CSS associated with this class is not being applied on the front-end.

Example:

let colorClass = text-[${item.class}]; // where item.class could be 'green'

Expected Output:

The class "text-[#189775]" should be applied to the element, but the corresponding CSS is not working as expected.

Question: Why is the "text-[#189775]" class not applying its CSS on the front-end, and how can we ensure that dynamically generated Color like this are correctly rendered with their associated styles?

*/

// app/about.js

export default async function About() {

//API Call to get header icon data
 const res = await fetch('https://api.example.com/colour/data');
 const { icons } = res.data

 //icons data recieved

 const icons = [
    {
        'icon' : 'Bookmarks',
        'class' : '#189775',
    },
    {
        'icon' : 'FilterIcon',
        'class' : '#0000FF',
    },
    {
        'icon' : 'ShareIcon',
        'class' : '#EFE89B',
    }
 ];

  return (
    <>
      {/* Header icons */}
      <div className="flex items-center gap-1">
        {icons && icons.map((item, index) => {
            return (
              <button
                className={`text-[${item.class}] bg-[${item.class}]`}
              >
              <GlobalIcon value={item.icon} />
              </button>
            );
          })}
      </div>
    </>
  );

};

// tailwind.config.js

const { nextui } = require("@nextui-org/react"); module.exports = { content: [ "./src/pages//*.{js,ts,jsx,tsx,mdx}", "./src/components/*/.{js,ts,jsx,tsx,mdx}", "./src/app//*.{js,ts,jsx,tsx,mdx}", "./node_modules/@nextui-org/theme/dist/*/.{js,ts,jsx,tsx}", ], theme: { extend: { colors: { white: "#ffffff", green: "#189775", blue: "#0000FF", yellow: "#EFE89B", },

  fontFamily: {
    geist: [
      "geist"
    ],
  },
},

}, plugins: [ nextui({ layout: { ariaLabel: "NextUI Layout", }, }), ], };

wongjn commented 2 months ago

As per the documentation:

The most important implication of how Tailwind extracts class names is that it will only find classes that exist as complete unbroken strings in your source files.

If you use string interpolation or concatenate partial class names together, Tailwind will not find them and therefore will not generate the corresponding CSS:

Don’t construct class names dynamically

<div class="text-{{ error ? 'red' : 'green' }}-600"></div>

In the example above, the strings text-red-600 and text-green-600 do not exist, so Tailwind will not generate those classes. Instead, make sure any class names you’re using exist in full:

Always use complete class names

<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>

So for your first situation, where you want text-green bg-green, etc. you could:

For when the color can be dynamic and is given as a color code, consider using the style attribute:

  const res = await fetch('https://api.example.com/colour/data');
  const { icons } = res.data

  return (
    <>
      {/* Header icons */}
      <div className="flex items-center gap-1">
        {icons && icons.map((item, index) => {
            return (
              <button
                style={{
                  color: item.class,
                  backgroundColor: item.class
                }}
              >