MOTION PALETTE
← すべてのデモ

Type Reveal

TypographyGSAP / SplitText / ScrollTrigger

フルスクリーンで開く ↗

枠の中でスクロール・クリックして動きを試せます。端末指定は実寸表示です。幅が足りない場合は横にスクロールできます。

再現プロンプト

架空のエディトリアル誌/タイプファウンドリ「The Foundry Review」の完成された縦長1ページサイト。カードは一切使わず、キネティックタイポのヒーロー、scrubで語ごとに塗られていくマニフェスト、font-weightが段階的に切り替わる書体見本、行ごとに逆方向へ流れる巨大折返しテキスト、単語ホバーでイタリック風に反転する引用ブロックまで、タイポグラフィだけでスクロール全域を語らせている。 配色・構成・動きの数値をまとめた指示書です。 お使いのAIに貼り、素材やお店の情報を伝えて実装してください。仕上がりは利用するAIと素材によって変わります。

Build a single self-contained HTML file (inline CSS and inline JS) reproducing a complete, long-scrolling one-page editorial site for a fictional magazine/type-foundry called "The Foundry Review". The only external dependencies allowed are GSAP core plus its SplitText and ScrollTrigger plugins from a CDN (e.g. `https://cdn.jsdelivr.net/npm/gsap@3.15/dist/gsap.min.js`, `.../SplitText.min.js`, `.../ScrollTrigger.min.js`); no other CDN, image, font file or fetch call. All visuals are pure DOM/CSS/SVG. NO card UI anywhere below the hero — no boxed/filled containers, no drop shadows, no rounded panels: every section is built purely from type, thin 1px rules, and SVG lines. The page scrolls with the normal browser window (the inner-scroll-container constraint only applies to the embedded demo shell, not this standalone build).

## Art direction
- Palette, used everywhere: background `#0E0C09`, cream text `#F5EFE6`, amber accent `#FFB74D`.
- Two families: Playfair Display (static weights 400/600/700/800/900, styles normal+italic) for every headline, manifesto line, flowing-text block and pull-quote; Archivo (all nine static weights 100–900 in steps of 100, style normal only) for labels, the ticker and the type-specimen rows. Load Archivo's individual static weight files, not a variable-font instance, so that scrubbing `font-weight` snaps between real, distinct glyph outlines instead of a smooth synthetic blend — this is what makes the specimen section feel "staged".
- Horizontal rhythm: every section uses `padding-inline: clamp(1.5rem, 6vw, 5rem)`; vertical rhythm `padding-block: clamp(3rem, 8vw, 6rem)` except the edge-to-edge hero.
- Every section is at least one viewport tall (`min-height:100vh`): Hero, Manifesto, Editorial Ticker, Type Specimen, Flowing Text, Pull Quote, Subscribe footer — seven full spreads.
- A 2px scroll-progress bar is pinned to the viewport top (`position:fixed; top:0; inset-inline:0; height:2px; z-index:40`), track `rgba(245,239,230,0.08)`, bar `linear-gradient(90deg, rgba(255,183,77,0.5), #FFB74D)`, `transform-origin:0% 50%`, driven by a ScrollTrigger on `document.body` (`start:"top top"`, `end:"bottom bottom"`, `scrub:0.3`) setting `scaleX` to progress on every update.
- Exactly one marquee exists on the whole page — the Editorial Ticker in Section 3. No other section may loop text infinitely.

