Concepts

Custom merging

Resolve conflicting Tailwind classes with a custom composer.

On this page

By default, cn('px-2', 'px-4') keeps both classes. To make the later Tailwind utility replace the earlier one, configure tailwind-merge as the composer.

Install tailwind-merge in the same application package. Put the configuration in the shared style module so every component gets the same behavior.

src/lib/style.ts
import { style } from '@hulla/style'
import { twMerge } from 'tailwind-merge'

export const { cn, vn } = style({ composer: twMerge })

Now cn('rounded px-2', 'px-4') returns rounded px-4. The same composer is used for both cn calls and classes returned by vn, so the output of a variant participates when you compose it with other classes.

Only the composer changes in this setup; @hulla/style still serializes objects and arrays before passing strings to it. tailwind-merge is an optional dependency that applies its own Tailwind conflict rules. It does not generate styles, and the default configuration of @hulla/style does not perform Tailwind-aware merging.

You can also provide your own composer or serializer through style({ composer, serializer }). A custom composer receives serialized strings in argument order. A custom serializer receives every input, including strings, so use it only when you need to change how inputs are converted. See Composition for class inputs and Variants for how variant output enters the same composition path.