Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Text

Pro

Drop Cap Text for React

A paragraph that opens with a large initial sunk into its first lines, inked in from the top as it scrolls into view. For React with Base UI, when an article or a chapter should open like a printed page.

Framework

Drop Cap Text sets a paragraph with a large first letter sunk a few lines into the text, the way a book or a magazine opens a chapter, and inks the letter in from the top, once, as the paragraph scrolls into view. An opening quote goes with the letter, and the rest of the paragraph wraps around it.

Use it on the first paragraph of an article, an essay, a story or a long landing page. To mark a phrase inside the text instead, use Highlight Text or Annotation Text. The cap is the paragraph's own first letter, set with the CSS initial-letter property (prefixed in Safari) and floated where that isn't supported; its ink is one registered CSS property run by a keyframe animation the install adds to your stylesheet, with no animation library. With reduced motion the cap is simply there.

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 { DropCapText } from "@/components/ui/drop-cap-text";
<DropCapText text="Typography is the craft of giving language a lasting visual form." />

Demos

Lines

lines is how many lines the cap sinks into, 3 by default: 2 suits a short paragraph or a narrow column, 4 the opening of a long piece. The cap's size follows from the lines and the paragraph's own line height.

Preview width

Serif

The cap takes the paragraph's font; give it its own with a first-letter: class, or set the whole paragraph in a serif as here. capColor takes any CSS colour, here the text's own, and duration is how long the ink takes, 1200 ms by default.

Preview width

Accessibility

The paragraph is one real <p>, read once and whole by screen readers, found by search and copied as written: the cap is its own first letter, styled, never a separate element. The cap keeps the paragraph's direction, so a right-to-left paragraph opens from the right. In forced-colors mode it takes the system's text colour. With reduced motion, or without JavaScript, it's inked from the start.

FAQ

Which browsers sink the cap into the lines?

Chrome, Edge and Safari set it with initial-letter (Safari as -webkit-initial-letter), which lines the cap's top up with the first line and its foot with the last. Firefox doesn't have it yet, so there the cap floats beside the lines, sized from the paragraph's line height to match within a pixel or two.

Can the cap use another font?

Yes: add a first-letter: class to the component, such as className="first-letter:font-serif" or first-letter:font-bold. The rest of the paragraph keeps its font.

What happens when the paragraph starts with a quote?

The opening quote becomes part of the cap, as typesetters do it: “O in the Serif demo is one initial, quote and letter together.

Can I put it inside my own paragraph?

No: it is the paragraph. It renders its own <p>, which takes className and your other props, inside a wrapper that takes no space, so put it where a paragraph goes and give it the text styles you want (size, leading, colour, width).

How does the ink animate if browsers can't animate a first letter?

They can't animate ::first-letter itself, so the keyframes run a registered, inherited CSS property, --drop-cap-text-ink, on the paragraph, and the letter's ink gradient reads it. The letter updates with its paragraph on every frame.

When does the cap ink in?

Once, when a quarter of the paragraph is in view; pass trigger="mount" to ink it as soon as the page shows it. A page without JavaScript shows it inked.

What happens with reduced motion?

The cap doesn't ink in: it's there in full from the start.

API Reference

DropCapText

<div> data-slot="drop-cap-text"

PropType
textstring

The paragraph; its first letter, with any opening quote, is the cap.

capColor?string

The cap's colour, any CSS colour. @default "var(--primary)".

duration?number

How long the cap takes to ink in, in milliseconds. @default 1200.

lines?number

How many lines the cap sinks into. @default 3.

trigger?"mount" | "view"

When the cap inks in: once the paragraph scrolls into view, or as soon as it's on the page.

Type
"mount" | "view"
Default
"view"
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.

AttributeType
data-view?string

"in" when visible is true, otherwise "out".

CSS variableType
--drop-cap-text-colorstring

The cap's colour.

--drop-cap-text-durationstring

How long the cap takes to ink in (1200ms).

--drop-cap-text-linesstring

How many lines the cap sinks into (3).

All 97 text effects