Pull Quote Lift
When a sentence inside a paragraph scrolls into the viewport, a shared-element animation lifts it out and scales it up into a full-width pull quote, dropping it back inline when it leaves the viewport.
npx shadcn@latest add https://webberui.com/r/pull-quote-lift.jsonPlayground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<PullQuoteLift />
Installation
npx shadcn@latest add https://webberui.com/r/pull-quote-lift.jsonOr, once registries are configured in components.json, install it as @webberui/pull-quote-lift.
Usage
import { PullQuoteLift, LiftQuote } from "@/components/ui/pull-quote-lift";
<PullQuoteLift>
<p>
Magazine editors pull the single most important sentence out and blow it up into a pull quote.
<LiftQuote>Animation is not decoration — it is how an interface speaks to its user.</LiftQuote>
The same technique works just as well on the web.
</p>
</PullQuoteLift>PullQuoteLift wraps the whole article and LiftQuote wraps the sentence to lift. When the sentence scrolls into the viewport it "floats out" and scales up into a full-width pull quote (with decorative quotation marks and rules above and below), and drops back to its inline position in the body text when it leaves the viewport.
Props
PullQuoteLift
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | — | The article content, whose paragraphs may contain one or more LiftQuote |
className | string | — | The className of the outer container |
LiftQuote
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | — | The sentence to lift into a pull quote |
quoteClassName | string | — | Appended to the lifted blockquote's className |
How it works
- How layoutId FLIP works: the inline
motion.spanand the liftedmotion.blockquoteshare the samelayoutId. On the switch, Motion snapshots the old element's position and size and transitions the new element from the old bounding box to its final position using transforms (FLIP), which is why the sentence appears to "fly" out of the line and into the quote block. - Font-size scale morph: FLIP interpolates two boxes of very different sizes with scale, so during the transition the text is temporarily scaled and distorted (morphing from the inline font size to the large quote font size). This is inherent to shared-element animation, and exact typography is restored once the animation ends.
- Where the pull quote renders: the lifted
blockquoteis rendered through a portal into a slot at the end of the article rather than inside the<p>that holds the sentence — a<blockquote>cannot be nested inside a<p>, and the portal also lets the inline and quote sides swap within the same commit, which is what makes the FLIP snapshots line up. - Placeholder strategy: a dimmed copy of the original sentence stays inline after the lift, so the paragraph never reflows and the element
useInViewobserves keeps a stable size, avoiding oscillation at the viewport boundary. - Nested scroll containers:
useInViewdefaults to the browser viewport as its root, and IntersectionObserver automatically accounts for clipping by ancestoroverflow, so it triggers correctly inside a fixed-height scroll container too. If the container scrolls while the animation is running, making the container amotionelement withlayoutScrollis recommended so FLIP measures correctly (see the demo source). - Round-trip animation: the quote block is wrapped in
AnimatePresence, so scrolling back out of the viewport hands its position back to the remounting inline span as it exits, cross-fading between the two.
Accessibility
- When the user has "reduce motion" enabled at the system level, nothing animates: the original sentence stays in the paragraph and the pull quote is shown statically
- The sentence always stays inside the paragraph (as a dimmed version while lifted), so the article's reading order never changes; the lifted
blockquoteis a decorative copy carryingaria-hidden, so the screen reader does not announce it twice
Running Head Folio
A book running-head system — a sticky thin bar showing the current chapter title on the left and a page number derived from the scroll position on the right, with the chapter title flipping like a turning page and the folio incrementing in step at chapter boundaries.
Vertical Writing Spread
A Chinese/Japanese vertical writing editorial layout built with CSS writing-mode — vertical columns flow right to left with horizontal pull quotes and images interleaved between them, text reveals character by character from top to bottom on entry, and horizontal scrolling advances the column order.