# Responsive (https://www.tailwind-variants.org/docs/responsive)

Use Tailwind breakpoint prefixes like sm: and md: inside base, variant, and slot class strings — no TV-specific API.

Responsive styles are plain Tailwind. Put breakpoint prefixes like `sm:`, `md:`, and `lg:` directly in your `base`, variant, and slot class strings — there is no TV-specific responsive API.

See [Tailwind responsive design](https://tailwindcss.com/docs/responsive-design) for breakpoint syntax.

> **info:** The old `responsiveVariants` option was removed. It depended on Tailwind's `content.transform`, which [Tailwind CSS v4](https://www.tailwind-variants.org/docs/tailwind-v4) no longer supports. Prefixes in class strings replace it.

## In `base`
Scale shared styles across breakpoints. Drag the preview — media and type step up at `sm` / `md`, and from `sm` the title block and price sit on one row:

```ts
import { tv } from 'tailwind-variants';

const stay = tv({
  base: 'rounded-xl border p-3.5 sm:p-4 md:p-5'
});

const media = tv({
  base: 'flex h-28 items-center justify-center rounded-lg bg-zinc-100 sm:h-36 md:h-40'
});

const details = tv({
  base: [
    'mt-3 flex flex-col gap-2.5',
    'sm:mt-3.5 sm:flex-row sm:items-end sm:justify-between'
  ]
});

const place = tv({
  base: 'text-[0.9375rem] font-semibold tracking-tight sm:text-lg md:text-xl'
});

const price = tv({
  base: 'text-[0.8125rem] sm:shrink-0 sm:text-right sm:text-sm'
});
```

## In variants
Bake responsive utilities into a variant value. Here `size` is a **variant name**; the `sm:` prefixes inside those strings are the responsive part — the primary action stays full-width until `sm`:

```ts
import { tv } from 'tailwind-variants';

const button = tv({
  base: 'inline-flex cursor-pointer items-center justify-center rounded-lg font-medium select-none transition-colors',
  variants: {
    variant: {
      primary: 'bg-zinc-900 text-white',
      secondary: 'border border-zinc-300 bg-zinc-50 text-zinc-900',
      tertiary: 'text-zinc-700 hover:bg-zinc-200/70'
    },
    size: {
      sm: 'h-9 px-3 text-[0.8125rem] sm:px-3.5 sm:text-sm',
      lg: 'h-10 w-full px-4 text-sm sm:w-auto sm:min-w-36'
    }
  },
  defaultVariants: {
    variant: 'primary',
    size: 'sm'
  }
});

button({ size: 'lg' });
// full-width CTA → inline from sm
```

## With slots
A calendar event: from `sm` title and place share one line; from `md` the card goes horizontal and those two stack again:

```ts
import { tv } from 'tailwind-variants';

const event = tv({
  slots: {
    root: [
      'flex flex-col gap-3.5 rounded-xl border p-3.5 sm:p-4',
      'md:flex-row md:items-center md:gap-4'
    ],
    time: [
      'flex w-fit flex-col self-start rounded-lg bg-zinc-100 px-3 py-2.5',
      'md:min-w-[4.5rem] md:items-center md:self-auto md:px-2.5 md:py-3'
    ],
    hour: 'text-sm font-semibold tracking-tight sm:text-[0.9375rem]',
    day: 'mt-0.5 text-[0.6875rem] text-zinc-500',
    body: [
      'flex min-w-0 flex-1 flex-col gap-0.5',
      'sm:flex-row sm:items-baseline sm:gap-2',
      'md:flex-col md:items-stretch md:gap-0.5'
    ],
    title: 'shrink-0 text-[0.875rem] font-medium sm:text-[0.9375rem]',
    place: [
      'min-w-0 text-[0.75rem] text-zinc-500',
      'sm:truncate sm:text-[0.8125rem]',
      'md:overflow-visible md:text-clip'
    ],
    actions: 'flex w-full gap-2 md:w-auto md:shrink-0'
  }
});

const { root, time, hour, day, body, title, place, actions } = event();
```

## At the call site
Overrides accept responsive classes too:

```ts
button({
  variant: 'primary',
  class: 'w-full sm:w-auto'
});
```

## Conflict resolution
Responsive utilities are distinct classes (`text-sm` vs `sm:text-base`). The default build merges conflicts **within the same breakpoint** — for example `sm:px-2` vs `sm:px-4` — the same way it merges unprefixed utilities. See [Class resolution](https://www.tailwind-variants.org/docs/class-resolution).
