|
| 1 | +# Recipes |
| 2 | + |
| 3 | +How to configure tailwind-merge with some common patterns. |
| 4 | + |
| 5 | +## Adding custom scale from Tailwind config to tailwind-merge config |
| 6 | + |
| 7 | +> I have a custom shadow scale with the keys 100, 200 and 300 configured in Tailwind. How do I make tailwind-merge resolve conflicts among those? |
| 8 | +
|
| 9 | +You'll be able to do this by creating a custom `twMerge` functon with [`extendTailwindMerge`](./api-reference.md#extendtailwindmerge). |
| 10 | + |
| 11 | +First, check whether your particular theme scale is included in tailwind-merge's theme config object [here](./configuring-tailwind-merge.md#theme). In the hypothetical case that tailwind-merge supported Tailwind's `boxShadow` theme scale, you could add it to the tailwind-merge config like this: |
| 12 | + |
| 13 | +```js |
| 14 | +const customTwMerge = extendTailwindMerge({ |
| 15 | + theme: { |
| 16 | + // The `boxShadow` key isn't actually supported |
| 17 | + boxShadow: [{ shadow: ['100', '200', '300'] }], |
| 18 | + }, |
| 19 | +}) |
| 20 | +``` |
| 21 | + |
| 22 | +In the case of the `boxShadow` scale, tailwind-merge doesn't include it in the theme object. Instead, we need to check out the [default config of tailwind-merge](../src/lib/default-config.ts) and search for the class group ID of the box shadow scale. After a quick search we find that tailwind-merge is using the key `shadow` for that group. We can add our custom classes to that group like this: |
| 23 | + |
| 24 | +```js |
| 25 | +const customTwMerge = extendTailwindMerge({ |
| 26 | + classGroups: { |
| 27 | + shadow: [{ shadow: ['100', '200', '300'] }], |
| 28 | + }, |
| 29 | +}) |
| 30 | +``` |
| 31 | + |
| 32 | +Note that by using `extendTailwindMerge` we're only adding our custom classes to the existing ones in the config, so `twMerge('shadow-200 shadow-lg')` will return the string `shadow-lg`. In most cases that's fine because you won't use that class in your project. |
| 33 | + |
| 34 | +If you expect classes like `shadow-lg` to be input in `twMerge` and don't want the class to cause incorrect merges, you can explicitly override the class group with [`createTailwindMerge`](./api-reference.md#createtailwindmerge), removing the default classes. |
| 35 | + |
| 36 | +```js |
| 37 | +const customTwMerge = createTailwindMerge(() => { |
| 38 | + const config = getDefaultConfig() |
| 39 | + config.classGroups.shadow = [{ shadow: ['100', '200', '300'] }] |
| 40 | + return config |
| 41 | +}) |
| 42 | +``` |
| 43 | + |
| 44 | +## Extracting classes with Tailwind's [`@apply`](https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply) |
| 45 | + |
| 46 | +> How do I make tailwind-merge resolve conflicts with a custom class created with `@apply`? |
| 47 | +> |
| 48 | +> ```css |
| 49 | +> .btn-primary { |
| 50 | +> @apply py-2 px-4 bg-blue-500 text-white rounded-lg hover:bg-blue-700; |
| 51 | +> } |
| 52 | +> ``` |
| 53 | +
|
| 54 | +I don't recommend using Tailwind's `@apply` directive for classes that might get processed with tailwind-merge. |
| 55 | +
|
| 56 | +tailwind-merge would need to be configured so that it knows about which classes `.btn-primary` is in conflict with. This means: If someone adds another Tailwind class to the `@apply` directive, the tailwind-merge config would need to get modified accordignly, keeping it in sync with the written CSS. This easy-to-miss dependency is brittle and can lead to bugs with incorrect merging behavior. |
| 57 | +
|
| 58 | +Instead of creating custom CSS classes, I recommend keeping the collection of Tailwind classes in a string variable in JavaScript and access it whenever you want to apply those styles. This way can reuse the collection of styles but don't need to touch the tailwind-merge config. |
| 59 | +
|
| 60 | +```jsx |
| 61 | +// React components with JSX syntax used in this example |
| 62 | +
|
| 63 | +const BTN_PRIMARY_CLASSNAMES = 'py-2 px-4 bg-blue-500 text-white rounded-lg hover:bg-blue-700' |
| 64 | +
|
| 65 | +function ButtonPrimary(props) { |
| 66 | + return <button {...props} className={twMerge(BTN_PRIMARY_CLASSNAMES, props.className)} /> |
| 67 | +} |
| 68 | +``` |
| 69 | +
|
| 70 | +## Modifying inputs and output of `twMege` |
| 71 | + |
| 72 | +> How do I make `twMerge` accept the same argument types as clsx/classnames? |
| 73 | +
|
| 74 | +You can wrap `twMerge` in another function which can modify the inputs and/or output. |
| 75 | + |
| 76 | +```js |
| 77 | +function customTwMerge(...inputs) { |
| 78 | + const modifiedInputs = modifyInputs(inputs) |
| 79 | + return twMerge(modifiedInputs) |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +--- |
| 84 | + |
| 85 | +Next: [API reference](./api-reference.md) |
| 86 | + |
| 87 | +Previous: [Configuring tailwind-merge](./configuring-tailwind-merge.md) |
0 commit comments