## Section 1: Hero
- Full-viewport, `overflow:hidden`, centered content column (`position:absolute; inset:0; display:flex; flex-direction:column; justify-content:center; gap:1.5rem; padding:clamp(1.5rem,6vw,5rem)`).
- Content: (1) label row — "Editorial — Vol. 04" left with its own drawn 1px SVG underline, "Type / Reveal" right in amber; (2) 3-line headline "SHAPE" / "THE SILENCE" / "BETWEEN WORDS", Playfair `700`, `font-size:clamp(2.25rem,7.5vw,6.5rem)`, `line-height:0.94`, `letter-spacing:-0.01em`, color `#F5EFE6`, "SILENCE" styled `color:#FFB74D; font-style:italic; font-weight:600`; (3) thin amber SVG rule below (`height:2px; width:clamp(180px,22vw,320px)`); (4) single-line phrase-roller (`height:1.9em; max-width:34rem; overflow:hidden`) with 3 absolutely-positioned spans, Archivo italic 500, `font-size:clamp(1rem,2.2vw,1.375rem)`, amber, phrases "FOR THOSE WHO READ SLOWLY", "TYPE THAT BREATHES", "A QUIET KIND OF LOUD"; (5) 2-digit rotation number + 2rem/1px amber tick + "Editorial Rotation" label; (6) bouncing scroll cue "Scroll to continue reading ↓" (`0.72rem`, `letter-spacing:0.15em`, `rgba(245,239,230,0.55)`, keyframe `translateY 0→6px→0`/`opacity 0.55→1→0.55`, `2.4s ease-in-out infinite`).
- Headline reveal: SplitText `type:"chars"`. Set chars `yPercent:120`, `clip-path:inset(0% 0% 100% 0%)`. Timeline (`delay:0.15`) tweens chars to `yPercent:0`, `clip-path:inset(0% 0% 0% 0%)`, `duration:0.9`, `ease:"power4.out"`, `stagger:0.03`; at position `0.55`, both SVG rules' `stroke-dashoffset` (drawn with `pathLength="1"` `stroke-dasharray="1"`) tween `1→0`, `duration:1.1`, `ease:"power2.inOut"`.
- Phrase roller: `gsap.timeline({repeat:-1, delay:1.9})`; each phrase `yPercent:120,opacity:0 → yPercent:0,opacity:1`, `duration:0.6`, `ease:"power3.out"`, updates the rotation number, holds `1.6s`, exits `yPercent:-120,opacity:0`, `duration:0.5`, `ease:"power3.in"`, resets to `yPercent:120`.
- Hover: on `pointerenter`, store each char's color/weight/style, then `gsap.to(chars,{duration:0.05, repeat:5, repeatRefresh:true, ease:"none", stagger:{each:0.015, from:"random"}, fontWeight:()=>random[400,600,900], fontStyle:()=>random["normal","italic"], color:()=>random["#F5EFE6","#FFB74D"]})`; on `pointerleave`, tween back to the stored originals, `duration:0.3`, `ease:"power2.out"`.

## Section 2: Manifesto (signature — scrub-painted highlight)
- Header: eyebrow "The Manifesto" amber, right "Scroll to illuminate" muted.
- One paragraph, Playfair 600, `font-size:clamp(1.6rem,4.6vw,3.4rem)`, `line-height:1.28`, `max-width:58rem`, base color `rgba(245,239,230,0.32)`: "We do not decorate a page, we argue with it. Every serif carries intent, every space is a measured breath, and every word must earn its weight before it earns your eye. This is a magazine built for readers who still believe that typography can persuade, can whisper, can occasionally shout, and can always tell the truth."
- SplitText `type:"words"`. Every word: `color:#F5EFE6`, `background-image:linear-gradient(180deg,#FFB74D,#FFB74D)`, `background-repeat:no-repeat`, `background-position:0 82%`, `background-size:0% 55%`, `box-decoration-break:clone`. Drive one scrubbed timeline: `gsap.timeline({scrollTrigger:{trigger:section, start:"top 75%", end:"bottom 45%", scrub:0.5}}).to(words,{backgroundSize:"100% 55%", ease:"none", stagger:0.045})`. Each word is painted by a growing amber band behind its lower two-thirds, left word first, exactly in step with scroll position, never autoplay.

## Section 3: Editorial Ticker (the page's one and only marquee)
- Full-bleed band, `border-block:1px solid rgba(255,183,77,0.25)`, `padding-block:clamp(1.5rem,4vw,2.5rem)`, `overflow:hidden`.
- Track repeats "EDITORIAL TICKER — WORDS OVER IMAGES — READ SLOWLY" 8 times joined by `"   —   "`, built from two duplicated spans for a seamless loop. Archivo 700 uppercase, `letter-spacing:-0.01em`, `font-size:clamp(1.1rem,3.2vw,2.1rem)`, base `rgba(245,239,230,0.9)`, odd child spans `#FFB74D`.
- Motion: `gsap.to(track,{xPercent:-50, duration:24, ease:"none", repeat:-1})` — constant speed, always running regardless of scroll, the page's idle-motion anchor.

