shadcn.io is not affiliated with official shadcn/ui
Outline Text draws a word as a hollow outline, then floods it with colour like ink rising through the letters: from the bottom, the top, the start, the end, or the middle outward. It can fill while the pointer is over it (or the link around it has keyboard focus), once when it scrolls into view, or over and over in a loop.
Use it for a big headline on a portfolio or an agency page, a case study's title, or a link that should answer the pointer. For text that's wiped into view from nothing, use Mask Reveal Text; for a printed shadow behind solid letters, Line Shadow Text. The outline is the real text, with a stroke and no fill; the fill is a copy on top, clipped away to its starting side and opened by a CSS clip-path transition (or a keyframe animation the install adds to your stylesheet, for the loop), with no animation library. With reduced motion the fill appears at once.
Installation
Usage
import { OutlineText } from "@/components/ui/outline-text";<h2>
<OutlineText text="Hover me" />
</h2>Demos
Fill from
fillFrom is where the colour comes in from: bottom by default, top, start or end (which follow the text's reading direction), or center, from the middle outward. Shown here with trigger="loop", which fills, holds, drains and rests, again and again.
View
trigger="view" fills the text once, when half of it has scrolled into view, and leaves it filled. duration is how long the fill takes, 700 ms by default.
Colors
strokeColor and fillColor take any CSS colours, including your theme's variables; both are the text's own colour by default, and strokeWidth is the outline's width in pixels, 1.5 by default. Inside a link, the fill also comes in when the link has keyboard focus.
Accessibility
Screen readers read the text once: the outline is the real text, and the fill is a decorative copy they skip. In a link, keyboard focus fills it just as the pointer does. In forced-colors mode, where the outline's transparent fill would leave little to read, the text is drawn solid in the system's text colour. With reduced motion the fill appears and disappears at once, and the loop stays an outline.
FAQ
How is the outline drawn?
With -webkit-text-stroke, supported in every current browser, on the real text with its fill made transparent. The fill is a copy of the text laid exactly over it, clipped with clip-path: inset() so that only the part that has "risen" shows.
Why do I see lines inside some letters?
Some fonts, many variable fonts among them, build letters from overlapping shapes, and the stroke traces every shape, joins included. A static cut of the font, or another family, draws clean outlines; the effect is clearest at a bold weight and a large size.
Can it fill when a whole card is hovered?
The fill answers the pointer over the text itself and keyboard focus on any element around it, such as the card's link. For a whole card, make the card the link.
Does the view trigger play again when I scroll back?
No. It fills once, the first time half the text is in view, and stays filled. Without JavaScript it shows filled.
API Reference
OutlineText
<span> data-slot="outline-text"
textstring
The text.
duration?number
How long the fill takes to flood the letters, in milliseconds.
- Default
700
fillColor?string
The fill's colour, any CSS colour. By default the text's colour.
fillFrom?"bottom" | "top" | "start" | "end" | "center"
Where the fill comes in from: a side (start and end follow the
text's reading direction), or the middle outward.
- Type
"bottom" | "top" | "start" | "end" | "center"- Default
"bottom"
strokeColor?string
The outline's colour, any CSS colour. By default the text's colour.
strokeWidth?number
The outline's width, in pixels. @default 1.5.
trigger?"hover" | "view" | "loop"
What fills it: the pointer over it (or keyboard focus on the link around it), the text scrolling into view (once), or a loop that fills and empties.
- Type
"hover" | "view" | "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.
data-view?string
"in" when visible is true, otherwise "out".
--outline-text-durationstring
How long the fill takes to flood the letters (700ms).
--outline-text-fillstring
The fill's colour (the text's colour by default).
--outline-text-fromstring--outline-text-strokestring
The outline's colour (the text's colour by default).
--outline-text-stroke-widthstring
The outline's width (1.5px).
Related
- Pro
Mask Reveal Text
EntranceWiped into view from nothing
- Pro
Line Shadow Text
DecorativeA printed shadow behind solid letters
- Pro
Text Hover Effect
InteractiveAn outline lit under the pointer
- Pro
Paint Text
InteractiveBrush colour on, it fades back
Highlight Text
DecorativeA band drawn behind a phrase
Gradient Text
DecorativeA fill that keeps flowing