Search code examples
cssreactjstailwind-css

TailwindCSS classnames does not override


I'm coding a Button component in ReactJS which receives some props for styling it. for example primary, rounded and outline. I join classNames with the className function which comes from "classnames" library.

import className from 'classnames'

interface ButtonProps {
    children: any // Elements that placed in the Button
    outline?: boolean // Adds outline to the Button, removes background color and change font color
    rounded?: boolean // Adds border radius to the Button
    primary?: boolean // Adds blue background color to the Button
    [key: string]: any // Add some more props for example event handlers
}

function Button({
    children,
    outline,
    rounded,
    primary,
    ...rest
}: ButtonProps) {

const classNames = 
    className(
        'flex items-center select-none px-3 py-0.5 border border-2 font-medium',
        {
            'text-white bg-blue-600 border-blue-600': primary,
            'rounded-lg': rounded,
            'text-blue-500 bg-transparent': outline && primary,
        },
        rest.className
    )

return (
        <button {...rest} className={classNames}>
            {children}
        </button>
    )
}

when I set primary prop alone, the Button will appear like this:

primary Button

and classnames from the browser inspector is flex items-center select-none px-3 py-0.5 border border-2 font-medium text-white bg-blue-600 border-blue-600 which is true and what we expect. but when I add outline along with primary prop, the Button will appear like this:

primary outline Button

and classnames is flex items-center select-none px-3 py-0.5 border border-2 font-medium text-white bg-blue-600 border-blue-600 text-blue-500 bg-transparent

as you can see, bg-transparent and text-blue-500 comes after than bg-blue-600 and text-white, then must override them. according to the pictures, bg-blue-600 will be overrided by bg-transparent, but text-white does not overrided by text-blue-500.

this screen comes from CSS styles part of Developer tools: CSS styles of the Button

why this happen and how can I fix this problem?

Thanks


Solution

  • You should not apply multiple class names that apply the same property on the same element with the same variant at the same time. With outline and primary truthy values, you'll get conflicting text-white and text-blue-600 as well as conflicting bg-blue-600 and bg-transparent. Instead only apply of these at any one time, like:

    const classNames = 
        className(
            'flex items-center select-none px-3 py-0.5 border border-2 font-medium',
            {
                'border-blue-600': primary,
                'text-white bg-blue-600': primary && !outline,
                'rounded-lg': rounded,
                'text-blue-500 bg-transparent': outline && primary,
            },
            rest.className
        )