## Section 4: Type Specimen (signature — scrub-stepped font-weight)
- Header: eyebrow "The Foundry's Own" amber, right "Specimen No. 04" muted. Heading "Reveal Sans, cut in nine weights", Playfair 700, `clamp(1.75rem,4vw,2.75rem)`. Subcopy "One family, nine steps from hairline to black — scroll to watch each line find its weight." (Archivo 400, `rgba(245,239,230,0.6)`, `max-width:44ch`).
- Below (`margin-top:clamp(2rem,5vw,3.5rem); padding-left:clamp(1rem,2.5vw,1.5rem)`), a 2px vertical rail (`rgba(245,239,230,0.12)`) runs the row list's full height; an amber fill scrubs `scaleY` `0→1` (`transform-origin:0% 0%`) via a section-level ScrollTrigger (`start:"top 80%"`, `end:"bottom 20%"`, `scrub:0.3`).
- 9 stacked rows (`display:flex; justify-content:space-between; align-items:baseline; border-top:1px solid rgba(245,239,230,0.12); padding-block:clamp(1rem,2.6vw,1.6rem)`), each repeating "Shape the silence between words." in Archivo, `font-size:clamp(1.4rem,4.2vw,3rem)`, `#F5EFE6`; weight/name pairs top→bottom: 100 THIN, 200 EXTRA LIGHT, 300 LIGHT, 400 REGULAR, 500 MEDIUM, 600 SEMIBOLD, 700 BOLD, 800 EXTRABOLD, 900 BLACK. Right-aligned label "{weight} · {NAME}", Archivo 600, `letter-spacing:0.25em`, `0.7rem`, amber.
- Weight sweep: each row's sentence tweens `fromTo({fontWeight:100},{fontWeight:<row's weight>, ease:"none", scrollTrigger:{trigger:row, start:"top 85%", end:"top 45%", scrub:0.4}})`. Since only the nine static weight files exist, the requested value snaps to the nearest loaded instance while animating, so each line visibly steps up in stages from hairline toward its target — discrete jumps, never a smooth blur.

## Section 5: Flowing Text (signature — opposite-direction lines + word hover)
- Header: eyebrow "Reading Against the Grain" amber, right "Hover a word" muted.
- One giant, naturally wrapping block: Playfair 800, `font-size:clamp(2.75rem,9vw,7.5rem)`, `line-height:0.98`, `letter-spacing:-0.015em`, uppercase, `#F5EFE6`, section `overflow:hidden`. Text: "Words are not ornaments. They are instruments tuned for attention. Every line here moves against the one before it, because reading was never meant to travel in a straight line."
- SplitText `type:"lines, words"` so each wrapped line is block-level, containing hoverable word spans. Per line (1-indexed), `dir = odd ? 1 : -1`; `gsap.fromTo(line, {xPercent:0}, {xPercent: dir*16, ease:"none", scrollTrigger:{trigger:section, start:"top bottom", end:"bottom top", scrub:0.6}})` — odd lines (1st, 3rd…) drift to `+16`, even lines to `-16`, shearing the block as it crosses the viewport.
- Word hover (pure CSS): word spans `display:inline-block`, `transition:color 0.22s cubic-bezier(0.22,1,0.36,1), transform 0.22s cubic-bezier(0.22,1,0.36,1)`, base `transform:skewX(0deg)`. On `:hover`: `color:#FFB74D`, `transform:skewX(-10deg)` — a fake italic via shear rather than a real italic font swap, so glyph width never changes and neighboring words never reflow (zero layout shift).

## Section 6: Pull Quote
- Background `radial-gradient(ellipse at 50% 40%, rgba(255,183,77,0.07), transparent 62%), #0E0C09`.
- Giant decorative opening-quote glyph (`“`), Playfair 900, `font-size:clamp(9rem,26vw,17rem)`, amber `opacity:0.14`, centered/absolute behind text, `pointer-events:none`; parallax `gsap.fromTo(mark,{y:-60},{y:60,ease:"none",scrollTrigger:{trigger:section,start:"top bottom",end:"bottom top",scrub:0.6}})`.
- Centered column, `max-width:42rem`. Quote "Typography is the last argument a writer makes after the words themselves have already agreed to stay quiet.", Playfair italic 500, `font-size:clamp(1.5rem,4vw,2.5rem)`, `line-height:1.35`, `#F5EFE6`. SplitText `type:"lines"`, set `yPercent:100, opacity:0`, revealed by a scrubbed timeline (`start:"top 75%", end:"top 25%", scrub:0.6`) tweening `yPercent:0, opacity:1`, `stagger:0.18`, `ease:"power1.out"`.
- Attribution "— Mira Aldana, Editor-in-Chief, The Foundry Review", Archivo 600 uppercase, `letter-spacing:0.25em`, `0.75rem`, amber, `margin-top:2rem`; own ScrollTrigger (`start:"top 45%"`, `toggleActions:"play none none reverse"`) tweening `opacity:0, clip-path:inset(0% 100% 0% 0%) → opacity:1, clip-path:inset(0% 0% 0% 0%)`, `duration:0.6`, `ease:"power3.out"` — a left-to-right wipe, not a plain fade-up.

## Section 7: Subscribe footer
- Border-top `1px solid rgba(255,183,77,0.25)`.
- Left block, `max-width:34rem`: eyebrow "Subscribe" amber; heading "Read the Foundry Letter", Playfair 700, `clamp(2rem,6vw,4rem)`, `line-height:1`; copy "One editorial letter, every first Tuesday. No noise, just typeset thinking, delivered before the coffee's cold." (Archivo, `rgba(245,239,230,0.65)`).
- An issue-preview row with label "The first letter", title "On leaving enough room." and a "Read the sample issue" button. Preserve the animated underline; open the complete issue and allow a local text download.
- Closing line: "Printed thinking, sent quietly — no metrics, just words worth keeping." (`rgba(245,239,230,0.55)`, `max-width:30ch`) — deliberately no counted-up subscriber statistic anywhere on the page.
- Footer meta row (`padding-block:1.5rem`, border-top `1px solid rgba(245,239,230,0.12)`, `0.7rem` uppercase, `letter-spacing:0.15em`): "The Foundry Review" left (`rgba(245,239,230,0.7)`, 600), "Est. 2018 · Issues · Foundry · Contact · Specimens" right (`rgba(245,239,230,0.45)`).

