Skip to Content
DocsResourcesShowcase

Conditional Styles

Learn how to use conditional and responsive styles in Chakra.

Chakra allows you to write styles for pseudo states, media queries, and custom data attributes with the conditional style props.

note
See the list of below.

For example, here's how to change the background color of a button when it's hovered:

<Box bg="red.500" _hover={{ bg: "red.700" }}>
  Hover me
</Box>

Conditional values can be nested to create complex selector rules.

Here's how to change the background color of an element when in focus on hover:

<Box bg={{ base: "red.500", _hover: { _focus: "red.700" } }}>
  Hover & Focus me
</Box>

This also works with the supported at-rules (@media, @layer, @container, @supports, and @page):

<Box
  css={{
    "@container (min-width: 10px)": {
      color: "green.300",
    },
  }}
>
  Hello
</Box>

Here's an example of how to style the hover, active, focus, and disabled states of an element

<chakra.button
  _hover={{ bg: "red.700" }}
  _active={{ bg: "red.900" }}
  _focus={{ bg: "red.800" }}
  _disabled={{ opacity: "0.5" }}
>
  Hover me > Hover me
</chakra.button>

Here's an example of how to style the first, last, odd, and even elements in a list

<Box as="ul">
  {items.map((item) => (
    <Box
      as="li"
      key={item}
      _first={{ color: "red.500" }}
      _last={{ color: "red.800" }}
    >
      {item}
    </Box>
  ))}
</Box>

You can also style even and odd elements using the _even and _odd modifier

<table>
  <tbody>
    {items.map((item) => (
      <chakra.tr key={item} _even={{ bg: "gray.100" }} _odd={{ bg: "white" }}>
        <td>{item}</td>
      </chakra.tr>
    ))}
  </tbody>
</table>

To style the ::before and ::after pseudo elements of an element, use the _before and _after modifiers

<Box _before={{ content: '"👋"' }} after={{ content: '"🥂"' }}>
  Hello
</Box>

To style the placeholder text of any input or textarea, use the _placeholder modifier:

<chakra.input
  placeholder="Enter your name"
  _placeholder={{ color: "gray.500" }}
/>

To style the file input button, use the _file modifier:

<chakra.input
  type="file"
  _file={{ bg: "gray.500", px: "4", py: "2", marginEnd: "3" }}
/>

Use the _motionReduce and _motionSafe modifiers to style an element based on the user's motion preference:

<Box _motionSafe={{ transition: "all 0.3s" }}>Hello</Box>

The prefers-color-scheme media feature is used to detect if the user has requested the system to use a light or dark color theme.

Use the _osLight and _osDark modifiers to style an element based on the user's color scheme preference:

<chakra.div bg={{ base: "white", _osDark: "black" }}>Hello</chakra.div>

The prefers-contrast media feature is used to detect if the user has requested the system use a high or low contrast theme.

Use the _highContrast and _lessContrast modifiers to style an element based on the user's color contrast preference:

<Box bg={{ base: "white", _highContrast: "black" }}>Hello</Box>

The orientation media feature is used to detect if the user has a device in portrait or landscape mode.

Use the _portrait and _landscape modifiers to style an element based on the user's device orientation:

<Box pb="4" _portrait={{ pb: "8" }}>
  Hello
</Box>

For arbitrary, use the css prop to write styles for one-off selectors:

<Box css={{ "&[data-state=closed]": { color: "red.300" } }} />

Here's another example that targets the child elements of a parent element:

<Box
  css={{
    "& > *": { margin: "2" },
  }}
/>

To style an element based on its parent element's state or attribute, add the group class to the parent element, and use any of the _group* modifiers on the child element.

<div className="group">
  <Text _groupHover={{ bg: "red.500" }}>Hover me</Text>
</div>

This modifier works for every pseudo class modifiers like _groupHover, _groupActive, _groupFocus, and _groupDisabled, etc.

To style an element based on its sibling element's state or attribute, add the peer class to the sibling element, and use any of the _peer* modifiers on the target element.

<div>
  <p className="peer">Hover me</p>
  <Box _peerHover={{ bg: "red.500" }}>I'll change by bg</Box>
</div>

Note: This only works for when the element marked with peer is a previous siblings, that is, it comes before the element you want to start.

To style an element based on the direction of the text, use the _ltr and _rtl modifiers

<div dir="ltr">
  <Box _ltr={{ ml: "3" }} _rtl={{ mr: "3" }}>
    Hello
  </Box>
</div>

To style an element based on its data-{state} attribute, use the corresponding _{state} modifier

<Box data-loading _loading={{ bg: "gray.500" }}>
  Hello
</Box>

This works for common states like data-active, data-disabled, data-focus, data-hover, data-invalid, data-required, and data-valid.

<Box data-active _active={{ bg: "gray.500" }}>
  Hello
