Skip to main content
Vuetify0 is now in alpha!
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One
Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

Styling Headless Components

v0 components are headless—they provide behavior and accessibility, you provide the styling. This guide covers two first-class patterns for styling based on component state.


IntermediateApr 5, 2026

Two Approaches

v0 exposes component state in two ways:

ApproachSyntaxBest For
Data Attributesdata-[selected]:bg-primarySimple states, utility-first CSS
Slot Props:class="{ 'bg-primary': isSelected }"Complex conditions, computed styles

Both approaches work with any CSS framework. Data attributes are set automatically via the attrs object—slot props give you reactive booleans for template logic.

Tip

Start with data attributes. They’re simpler and keep styling in CSS where it belongs. Reach for slot props only when you need complex conditional logic.

Data Attributes Reference

All v0 components expose state via data-* attributes in the attrs object:

ComponentAttributesNotes
Selection
Single
Group
data-selected
data-disabled
Set on items
Groupdata-mixedTri-state only
Tabsdata-selected
data-disabled
Tab items
ExpansionPaneldata-selected
data-disabled
Activator element
Checkboxdata-state
data-disabled
checked unchecked indeterminate
Radiodata-state
data-disabled
checked unchecked
Popoverdata-popover-openActivator element
Dialogdata-dialog-openActivator element
Info

Attributes are only present when true. Use [data-selected] not [data-selected="true"].

Ask AI
What data attributes does Selection.Item expose and how do I style them?

Styling with Data Attributes

Data attribute selectors let you style based on state purely in CSS. This works with Tailwind, UnoCSS, plain CSS, or any framework supporting attribute selectors.

Tailwind / UnoCSS

Use the data-[attr]: variant↗ to apply classes when an attribute is present:

Tailwind / UnoCSS Data Attributes

Tabs styled with utility classes using data-[selected]:bg-primary attribute selectors.

Selected: apple

CSS Modules

Target data attributes in your module styles↗:

CSS Modules

Tabs styled with CSS modules targeting [data-selected] in scoped styles.

Selected: apple

Plain CSS

Standard attribute selectors↗ work in any stylesheet:

css
/* Single state */
[data-selected] {
  background: var(--v0-primary);
  color: var(--v0-on-primary);
}

/* Compound states */
[data-selected][data-disabled] {
  background: color-mix(in srgb, var(--v0-primary) 60%, transparent);
  cursor: not-allowed;
}
Tip

CSS Modules pair well with theme tokens. Use var(--v0-*) for consistent theming across your app.

Styling with Slot Props

Slot props provide reactive state as JavaScript booleans. Use them when you need:

  • Multiple dependent states: isSelected && !isDisabled && isFocused

  • Computed class names from external logic

  • Conditional rendering (icons, badges, text)

  • Dynamic inline styles (progress bars, animations)

Slot Props

Selection items styled using reactive slot props (isSelected, attrs) for conditional classes and checkmarks.

Selected: Banana

Warning

Always spread attrs on your interactive element. It contains ARIA attributes required for accessibility, plus data attributes for CSS styling.

Advanced Patterns

Transitions

Add CSS transitions for smooth state changes:

CSS Transitions

Tabs with fade, scale, and shadow transitions on state change.

Selected: fade

Focus States

Combine focus-visible with selection state for keyboard navigation feedback:

vue
<template>
  <Tabs.Item
    class="focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2
           data-[selected]:bg-primary"
    :value="item"
  >
    {{ item }}
  </Tabs.Item>
</template>

Compound States

Style combinations using CSS attribute selectors:

Compound State Selectors

Selection items demonstrating combined state styling (normal, disabled, disabled-selected) via compound attribute selectors.

Selected: disabled-selected

Parent-Child Styling

Use Tailwind’s group utilities to style children based on parent state:

vue
<template>
  <Tabs.Item class="group inline-flex items-center gap-2" :value="item">
    <span class="group-data-[selected]:font-bold">{{ item }}</span>
    <CheckIcon class="size-4 opacity-0 group-data-[selected]:opacity-100 transition-opacity" />
  </Tabs.Item>
</template>

When to Use Which

Diagram

Use controls to zoom and pan. Click outside or press Escape to close.

Tip

When in doubt, start with data attributes. Refactor to slot props only if the conditional logic becomes unwieldy.

Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/