Interaction states
Some utility classes can be applied conditionally by adding a modifier prefix to the beginning of the class name, describing the condition you want to target. Modifiers based on viewport size are described in Responsive design.
Interaction states
Section titled “Interaction states”Commonly used interaction states such as hover and active can get conditional styles depending on their state using the modifier prefixes hover: and active: – for a few select styles. For example, to set the border colour of an element when it is hovered, use the hover:border-primary class.
Foreground colours don’t change on hover, with the exception for links in groups with selected states.
There’s no focus: modifier, instead the same keyboard focus styles are added to all focusable elements by default. Use tabindex=0 to make an element focusable and ensure that you have no custom styles overriding the focus outline.
Element states
Section titled “Element states”Design system styles for states such as selected, checked, active have similar modifiers, allowing you to conditionally apply styles to elements depending on their state.
States are mapped to standard HTML attributes and aria-attributes. Using standard attributes instead of toggling class names ensures that the visible behaviour and accessibility attributes stay in sync, giving you a single source of truth for the state of your components.
To style an element based on the state of an parent element, some common interactive elements have parent prefix modifiers. For example, to style a button based on the state of the aria-current attribute on a parent link, use the link-current: modifier.
All states
Section titled “All states”| Modifier | Applies |
|---|---|
active: | to an element being pressed |
hover: | to hovered elements, for devices with hover support |
button-hover: | if an ancestor is a hovered button |
link-hover: | if an ancestor is a hovered link |
current: | to an element with [aria-current=page|true|step] |
link-current: | if an ancestor is a link with [aria-current=true] |
checked: | to an element with [aria-checked=true] |
checkbox-checked: | if an ancestor is an element with [role=checkbox][aria-checked=true] |
radio-checked: | if an ancestor is an element with [role=radio][aria-checked=true] |
expanded: | to elements with [aria-expanded=true] |
button-expanded: | if an ancestor is a button with [aria-expanded=true] |
selected: | to an element with [aria-selected=true] |
tab-selected: | if an ancestor is an element with [role=tab][aria-selected=true] |
details-open: | if a direct parent is a details with open=true, or an ancestor is a summary of an open details |
odd: | to the :nth-child(odd) element. |
Examples
Section titled “Examples”For example, to set the border colour of an element when it is selected, use the selected:border-primary class and toggle the selected state using the aria-selected attribute. Click the examples below to see how the styles change with the attribute value.
<h2 class="font-medium" id="label">Select an option</h2><div class="flex gap-8 mt-16" role="radiogroup" aria-labelledby="label"> <div role="radio" class="border px-16 py-8 transition-colors checked:border-accent-blue checked:border-2 hover:border-primary" aria-checked="true" tabindex="0" > Option 1 </div> <div role="radio" class="border px-16 py-8 transition-colors checked:border-accent-blue checked:border-2 hover:border-primary" aria-checked="false" tabindex="-1" > Option 2 </div></div><div role="tablist" class="flex gap-16"> <button role="tab" class="border-b-2 border-transparent selected:border-accent-blue p-8" aria-selected="true" > Tab 1 </button> <button role="tab" class="border-b-2 border-transparent selected:border-accent-blue p-8" aria-selected="false" > Tab 2 </button></div>CSS Examples
Section titled “CSS Examples”When creating your own utility classes or component styles you can use the same approach to apply styles based on the state of the element. If no native HTML or aria attribute is available you can use data- attributes.
.nav-link[aria-current='page'] {}.nav-button[disabled] {}.nav-button[data-size='large'] {}<> <a href="#" className="nav-link" aria-current={isActive ? 'page' : undefined}> Link </a> <button className="nav-button" disabled={isDisabled} data-size={size}> Button </button></>.nav-link.nav-link--is-active {}.nav-button.nav-button--is-disabled {}.nav-button.nav-button--large {}<> <a href="#" className={`nav-link${isActive ? ' nav-link--is-active' : ''}`}> Link </a> <button className={[ 'nav-button', isDisabled && 'nav-button--is-disabled', size && `nav-button--${size}`, ].filter(Boolean)} > Button </button></>