
How to Create Drop Caps with CSS?
- Sajjad
- Typography
- 01 Oct, 2026
An editor asks you to make the long-read feature section feel more like a magazine, and the first thing on their list is a large initial letter at the start of each story. You add a span around the first letter, bump its font size, float it left, and it looks fine on your screen. Then you check Safari and the letter sits a few pixels too high, the next line collides with it on mobile, and a screen reader announces the first word as two separate pieces. Drop caps look simple, but getting one right means dealing with font metrics, browser differences, and accessibility.
This article walks through what a drop cap is, the three ways to build one in CSS, how to size it so it lines up with the body text, how to handle punctuation and accessibility, and when a drop cap is worth adding at all.
What Is a Drop Cap?
A drop cap is an enlarged first letter of a paragraph that sinks down into the text block, spanning several lines, with the body text wrapping around it. It comes from medieval manuscripts and has survived in books, magazines, and editorial websites as a signal that says "a story starts here."
There are three related styles:
| Style | Description |
|---|---|
| Drop cap | The letter sinks into the paragraph; its top aligns with the first line |
| Raised cap | The letter sits on the first line's baseline and rises above the text |
| Sunken-raised | The letter sinks a few lines and also rises above the first line |
A well-set drop cap has two alignments that matter: the top of the letter lines up with the cap height of the first line, and the baseline of the letter lines up with the baseline of the last line it spans. Most CSS drop caps on the web get the first one roughly right and the second one wrong.
Method 1: ::first-letter with float
The traditional technique uses the ::first-letter pseudo-element, which targets the first letter of a block without changing the HTML. Floating it lets the text wrap around it.
.article > p:first-of-type::first-letter {
float: left;
font-family: "Playfair Display", Georgia, serif;
font-size: 4.5em;
line-height: 0.85;
font-weight: 700;
margin-block-start: 0.05em;
margin-inline-end: 0.08em;
color: var(--color-primary);
}
This works in every browser and needs no markup changes. The downside is that font-size, line-height, and margin-block-start are magic numbers. They depend on the specific font's metrics, the body line height, and sometimes the browser. Change the body font or line height and you will need to tune them again.
Which Properties Work on ::first-letter
The pseudo-element accepts a limited set of properties: font properties, color, background, margin, padding, border, float, text-decoration, text-transform, letter-spacing, word-spacing, line-height, text-shadow, vertical-align (when not floated), and initial-letter. Layout properties like position and display do not apply.
Sizing the Float Method with a Formula
You can reduce the guesswork. Suppose you want the letter to span N lines, your body has a unitless line height L, and your display font's cap height is c (as a fraction of the em, typically 0.65–0.72). The distance from the top of the capitals on line one to the baseline of line N is (N - 1) × L + c body ems. The drop cap's capital height is its font size times c. So:
font-size = ((N - 1) × L + c) / c (in em, relative to the body)
Example: N = 3, L = 1.6, c = 0.7
font-size = (2 × 1.6 + 0.7) / 0.7 = 5.57em
You will still need a small margin-block-start adjustment because the floated letter's line box includes space above the capital, but starting from the formula gets you within a pixel or two. You can find a font's cap height in its specimen, in a font inspector, or with fonttools:
pip install fonttools
python3 -c "from fontTools.ttLib import TTFont; f=TTFont('PlayfairDisplay.ttf'); print(f['OS/2'].sCapHeight / f['head'].unitsPerEm)"
Method 2: initial-letter
The initial-letter property was designed specifically for drop caps. Instead of guessing font sizes, you tell the browser how many lines the letter should span, and it computes the size and alignment from the font's own metrics.
.article > p:first-of-type::first-letter {
initial-letter: 3;
font-family: "Playfair Display", Georgia, serif;
font-weight: 700;
margin-inline-end: 0.5em;
color: var(--color-primary);
}
initial-letter: 3 makes the letter three lines tall and sinks it three lines. A second value controls the sink separately:
/* Three lines tall, sunk two lines: rises one line above the paragraph */
p::first-letter {
initial-letter: 3 2;
}
/* Three lines tall, sitting on the first baseline: a raised cap */
p::first-letter {
initial-letter: 3 1;
}
The browser aligns the cap height with the first line and the baseline with the Nth line automatically. That is what the float method can only approximate. For a full walkthrough of values and alignment options, see the dedicated post on the CSS initial-letter property.
Browser Support
Chromium-based browsers support initial-letter unprefixed, and Safari supports it with the -webkit-initial-letter prefix. Firefox does not support it at the time of writing. That gap is why the recommended approach is to combine both methods.
Method 3: Progressive Enhancement (Recommended)
Use the float method as a baseline and upgrade to initial-letter where supported. A feature query keeps the two from fighting:
.dropcap::first-letter {
float: left;
font-family: "Playfair Display", Georgia, serif;
font-weight: 700;
font-size: 5.5em;
line-height: 0.8;
margin-block-start: 0.08em;
margin-inline-end: 0.1em;
color: var(--color-primary);
}
@supports (initial-letter: 3) or (-webkit-initial-letter: 3) {
.dropcap::first-letter {
float: none;
font-size: inherit;
line-height: inherit;
margin-block-start: 0;
-webkit-initial-letter: 3;
initial-letter: 3;
margin-inline-end: 0.5em;
}
}
<article class="article">
<p class="dropcap">
Long before the web, scribes painted elaborate initials at the start of each chapter...
</p>
<p>The second paragraph continues normally.</p>
</article>
Firefox users see a well-tuned floated drop cap. Chrome, Edge, and Safari users get the precise, metric-aligned version.
Handling Punctuation and Edge Cases
Opening Quotes
If the paragraph begins with a quotation mark, ::first-letter includes the punctuation together with the first letter. A paragraph starting with a curly opening quote followed by "T" will enlarge both characters. That is usually correct typographically, but the quote can look oversized. Two fixes:
- Rewrite the opening so the paragraph does not start with a quote.
- Hang the punctuation in the margin with a negative inline margin, tuned to your font.
Short First Paragraphs
A three-line drop cap on a two-line paragraph leaves the next paragraph wrapping around the letter, or a gap below the letter. Either keep drop caps for paragraphs you know are long enough, or add display: flow-root to the paragraph so the float is contained:
.dropcap {
display: flow-root;
}
Lowercase or Numeric Starts
A paragraph that starts with a digit ("2026 was...") or a lowercase brand name produces a drop cap that does not align with the cap height. Either style those cases manually or skip the drop cap for them.
Mobile Widths
A 5em letter on a narrow screen can leave only a few characters per line beside it. Reduce the span on small containers:
.dropcap::first-letter {
-webkit-initial-letter: 2;
initial-letter: 2;
}
@media (min-width: 40rem) {
.dropcap::first-letter {
-webkit-initial-letter: 3;
initial-letter: 3;
}
}
Remember to adjust the float fallback inside the same queries if you support Firefox.
Accessibility: Avoid Splitting the Word
The most common accessibility mistake is wrapping the first letter in its own element:
<!-- Avoid: some screen readers announce "L" and then "ong before" -->
<p><span class="dropcap">L</span>ong before the web...</p>
Some screen reader and browser combinations treat the span as a separate chunk, so the first word is read as a letter followed by a fragment. Search engines and translation tools can also stumble. ::first-letter avoids the problem entirely, because the DOM text stays as one unbroken word.
If you truly need a separate element, for example to use an SVG ornamental initial, hide the decorative version from assistive technology and keep the full word available:
<p class="has-ornament">
<span class="ornament" aria-hidden="true">L</span>
<span class="visually-hidden">L</span>ong before the web...
</p>
That pattern is fragile and verbose, which is another reason to prefer ::first-letter.
Contrast and Decoration
A drop cap is large text, so WCAG 1.4.3 requires only a 3:1 contrast ratio against its background, compared with 4.5:1 for normal text. Decorative colours and backgrounds still need to meet that minimum. The WCAG contrast requirements for text article explains how large text is defined.
Styling Ideas
Boxed Drop Cap
.dropcap-boxed::first-letter {
float: left;
font-size: 3.2em;
line-height: 1;
font-weight: 700;
padding: 0.1em 0.2em;
margin: 0.1em 0.15em 0 0;
color: #fff;
background: var(--color-primary);
border-radius: 0.1em;
}
Outlined Drop Cap
.dropcap-outline::first-letter {
-webkit-initial-letter: 3;
initial-letter: 3;
color: transparent;
-webkit-text-stroke: 2px var(--color-primary);
margin-inline-end: 0.4em;
}
Outlined letters need a heavy weight to remain legible, and the stroke width should be checked at 200% zoom.
Gradient Drop Cap
::first-letter accepts backgrounds, so you can combine it with background-clip: text. The full technique, including fallbacks, is covered in gradient text with background-clip.
.dropcap-gradient::first-letter {
-webkit-initial-letter: 3;
initial-letter: 3;
background: linear-gradient(135deg, #7c3aed, #db2777);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
margin-inline-end: 0.4em;
}
Drop Caps in Tailwind CSS v4
Tailwind includes a first-letter: variant, so you can build a float-based drop cap with utilities:
<p
class="first-letter:float-left first-letter:mr-2 first-letter:text-7xl first-letter:leading-[0.8] first-letter:font-bold first-letter:text-primary"
>
Long before the web, scribes painted elaborate initials...
</p>
For initial-letter, add a custom utility in your CSS entry file:
@import "tailwindcss";
@utility drop-3 {
-webkit-initial-letter: 3;
initial-letter: 3;
}
Then use first-letter:drop-3 alongside the float utilities, wrapped in a supports-[initial-letter:3]: variant if you want to switch off the float fallback where it is not needed.
Drop Caps in Markdown and MDX Content
On a content-driven site, you rarely want authors adding classes to the first paragraph. Target it structurally instead:
.prose > p:first-of-type::first-letter {
/* drop cap styles */
}
If some articles start with an image or a callout instead of a paragraph, :first-of-type still picks the first p. To limit drop caps to specific posts, add a frontmatter flag and apply a class on the article wrapper only when it is set.
When to Use a Drop Cap
Drop caps are a strong editorial signal. They work well for:
- Long-form features, essays, and stories
- The opening of a book chapter or a new section in a long read
- Newsletters and magazine-style landing pages
They work poorly for:
- Documentation, tutorials, and help articles, where readers scan rather than settle in
- Short posts with a one- or two-line opening paragraph
- Every paragraph. One drop cap per article, or per major section, is plenty
If you are styling long reads more broadly, the guide on how to style long-form articles covers measure, spacing, and pull quotes that pair well with a drop cap.
Drop Caps FAQ
Use the first-letter pseudo-element with a floated fallback, then upgrade to the initial-letter property inside a feature query. That gives precise, metric-based alignment in Chromium and Safari and a good approximation in Firefox, without changing the HTML.
Not at the time of writing. Chromium-based browsers support it unprefixed and Safari supports it with the webkit prefix. Firefox users need the float-based fallback, which is why progressive enhancement is the recommended approach.
Not when you build them with the first-letter pseudo-element, because the word stays intact in the DOM. Problems come from wrapping the first letter in its own element, which can cause screen readers to announce the word in pieces. Also make sure the letter meets the 3:1 contrast minimum for large text.
The float method relies on font size, line height, and margin values tuned to a specific font. If you change the font or the body line height, the alignment breaks. Use the initial-letter property where available, or recalculate the size from the font's cap height and your line height.
Yes. A decorative serif or display face often works well for the initial while the body stays in a text face. Load only the weight you need, and check that the fallback font still produces a reasonable result before the web font arrives.
Two to four lines is typical. Three is the most common choice for desktop articles. On narrow mobile screens, drop to two lines so the text beside the letter still has a comfortable number of characters per line.
Conclusion
A good drop cap is a small detail that tells readers they are in a carefully made piece of writing. In CSS, the clean way to build one is the ::first-letter pseudo-element: no extra markup, no split words, and no impact on screen readers or search engines. Layer initial-letter on top for browsers that support it, and you get letters that align to the font's real cap height and baseline instead of hand-tuned guesses.
Keep the use focused. One drop cap at the start of a long article, sized to two lines on mobile and three on desktop, with enough contrast and a sensible fallback, delivers the editorial effect without hurting readability. Anything more starts to feel like decoration for its own sake.
Here are some useful references for going deeper on drop caps:
- MDN Web Docs: ::first-letter — supported properties, punctuation handling, and examples.
- MDN Web Docs: initial-letter — syntax and browser compatibility for metric-based drop caps.
- W3C: CSS Inline Layout Module Level 3 — the specification that defines initial-letter and its alignment rules.
- CSS-Tricks: Drop Caps — a long-running collection of drop cap techniques.


