Layers and conflict resolution

uv never merges utilities. Put a uv layer in UnoCSS and prefix classes that must win with uno-layer-uv.

Tailwind Variants' default build drops conflicting utilities with tailwind-merge. UnoCSS Variants does not. Every class you put in base, variants, compounds, extend, and class / className is concatenated and returned.

That is deliberate: the CSS cascade and specificity stay visible. The uv-no-merge tests in the package assert that conflicts are preserved.

What that means

import { uv } from 'unocss-variants';

const button = uv({
  base: 'px-4 py-2 rounded'
});

button({ class: 'px-2 py-4 rounded-lg' });
// px-4 py-2 rounded px-2 py-4 rounded-lg

Both px-4 and px-2 are in the string. Which padding you see depends on stylesheet order, not on which token appears last in the class attribute.

The same applies to extend: parent bg-zinc-100 and child bg-blue-500 both remain unless the child is assigned a later CSS layer.

Configure a uv layer

UnoCSS can emit utilities into named CSS layers. Give uv a higher order than the default layer, then prefix the utilities that must win:

uno.config.ts
import { defineConfig } from 'unocss';

export default defineConfig({
  layers: {
    // Default utilities sit below this. Higher number = later in CSS = wins.
    uv: 10
  }
});

Prefix classes that should win

The uno-layer-<name>: variant puts a utility into that layer:

const buyButton = uv({
  extend: baseButton,
  base: [
    'rounded-lg',
    'uno-layer-uv:bg-blue-500',
    'uno-layer-uv:hover:bg-blue-600'
  ]
});

bg-zinc-100 from the parent (default layer) and uno-layer-uv:bg-blue-500 from the child both exist in the class list. The uv layer is emitted later, so the button is blue.

Use the same prefix on:

  • Child recipe classes that override a parent
  • Compound variant backgrounds that override a color variant
  • Call-site class overrides that must beat the recipe

Skip the prefix when there is no conflict (layout, typography, shadows).

Suggested cascade

A practical order when a recipe is applied:

  1. base
  2. Variant classes
  3. Compound variants / compound slots
  4. Call-site class / className

Because nothing is removed, step 4 does not automatically override step 2. If a call-site class conflicts with a variant, prefix the call-site class (or the variant) with uno-layer-uv:.

What not to do

  • Do not install tailwind-merge for uv — it is not wired up, and there is no twMerge config flag.
  • Do not assume later tokens in the string win. That is merge-library behavior, not CSS.
  • Do not look for createTV, a second uv(options, config) argument, or unocss-variants/lite.