Ariakit
/

Styling

Ariakit provides unstyled components by default. You're free to style them using your favorite styling method.

Applying styles

Ariakit components accept all native props, including className, style, and ref. You can use them to apply your styles just like you would with any other React element using plain CSS, inline CSS, CSS modules, CSS-in-JS, Styled Components, Emotion, Tailwind, etc.

ref={dialogRef}
style={{ backgroundColor: "white" }}
className="dialog bg-white"
/>

CSS selectors

[aria-checked]

The aria-checked attribute is applied to the Checkbox component when the input is checked. It can be either true or false.

.checkbox[aria-checked="true"] {
background-color: hsl(204 100% 40%);
color: hsl(204 20% 100%);
}

[aria-disabled]

Not all HTML elements accept the disabled attribute. That's why the Focusable component and all components that use it underneath will apply the aria-disabled attribute to the rendered element when the disabled prop is set to true.

.button[aria-disabled="true"] {
opacity: 0.5;
}

[aria-expanded]

The aria-expanded attribute is applied to the Disclosure component and all components that use it underneath, such as PopoverDisclosure, MenuButton, and Select, when the content element is shown.

.button[aria-expanded="true"] {
background-color: #eee;
}

[aria-invalid]

The aria-invalid attribute is applied to Form field components when there's a visible error message. You can use it to style the field differently when it's invalid.

.input[aria-invalid="true"] {
border-color: red;
}

[data-active]

The data-active attribute is applied to clickable components, such as Command and Button, to simulate the :active pseudo-class when the components are not rendered as native button elements.

It's important to note that, to avoid doing unnecessary work, the data-active attribute is not applied to components that are rendered as button elements. Therefore, you should use both the :active and [data-active] selectors to keep your styles consistent.

.button:active,
.button[data-active] {
background-color: #eee;
}

[data-active-item]

The data-active-item attribute is applied to composite widget items when they receive focus or are hovered (when the focusOnHover prop is set to true). Besides the Composite component itself, composite widgets include Combobox, Menu, Radio, Select, Tab, and Toolbar.

This attribute is also applied to the Combobox component when it's the only active item in the composite widget. In other words, when no ComboboxItem is active and the focus is solely on the combobox input. In this case, you can use this selector to provide additional affordance to users who pressed on the first item or on the last item to place both virtual and actual DOM focus on the combobox input.

.item[data-active-item] {
background-color: #eee;
}

[data-autofill]

The data-autofill attribute is applied to the Select component when it's used within a form and the value has been autofilled by the browser.

.select[data-autofill] {
background-color: rgb(219 237 255);
}

[data-backdrop]

The data-backdrop attribute can be used to style all Dialog backdrop elements at once.

[data-backdrop] {
background-color: rgba(0, 0, 0, 0.5);
}

[data-open]

The data-open attribute is rendered on Disclosure components when the content element is shown. It's similar to data-enter, but it's applied synchronously. This is equivalent to the open attribute applied to native disclosure elements.

This is handy for applying CSS animations to the content element. For CSS transitions, you should use data-enter instead.

.dialog[data-open] {
animation: fade-in 200ms;
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

[data-enter]

When Disclosure components are displayed, they assign the data-enter attribute to the rendered element. This occurs after a brief delay, allowing the browser to paint the starting style of the element before the transition begins.

.dialog {
transform: scale(0.9);
transition: transform 200ms;
}
.dialog[data-enter] {
transform: scale(1);
}

[data-leave]

Similar to data-enter, Disclosure components will apply the data-leave attribute to the rendered element when it's being hidden. This only occurs if an enter transition or animation was detected.

Typically, when using CSS transitions, data-enter is all you need. The CSS transition will reverse when the element is hidden. However, if you want to style the exit transition differently, or prefer to use CSS animations, you can use data-leave for this purpose.

.dialog {
transform: scale(1);
transition: transform 200ms;
}
.dialog[data-leave] {
transform: scale(0.9);
}

[data-focus-visible]

The data-focus-visible attribute is applied to the Focusable component and all components that use it underneath when there's a keyboard interaction on a focusable element.

It works the same way as the :focus-visible pseudo-class. However, unlike :focus-visible, the data-focus-visible attribute is also applied to composite widget items, such as ComboboxItem, when they receive virtualFocus.

If you're styling Ariakit components, it's recommended to use the [data-focus-visible] selector to keep your styles consistent.

.button[data-focus-visible] {
outline: 2px solid #007acc;
}

[data-user-value]

The data-user-value attribute is used on the span elements within ComboboxItemValue that correspond to the user's input. This is handy when you need to emphasize the matching segment of the item value.

[data-user-value] {
background-color: #eee;
}

[data-autocomplete-value]

The data-autocomplete-value attribute is applied to the span elements within ComboboxItemValue that do not correspond to the user's input. In other words, these are the sections of the item value that act as autocomplete suggestions.

[data-autocomplete-value] {
color: #aaa;
}

CSS variables

Some components, such as Dialog, Popover, Menu, Hovercard, SelectPopover, ComboboxPopover, among others, expose CSS variables that you can use to customize their appearance.

--dialog-viewport-height

The --dialog-viewport-height variable exposes the height of the visual viewport, considering the space taken by virtual keyboards on mobile devices. Use this CSS variable when you have input fields in your dialog to ensure it always fits within the visual viewport:

.dialog {
max-height: var(--dialog-viewport-height, 100dvh);
}

If the dialog has margins, use calc() to subtract the margin from the viewport height value:

.dialog {
--inset: 16px;
inset: var(--inset);
max-height: calc(var(--dialog-viewport-height, 100dvh) - var(--inset) * 2);
}

--popover-anchor-width

The --popover-anchor-width variable exposes the width value of the anchor element. It's useful when you want to make the popover element have a minimum or the same width as the anchor element.

.combobox-popover {
/* The combobox popover will have the combobox input width as its min width */
min-width: var(--popover-anchor-width);
}

--popover-available-height

The --popover-available-height variable exposes the available vertical space in the viewport based on the popover's placement. You can use this to make the popover element have a maximum height that fits the available space.

.popover {
max-height: var(--popover-available-height);
}

--popover-available-width

The --popover-available-width variable exposes the available horizontal space in the viewport based on the popover's placement. You can use this to make the popover element have a maximum width that fits the available space.

.popover {
max-width: var(--popover-available-width);
}

--popover-overflow-padding

The --popover-overflow-padding variable exposes the amount of padding that should be added between the popover element and the viewport edges. You can use this in combination with 100% or 100vw values to make the popover element fill the entire viewport width, while still keeping the padding.

.popover {
width: calc(100vw - var(--popover-overflow-padding) * 2);
}

--popover-transform-origin

You can adjust the transform origin value of the popover element using the --popover-transform-origin variable. This comes in handy when you're animating the popover element and need the transform origin anchored to the anchor element.

.popover {
transform-origin: var(--popover-transform-origin);
}

--scrollbar-width

The Dialog component will define a --scrollbar-width CSS variable on the html element when a modal dialog is open. Since the scrollbar is hidden when a modal dialog is open, this variable can be used to adjust the right padding of your position: fixed elements.

.header {
position: fixed;
padding-inline: 16px;
padding-inline-end: calc(16px + var(--scrollbar-width, 0));
}

Next steps

Continue reading our Guide to learn more about Ariakit:

Stay tuned

Join 1,000+ subscribers and receive monthly tips & updates on new Ariakit content.

No spam. Unsubscribe anytime. Read latest issue