Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Smallcaps Text for React

Text that settles into the font's small capitals and back, letter by letter. For React with Base UI, when an editorial heading or a link should change its type with care.

Framework

Smallcaps Text turns a line into small capitals, capitals drawn at the height of lowercase letters, and back: each letter dissolves into its other form a moment after the one before it, with a slight rise, so the change drifts slowly along the line. It turns while the pointer is over it, or on its own, in a loop.

Use it for editorial headings, running heads, a byline or quiet navigation, where the type should feel considered rather than loud. For the bolder turn to full capitals, use Caps Toggle Text; for words that change altogether, Morph Text. The text and its small capitals sit in the same place, the second set with the font's own small capitals through CSS font-variant-caps, and CSS transitions turn each letter, or CSS keyframe animations the install adds to your stylesheet for the loop, with no animation library and no script. With reduced motion the form changes at once and the loop rests.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { SmallcapsText } from "@/components/ui/smallcaps-text";
<a href="/essays">
  <SmallcapsText text="Essays" />
</a>

Demos

Hover

trigger="hover", the default, turns the text while the pointer is over it, and back when it leaves. Inside a link or a button it also turns while that has keyboard focus, so the keyboard sees what the pointer sees.

Preview width

Tracking

Small capitals read better with a little more space between them, so they get 0.05em of letter spacing; --smallcaps-text-tracking sets it, here opened up for a running head. With trigger="loop", duration is how long each form stays, 3000 ms by default, and stagger the time between one letter settling and the next, 50 ms.

Preview width

Accessibility

Screen readers read the text once, as written, from a visually hidden copy; the two layers of letters are hidden from them. The loop pauses while the pointer is over it, and with reduced motion the form changes without fading, and the loop stays on the text as written.

FAQ

Are these real small capitals?

They're the font's own, when it has them: CSS font-variant-caps: all-small-caps asks for the small capitals the type designer drew. Many text and serif faces have them; when a font doesn't, the browser makes them from its capitals, scaled down, which reads a little lighter and thinner but works.

What case should I write the text in?

The case it should rest in. It shows as written, and every letter, capital or not, turns to a small capital: The quiet details becomes a line of small capitals with no taller first letter.

How is it different from Caps Toggle Text?

Caps Toggle Text turns to full capitals, with letters that shrink and grow, quickly; Smallcaps Text turns to capitals the height of lowercase, so the line keeps its size, with letters that only fade and rise a little, slowly. One shouts a word; the other sets it in a different register.

Does the line change width when it turns?

No. Both forms are laid out in the same place, and the wider holds the space, so nothing around the text moves.

What do screen readers hear?

The text once, as written. Small capitals are only a look, so nothing is read out differently.

What happens with reduced motion?

On hover the form still changes, at once, without fading. The loop rests on the text as written.

API Reference

SmallcapsText

<span> data-slot="smallcaps-text"

PropType
textstring

The text, as written: it shows like this at rest, and in small capitals when it turns.

duration?number

With trigger="loop", how long each form stays, in milliseconds. @default 3000.

stagger?number

The time between one letter settling and the next, in milliseconds. @default 50.

trigger?"hover" | "loop"

What turns it: the pointer over it (or keyboard focus on the link or button around it), or a loop on its own.

Type
"hover" | "loop"
Default
"hover"
render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CSS variableType
--smallcaps-text-durationstring

With trigger="loop", how long each form stays (3000ms).

--smallcaps-text-staggerstring

The time between one letter settling and the next (50ms).

--smallcaps-text-trackingstring

The small capitals' letter spacing (0.05em).

All 97 text effects