Weird problem here. I have a progress bar that looks like this:
1 export default function PercentageBar(props) {
2 return (
3 <div className="w-full h-1 my-1 bg-stone-200">
4 <div className={`h-1 bg-orange-500 w-[${props.percent}%]`} />
5 </div>
6 );
7 }
The styling is done via Tailwind CSS. If you're unfamiliar, basically what's happening is the outer div is as wide as the parent div, has a height of 1, margin on the top and bottom of 1, and is colored in a gray-ish tone. The inner div is then rendered on top of that, which also has a height of 1. The inner div is in orange and is as wide as props.percent
(a percentage of the full width of the parent div).
I've verified that the props.percent
is being passed in properly.
When props.percent
changes at runtime dynamically, line 4 in particular sometimes acts weird (regardless of the percent passed in).
For example, if props.percent
was equal to 48 and is now equal to 52, Inspect Element tells me that the line is
<div className={`h-1 bg-orange-500 w-[52%]`} />
which is correct. However, it's rendered like below (a full bar)
<div className={`h-1 bg-orange-500 w-[100%]`} />
Furthermore, sometimes it's rendered like props.percent
equals 0. This only happens after props.percent
changed values.
I've tried doing hard refreshes, resetting caches, etc. but the problem persists sporadically and across different browsers. If I refresh enough, sometimes the problem doesn't appear. Any idea what's happening here? Much appreciated!
I have same the similar problem but with the classNames
to tackle this i have sent the classNames
from where i'm using component
this ensure that component
will re-render when props changes and I have also sent !
important
keyword is anything changing your class. Hope this will resolve your issue.
export default function PercentageBar({witdhPercentage}) {
return (
<div className="w-full h-1 my-1 bg-stone-200">
<div className={`h-1 bg-orange-500 ${witdhPercentage}`} />
</div>
);
}
<PercentageBar witdhPercentage={`!${w-[${props.percent}%]}`} />
If you are using Tailwind 3 (or Tailwind 2 in JIT mode), you cannot create classes dynamically, since they will not be included in the final CSS.
For your variable value, you might consider using a style
prop instead to set the width. For example:
<div style={{width: `${props.percent}%`}} className={'h-1 bg-orange-500'} />
Found the answer! Thanks to Ed Lucas for pointing me in the right direction. He's right - you can't create class names dynamically in Tailwind. You can find the explanation on that here.
However, using the style tag that Ed suggested didn't work for me. Instead, what I did was I created a new function containing a switch statement that returns unbroken strings of class names for each width value. In other words:
function getWidthClassName(percent) {
switch (percent) {
case 0:
return 'w-[0%]';
case 1:
return 'w-[1%]';
case 2:
return 'w-[2%]';
...
case 99:
return 'w-[99%]';
case 100:
return 'w-[100%]';
default:
return 'w-[0%]';
}
}
Then, my progress bar looked like this:
export default function PercentageBar({percent}) {
let widthClassName = getWidthClassName(percent);
return (
<div className="w-full h-1 my-1 bg-stone-200">
<div className={`h-1 bg-orange-500 ${widthClassName}`} />
</div>
);
This works because instead of dynamically constructing class names at runtime, we now instead construct them statically. Tailwind is happy and we're happy.