Styling
A guide to styling Base UI components with your preferred styling engine.
Base UI components are unstyled, don’t bundle CSS, and are compatible with Tailwind, CSS Modules, CSS-in-JS, or any other styling solution you prefer. You retain total control of your styling layer.
Style hooks
CSS classes
Components that render an HTML element accept a className
prop to style the element with CSS classes.
<Switch.Thumb className="SwitchThumb" />
The prop can also be passed a function that takes the component’s state as an argument.
<Switch.Thumb className={(state) => (state.checked ? 'checked' : 'unchecked')} />
Data attributes
Components provide data attributes designed for styling their states. For example, Switch can be styled using its [data-checked]
and [data-unchecked]
attributes, among others.
.SwitchThumb[data-checked] {
background-color: green;
}
CSS variables
Components expose CSS variables to aid in styling, often containing dynamic numeric values to be used in sizing or transform calculations. For example, Popover exposes CSS variables on its Popup
component like --available-height
and --anchor-width
.
.Popup {
max-height: var(--available-height);
}
Check out each component’s API reference for a complete list of available data attributes and CSS variables.
Tailwind CSS
Apply Tailwind classes to each part via the className
prop.
import * as React from 'react';
import { Menu } from '@base-ui-components/react/menu';
export default function ExampleMenu() {
return (
<Menu.Root>
<Menu.Trigger className="flex h-10 items-center justify-center gap-1.5 rounded-md border border-gray-200 bg-gray-50 px-3.5 text-base font-medium text-gray-900 select-none hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-blue-800 active:bg-gray-100 data-[popup-open]:bg-gray-100">
Song
</Menu.Trigger>
<Menu.Portal>
<Menu.Positioner className="outline-none" sideOffset={8}>
<Menu.Popup className="origin-[var(--transform-origin)] rounded-md bg-[canvas] py-1 text-gray-900 shadow-lg shadow-gray-200 outline outline-1 outline-gray-200 transition-[transform,scale,opacity] data-[ending-style]:scale-90 data-[ending-style]:opacity-0 data-[starting-style]:scale-90 data-[starting-style]:opacity-0 dark:shadow-none dark:-outline-offset-1 dark:outline-gray-300">
<Menu.Item className="flex cursor-default py-2 pr-8 pl-4 text-sm leading-4 outline-none select-none data-[highlighted]:relative data-[highlighted]:z-0 data-[highlighted]:text-gray-50 data-[highlighted]:before:absolute data-[highlighted]:before:inset-x-1 data-[highlighted]:before:inset-y-0 data-[highlighted]:before:z-[-1] data-[highlighted]:before:rounded-sm data-[highlighted]:before:bg-gray-900">
Add to Library
</Menu.Item>
<Menu.Item className="flex cursor-default py-2 pr-8 pl-4 text-sm leading-4 outline-none select-none data-[highlighted]:relative data-[highlighted]:z-0 data-[highlighted]:text-gray-50 data-[highlighted]:before:absolute data-[highlighted]:before:inset-x-1 data-[highlighted]:before:inset-y-0 data-[highlighted]:before:z-[-1] data-[highlighted]:before:rounded-sm data-[highlighted]:before:bg-gray-900">
Add to Playlist
</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
</Menu.Portal>
</Menu.Root>
);
}
CSS Modules
Apply custom CSS classes to each part via the className
prop.
Then style those classes in a CSS Modules file.
import * as React from 'react';
import { Menu } from '@base-ui-components/react/menu';
import styles from './menu.module.css';
export default function ExampleMenu() {
return (
<Menu.Root>
<Menu.Trigger className={styles.Button}>Song</Menu.Trigger>
<Menu.Portal>
<Menu.Positioner className={styles.Positioner} sideOffset={8}>
<Menu.Popup className={styles.Popup}>
<Menu.Item className={styles.Item}>Add to Library</Menu.Item>
<Menu.Item className={styles.Item}>Add to Playlist</Menu.Item>
</Menu.Popup>
</Menu.Positioner>
</Menu.Portal>
</Menu.Root>
);
}
CSS-in-JS
Wrap each component part and apply styles, then assemble your styled components.
import * as React from 'react';
import { Menu } from '@base-ui-components/react/menu';
import styled from '@emotion/styled';
const StyledMenuTrigger = styled(Menu.Trigger)`
// Button styles
`;
const StyledMenuPositioner = styled(Menu.Positioner)`
// Positioner styles
`;
const StyledMenuPopup = styled(Menu.Popup)`
// Popup styles
`;
const StyledMenuItem = styled(Menu.Item)`
// Menu item styles
`;
const MenuExample = () => (
<Menu.Root>
<StyledMenuTrigger>Song</StyledMenuTrigger>
<Menu.Portal>
<StyledMenuPositioner>
<StyledMenuPopup>
<StyledMenuItem>Add to Library</StyledMenuItem>
<StyledMenuItem>Add to Playlist</StyledMenuItem>
</Menu.Portal>
</StyledMenuPositioner>
</StyledMenuPopup>
</Menu.Root>
);
export default MenuExample;