Focus Ring
Style focus states with accessibility-first focus ring utilities.
Focus rings are essential for accessibility, helping users identify which element currently has keyboard focus. Bamboo provides comprehensive focus ring utilities that work with both regular focus and focus-visible states.
Focus Ring Variants
The focusRing utility applies focus styles using the &:is(:focus, [data-focus]) selector and supports four variants:
// Outside focus ring (default 2px offset)
<button className={css({ focusRing: 'outside' })}>
Click me
</button>
// Inside focus ring (no offset, with border)
<button className={css({ focusRing: 'inside' })}>
Click me
</button>
// Mixed focus ring (semi-transparent with border)
<button className={css({ focusRing: 'mixed' })}>
Click me
</button>
// No focus ring
<button className={css({ focusRing: 'none' })}>
Click me
</button>
Focus Visible Ring
The focusVisibleRing utility only applies focus styles during keyboard navigation using the
&:is(:focus-visible, [data-focus-visible]) selector:
<button className={css({ focusVisibleRing: 'outside' })}>Only shows focus ring on keyboard navigation</button>
Focus Ring vs. Focus Visible Ring
The Focus Visible Ring functions similarly to the Focus Ring, but with a key difference: it only applies focus indicator styles when an element receives keyboard focus.
This ensures that the focus ring is visible only when navigating via keyboard, improving accessibility without affecting mouse interactions.
Customization
You can customize focus ring appearance with additional utilities:
<button
className={css({
focusRing: 'outside',
focusRingColor: 'blue.500',
focusRingWidth: '3px',
focusRingStyle: 'dashed',
focusRingOffset: '4px',
})}
>
Custom focus ring
</button>
| Prop | CSS Property | Token Category | Description |
|---|---|---|---|
focusRing | Multiple | Enum | Focus ring variant |
focusVisibleRing | Multiple | Enum | Keyboard-only focus ring |
focusRingColor | --focus-ring-color-prop | colors | Focus ring color |
focusRingWidth | --focus-ring-width | borderWidths | Focus ring thickness |
focusRingStyle | --focus-ring-style | borderStyles | Focus ring style |
focusRingOffset | --focus-ring-offset | spacing | Distance from element |
The four modifiers emit a custom property and nothing else. They do not style anything on their own — a focusRing or
focusVisibleRing variant is what reads them. The variables inherit, so setting them on an ancestor themes the rings of
its whole subtree.
Global Ring Color
You can set a global focus ring color by defining the CSS custom property:
bamboo.config.ts
import { defineConfig } from '@bamboocss/dev'
export default defineConfig({
global: {
css: {
html: {
'--global-color-focus-ring': '#3b82f6',
},
},
},
})This color will be used as the default for all focus rings unless overridden by the focusRingColor prop.
Examples
Basic Focus Ring
import { css } from '../styled-system/css'
function Button({ children }) {
return (
<button
className={css({
px: '4',
py: '2',
bg: 'blue.500',
color: 'white',
rounded: 'md',
focusRing: 'outside',
})}
>
{children}
</button>
)
}
Keyboard-Only Focus Ring
import { css } from '../styled-system/css'
function Input({ ...props }) {
return (
<input
className={css({
px: '3',
py: '2',
borderWidth: '1px',
borderColor: 'gray.300',
rounded: 'md',
focusVisibleRing: 'outside',
focusRingColor: 'blue.500',
})}
{...props}
/>
)
}