# How to Override Tailwind CSS Styles in a React Component

## The Problem

Say you've built a `<Button />` component in React that encapsulates your design system and perhaps some business logic to reuse across your React project using Tailwind CSS as the styling tool. It might look something like this:

```apache
export default function Button({ className, children, ...props }) {
  return (
    <button
      className={`py-4 px-6 text-white bg-blue-800 text-md hover:opacity-80 transition-opacity ${className}`}
      {...props}
    >
      {children}
    </button>
  );
}
```

Great! So using this `<Button />` anywhere in your project will render the button with some default styles, like the `bg-blue-800` background colour:

[https://codesandbox.io/p/devbox/tailwind-override-in-react-component-disabled-s3jvt3](https://codesandbox.io/p/devbox/tailwind-override-in-react-component-disabled-s3jvt3)

<iframe src="https://codesandbox.io/p/devbox/tailwind-override-in-react-component-s3jvt3?embed=1&file=%2Fsrc%2FApp.tsx" style="width:100%;height:500px;border:0;border-radius:4px;overflow:hidden" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>

Notice, that we also support passing the `className` prop to this button component, for when there's an exceptional use-case where we'd want to tweak some button styles on an ad-hoc basis.

Consider the case, where we want to change the blue background colour to black. The `bg-black` Tailwind utility should help us do that. Wonderful, let's see what happens if we pass this in the `className` prop for the `<Button />` component:

```xml
<Button className="bg-black">Styled button</Button>
```

And here's what the result looks like:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719745062064/a8cf6d81-5e46-4e0b-8401-ffdff57d3f77.png align="center")

That's strange! The button still remains blue. Why didn't the `bg-black` class name override `bg-blue-800`?! After all, if we look at how the `className` prop is used on our `<Button />` component, it's specified at the end of all the default Tailwind utilities:

```apache
className={`py-4 px-6 text-white bg-blue-800 text-md hover:opacity-80 transition-opacity ${className}`}
```

so the rendered HTML looks like this:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1719745392395/21575dd2-d09b-45e6-8a31-01c327ee26d0.png align="center")

The first thought here is that since `bg-black` is used after `bg-blue-800`, it should take precedence.

However, this is not true. The order in which the class names appear in the `class` attribute of an HTML element does NOT matter. What matters is the order of these class rules defined in the cascading stylesheet instead.

In our case, Tailwind CSS includes the rules for all the utilities we enjoy using in our app when we include its stylesheets upon installing it. In our example the `index.css` file does this with:

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

So, now we know that in order for `bg-black` to take precedence over `bg-blue-800`, we need that style rule to appear later in the stylesheet, but we don't have control over it! How do we go around this?

## The Solution

So, how do we override Tailwind CSS Styles in a React Component?

We can use a package called [tailwind-merge](https://github.com/dcastil/tailwind-merge?tab=readme-ov-file#tailwind-merge)! This package exposes a `twMerge` helper that can help remove conflicting classes and prefer the `className` that you pass to a React component instead. Let's see how we can make use of this helper:

```apache
import { twMerge } from "tailwind-merge";

export default function Button({ className, children, ...props }) {
  return (
    <button
      className={twMerge(
        "py-4 px-6 text-white bg-blue-800 text-md hover:opacity-90 transition-opacity",
        className,
      )}
      {...props}
    >
      {children}
    </button>
  );
}
```

We've updated our `<Button />` component so the `className` is now the return value of the `twMerge` function imported from `"tailwind-merge"`, with the default button classes as the first argument and the provided `className` prop as the second argument. With this in place, using our `<Button />` with the `className="bg-black"` prop now renders the button as intended:

[https://codesandbox.io/p/devbox/tailwind-override-in-react-component-tailwind-merge-d8nj7p?file=%2Fsrc%2FButton.component.tsx&embed=1](https://codesandbox.io/p/devbox/tailwind-override-in-react-component-tailwind-merge-d8nj7p?file=%2Fsrc%2FButton.component.tsx&embed=1)

<iframe src="https://codesandbox.io/p/devbox/tailwind-override-in-react-component-tailwind-merge-d8nj7p?file=%2Fsrc%2FButton.component.tsx&embed=1" style="width:100%;height:500px;border:0;border-radius:4px;overflow:hidden" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe>

## Bonus

If you use the [clsx](https://www.npmjs.com/package/clsx) package for constructing classNames in React conditionally, a new helper function can help you combine `clsx` and `twMerge` and use it frequently across React components. Here's such a helper function called `cn` in TypeScript:

```typescript
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputClasses: ClassValue[]) {
  return twMerge(clsx(inputClasses))
}
```

So you can make use of this in the `<Button />` component like so,

```typescript
import { cn } from "../cn.helper";

export default function Button({ className, children, ...props }) {
  return (
    <button
      className={cn(
        "py-4 px-6 text-white bg-blue-800 text-md hover:opacity-90 transition-opacity",
        className,
      )}
      {...props}
    >
      {children}
    </button>
  );
}
```

Thanks for reading!
