Dynamically construct class names in TailwindCss
P粉147747637
2023-08-24 10:11:17
<p>I'm currently building a component library using TailwindCss for my next project, and I just ran into a small problem with the Button component. </p>
<p>I passed props like <code>'primary'</code> or <code>'secondary'</code> which works the same as what I did in <code>tailwind.config.js< ;/code> and then I want to assign it to the button component using <code>Template Lites</code> like this: <code>bg-${color}-500</ code></p>
<pre class="brush:php;toolbar:false;"><button
className={`
w-40 rounded-lg p-3 m-2 font-bold transition-all duration-100 border-2 active:scale-[0.98]
bg-${color}-500 `}
onClick={onClick}
type="button"
tabIndex={0}
>
{children}
</button></pre>
<p>The class name displays fine in the browser, it shows <code>bg-primary-500</code> in the DOM, but not in the Applied Styles tab. </p>
<p>Theme configuration is as follows:</p>
<pre class="brush:php;toolbar:false;">theme: {
extend: {
colors: {
primary: {
500: '#B76B3F',
},
secondary: {
500: '#344055',
},
},
},
},</pre>
<p>But it doesn't apply any styles. If I just manually add <code>bg-primary-500</code> it works fine. </p>
<p>Honestly, I'm just wondering if this is because the JIT compiler isn't picking up dynamic class names, or if I'm doing something wrong (or if this isn't the way to use tailWind). </p>
<p>Any help is welcome, thanks in advance! </p>
It is not recommended to write Tailwind CSS classes in this way. Even JIT mode is not supported, to quote the Tailwind CSS documentation: "Tailwind does not include a client runtime of any kind, so class names need to be statically extracted at build time and cannot be relied upon in the client ”
So after finding out that this way of working is deprecated and the JIT does not support it (thanks to the generous commenter). I've changed the approach to a more "configuration" based approach.
Basically, I define a const with a base configuration of different props and apply them to the component. This requires more maintenance, but it gets the job done.
This is a configuration example. (no typing required for now) and some better refactoring, but you'll get the idea.
const buttonConfig = { // Colors primary: { bgColor: 'bg-primary-500', color: 'text-white', outline: 'border-primary-500 text-primary-500 bg-opacity-0 hover:bg-opacity-10', }, secondary: { bgColor: 'bg-secondary-500', color: 'text-white', outline: 'border-secondary-500 text-secondary-500 bg-opacity-0 hover:bg-opacity-10', }, // Sizes small: 'px-3 py-2', medium: 'px-4 py-2', large: 'px-5 py-2', };Then I apply the style like this:
<motion.button whileTap={{ scale: 0.98 }} className={` rounded-lg font-bold transition-all duration-100 border-2 focus:outline-none ${buttonConfig[size]} ${outlined && buttonConfig[color].outline} ${buttonConfig[color].bgColor} ${buttonConfig[color].color}`} onClick={onClick} type="button" tabIndex={0} > {children} </motion.button>