Borders
Borders define the edge of a surface and separate content within it. A border is three decisions: width, style, and color. Use the hairline token for width, solid for style, and a semantic token for color.
- Set width with
borderWidth(or a side, e.g.borderBottomWidth). - Set style with
borderStyleand color withborderColor. - Default to
borderWidth="hairline",borderStyle="solid",borderColor="base.border".
Hairline
The default border width — density-adaptive: 1px on standard displays, 0.5px on high-DPI (≥2x) displays so borders stay crisp. Use for resting borders on surfaces (inputs, selects, comboboxes, textareas, badges, cards, avatars, icon boxes) and dividers; pair withborderStyle="solid" and a semantic borderColor (base.border by default). Menus and popovers are generally borderless — they elevate with shadow instead. Not for focus rings (use the outline shadow). A fixed literal 1px / 2px is a rare exception for emphasis or density-independent alignment — never the default.
It's a borderWidth token backed by the --chakra-border-hairline CSS variable.
Avoid
- Hardcoding
0.5pxor1pxfor standard borders — usehairlineso density is handled for you. - In-between widths like
0.75pxor1.5px.
In component themes
In theme component configs, import the $borderHairline CSS variable and compose it into the border shorthand:
Color
Border color is always a semantic token, never a raw hex or palette step. base.border is the default; reach for an intent color only when the border itself communicates status.
base.border— the outer edge of a surface (input, card, badge, avatar).base.divider— separators inside a surface (table rows, list items, sections). It's lighter thanbase.borderso internal structure recedes.- Intent borders (
primary,danger,warning,success,upsell) — only when the border carries meaning, e.g. an invalid field or a selected option.
Border vs. divider
Use base.border for the edge of a surface and base.divider for separators within it. The divider is one step lighter so the container reads as the dominant shape.
Style
solidis the default for every border.dashedis reserved for pending, placeholder, or not-yet-committed states (e.g. a pending badge). Don't use it for decoration.
Borders vs. shadows
Borders and shadows do different jobs. A border defines an edge; a shadow lifts a surface off the canvas.
- Use a
hairlineborder for definition on a flat surface that sits on the page. - Use a shadow for elevation (menus, popovers, modals).
- Some elements use both — inputs pair a
hairlineborder with thebuttonShadowLightshadow. - Avoid stacking a visible border with a large elevation shadow; it creates a doubled edge.
Do's and don'ts
- Do default to
borderWidth="hairline"+borderStyle="solid"+borderColor="base.border". - Do use
base.dividerfor separators inside a surface. - Do match the border color to intent (
danger.borderon an invalid field). - Don't hardcode
0.5pxor1pxfor standard borders — usehairline. - Don't use a border to signal focus — use the
outlineshadow. - Don't reach for raw colors (
gray.300, hex) when a semantic token exists.
Related
- Border Radius — corner rounding and nesting.
- Colors — the full semantic color palette.
- Shadows — elevation and depth.