</Box>

To style an element based on its data-orientation attribute, use the _horizontal and _vertical modifiers

<Box
  data-orientation="horizontal"
  _horizontal={{ bg: "red.500" }}
  _vertical={{ bg: "blue.500" }}
>
  Hello
</Box>

To style an element based on its aria-{state}=true attribute, use the corresponding _{state} prop

<Box aria-expanded="true" _expanded={{ bg: "gray.500" }}>
  Hello
</Box>

Here's a list of all the condition props you can use in Chakra:

Condition nameSelector
_hover&:is(:hover, [data-hover])
_focus&:is(:focus, [data-focus])
_focusWithin&:focus-within
_focusVisible&:is(:focus-visible, [data-focus-visible])
_disabled&:is(:disabled, [disabled], [data-disabled])
_active&:is(:active, [data-active])
_visited&:visited
_target&:target
_readOnly&:is(:read-only, [data-read-only])
_readWrite&:read-write
_empty&:is(:empty, [data-empty])
_checked&:is(:checked, [data-checked], [aria-checked=true])
_enabled&:enabled
_expanded&:is([aria-expanded=true], [data-expanded])
_highlighted&[data-highlighted]
_before&::before
_after&::after
_firstLetter&::first-letter
_firstLine&::first-line
_marker&::marker
_selection&::selection
_file&::file-selector-button
_backdrop&::backdrop
_first&:first-child
_last&:last-child
_only&:only-child
_even&:even
_odd&:odd
_firstOfType&:first-of-type
_lastOfType&:last-of-type
_onlyOfType&:only-of-type
_peerFocus.peer:is(:focus, [data-focus]) ~ &
_peerHover.peer:is(:hover, [data-hover]) ~ &
_peerActive.peer:is(:active, [data-active]) ~ &
_peerFocusWithin.peer:focus-within ~ &
_peerFocusVisible.peer:is(:focus-visible, [data-focus-visible]) ~ &
_peerDisabled.peer:is(:disabled, [disabled], [data-disabled]) ~ &
_peerChecked.peer:is(:checked, [data-checked], [aria-checked=true]) ~ &
_peerInvalid.peer:is(:invalid, [data-invalid], [aria-invalid=true]) ~ &
_peerExpanded.peer:is([aria-expanded=true], [data-expanded]) ~ &
_peerPlaceholderShown.peer:placeholder-shown ~ &
_groupFocus.group:is(:focus, [data-focus]) &
_groupHover.group:is(:hover, [data-hover]) &
_groupActive.group:is(:active, [data-active]) &
_groupFocusWithin.group:focus-within &
_groupFocusVisible.group:is(:focus-visible, [data-focus-visible]) &
_groupDisabled.group:is(:disabled, [disabled], [data-disabled]) &
_groupChecked.group:is(:checked, [data-checked], [aria-checked=true]) &
_groupExpanded.group:is([aria-expanded=true], [data-expanded]) &
_groupInvalid.group:invalid &
_indeterminate&:is(:indeterminate, [data-indeterminate], [aria-checked=mixed])
_required&:is(:required, [data-required], [aria-required=true])
_valid&:is(:valid, [data-valid])
_invalid&:is(:invalid, [data-invalid], [aria-invalid=true])
_autofill&:autofill
_inRange&:in-range
_outOfRange&:out-of-range
_placeholder&::placeholder
_placeholderShown&:placeholder-shown
_pressed&:is([aria-pressed=true], [data-pressed])
_selected&:is([aria-selected=true], [data-selected])
_default&:default
_optional&:optional
_open&[open]
_fullscreen&:fullscreen
_loading&:is([data-loading], [aria-busy=true])
_currentPage&[aria-current=page]
_currentStep&[aria-current=step]
_motionReduce@media (prefers-reduced-motion: reduce)
_motionSafe@media (prefers-reduced-motion: no-preference)
_print@media print
_landscape@media (orientation: landscape)
_portrait@media (orientation: portrait)
_dark&.dark, .dark &
_light&.light, .light &
_osDark@media (prefers-color-scheme: dark)
_osLight@media (prefers-color-scheme: light)
_highContrast@media (forced-colors: active)
_lessContrast@media (prefers-contrast: less)
_moreContrast@media (prefers-contrast: more)
_starting@starting-style
_ltr[dir=ltr] &
_rtl[dir=rtl] &
_scrollbar&::-webkit-scrollbar
_scrollbarThumb&::-webkit-scrollbar-thumb
_scrollbarTrack&::-webkit-scrollbar-track
_horizontal&[data-orientation=horizontal]
_vertical&[data-orientation=vertical]

Chakra lets you create your own conditions, so you're not limited to the ones in the default preset. Learn more about customizing conditions

.

Previous

Color Opacity Modifier

Next

Virtual Color