Utilities

Opt-in CSS helper classes shipped by open-props/extra/utilities.css (imported via /ui/ui.css). Use these instead of writing equivalent CSS. One of them — .visually-hidden — is redefined in ui.css after that import; read its section below before grepping the vendor file for the rule.

These are the only utility classes in the codebase. For component styling, use element / contextual selectors plus --_ private props — see Conventions.

ClassVariantsDescription
.truncate—Single-line ellipsis (replaces white-space/overflow/text-overflow trio)
.visually-hidden.sr-onlyHide content but keep it available to assistive tech
.fade-up-and-in—Entry animation — fade + slide up
.border-between-inline.border-between-blockBorder width between sibling children, from the --border custom prop on the parent — the children supply the style
.gradient-border—Gradient border-image frame — needs a border style and a gradient source of your own

.truncate

Single-line ellipsis. Requires a constrained width (flex item with min-width: 0, or explicit max-width).

Show code

.visually-hidden / .sr-only

Hide visually while keeping the element in the accessibility tree. Use for icon-only button labels, form hints read by screen readers, and the polite live regions announce() writes into.

Show code

Why ui.css overrides the vendor styles

Open Props' utilities sheet resolves this class to inline-size: 0; block-size: 0; overflow: hidden. ui.css redefines it immediately after the import as the conventional clipped-1px box — position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap — which is also, declaration for declaration, the rule accordion() and tree() inject for their own live regions. The physical width/height win over the imported logical inline-size/block-size on source order at equal specificity, in both Chromium and Firefox — so the override has to stay after the import to keep winning. public/open-props/ is vendored and left untouched, so the correction lives here.

The zero-size box has two problems. One was measured in the browser; the other is reported by accessibility sources:

In the tested Chromium and Firefox versions, a zero-size element remains in the accessibility tree without an ignored reason. The problems concern assistive technology and text layout. A live region has no visible fallback, so a failed announcement leaves the user without feedback.

.fade-up-and-in

Entry animation — fades in while sliding up. Applies on element mount.

Show code

.border-between-inline / .border-between-block

Draw a border between sibling children without a trailing one: the rule sets border-inline-start-width — border-block-start-width for the -block variant — from --border on every child but the first.

The utility only sets border width. --border holds a length, not the border shorthand: a shorthand value is invalid for a width property, so the declaration is thrown away and the width falls back to the initial medium — which can produce an unintended divider, or no divider if no border style is set.

You must set the border style as well: without one, the used width is 0, and neither the utility nor the normalize layer declares a border-*-style, so declare the style and color on each child. Declare them as longhands, the way the demo does — the border-inline-start shorthand resets the width too, and from an inline style that reset outranks the utility's rule.

Show code

.gradient-border

Decorative gradient frame, drawn as a border-image. The rule is three declarations: border-width: var(--size-3), border-image-slice: 1, and border-image-source: var(--conic-gradient-3).

The class alone draws no border for two reasons. There is no --conic-gradient-3 in the loaded token set — Open Props names its gradients --gradient-1 … --gradient-30, several of which are conic — so the source resolves to none. And with no border-style the used border width is 0 regardless of border-width. Supply both on the element: border-style: solid; --conic-gradient-3: var(--gradient-11), or set your own border-image-source and skip the class.

See also