## Scroll animations (shared rules)
- Every ScrollTrigger lives inside one root `gsap.context()` so all animation can be reverted together.
- Entrance reveals that should replay on scroll-back (quote attribution, footer underline) use `toggleActions:"play none none reverse"`.
- Position-bound effects — manifesto highlight, specimen weight sweep, flowing-text line shear, quote-mark parallax, quote-line reveal, specimen rail — all use `scrub` (0.3–0.6) so state is a direct function of scroll position, never a one-shot autoplay.
- Reveal tweens stay GPU-friendly (`transform`, `opacity`, `clip-path`) plus, only where the signature requires it, `background-size` (manifesto) and `font-weight` (specimen).
- No numbered 01/02/03 list below the hero, no stat counter, no filled-background card/panel, and only one marquee on the whole page.

## Performance & accessibility
- Modest animated node count: 27 headline chars, ~52 manifesto words, 9 specimen rows, ~6 flowing-text lines (~26 words total), ~3–4 quote lines — 60fps at dpr2/1440px via transform/opacity/clip-path/background-size/font-weight tweens only.
- Respect `prefers-reduced-motion: reduce`: skip char/word/line stagger, scrub parallax, the ticker loop and the flowing-text shear; set final states directly (chars `yPercent:0`, rules `stroke-dashoffset:0`, manifesto words `background-size:100% 55%`, specimen rows at their assigned `font-weight`, rail `scaleY:1`, quote lines full opacity, attribution `opacity:1` unclipped); keep only the headline hover (simplified to one `0.3s` color tween) and flow-word hover (transition `0.01s`); drop the scroll-cue keyframe entirely.
- On unmount, revert the `gsap.context()` (also reverting every `SplitText` split) and remove the headline's pointer listeners; when embedded in a constrained container, watch it with a `ResizeObserver` and call `ScrollTrigger.refresh()` on resize.

## Action flow and content

Implement the following local planning experience for the primary CTA, in the visual language of the page. Use a real button opening a labelled modal dialog. Choosing a pricing card must preselect that exact plan. A navigation link may move to another section; a planning CTA must lead to its review flow.

Use this content for the dialog, including the option details and notes:

{
  "slug": "type-reveal",
  "brand": "THE FOUNDRY REVIEW",
  "accent": "#875d25",
  "title": "A letter worth keeping",
  "intro": "Issue 01 — On leaving enough room. Three observations on typography, rhythm and the reader’s attention.",
  "facts": [
    [
      "Cadence",
      "One letter on the first Tuesday of each month"
    ],
    [
      "Reading time",
      "About four minutes"
    ],
    [
      "In this issue",
      "Scale, pauses and the craft of the final line"
    ]
  ],
  "notes": [
    "01 / Scale is a promise. A large heading asks for attention; the paragraph below must reward it with a precise idea.",
    "02 / A pause is part of the sentence. White space gives related thoughts a place to settle and separates what should be read next.",
    "03 / End where the reader can begin. A final line should leave an observation to carry into the next piece of work.",
    "Save this sample issue as a text file. No email address or newsletter registration is required."
  ]
}

- Explain before input that this is a fictional brand sample: choices can be reviewed and saved, with no external submission, booking, payment or registration. Use each brand's language. Do not launch a mail client or present an installer for a fictional product.
- Give every option group a legend, inputs explicit labels and errors linked descriptions. Validate options against the allowed values, requested dates as actual dates from today onward, and free text as 10–2,000 trimmed characters. Blank spaces alone must fail. Tracking accepts the sample reference TG-2048 only.
- Focus the first invalid field and preserve every entered value. On success, show the selected option WITH its full detail, requested date or brief, relevant facts and notes. An edit action returns to the preserved form. Do not claim a real reservation, purchase or account has succeeded.
- Save the complete review as UTF-8 text. A browser download request is not proof of a file being written. On download failure, retain the full text in a labelled, selectable textarea and offer retry. Do not show a false success state.
- Constrain modal content to the viewport with internal scrolling. Support keyboard and touch, trap focus while open, close on Escape and restore focus to the exact initiating control. Keep these operations available with motion disabled.
- If a separate project-contact CTA is present, let it collect a project brief and review it locally; a product selection CTA must retain the product choice. Verify both flows independently.