Typewriter <mv-typewriter>

히어로 문구를 위한 타자기: 불규칙한 리듬과 문장 부호에서의 멈춤으로 문구를 한 글자씩 입력하고, 바, 블록, 밑줄 캐럿 뒤에서 지우고 순환하며, 최종 크기로 미리 확보된 상자 안에서 동작해 주변이 움직이지 않습니다.

카테고리애니메이션 텍스트
유형Web Component (<mv-typewriter>)
상태안정
Keywordstypewriter, typing, caret, cursor, rotating, hero, terminal

When to use

  • A hero line should type several phrases in a loop, deleting between them, without pushing the layout around
  • A terminal or conversational tone needs realistic irregular typing with pauses on punctuation
  • Animated copy must stay readable by screen readers and findable with the browser search

Avoid when

  • A single word should change inside a sentence with a smooth width glide → use Word Rotate instead
  • Key information only appears after long typing delays; visitors may leave before reading it

설치

node scripts/add.mjs typewriter --out ./src/marvelous

Marvelous UI MCP 서버를 사용하는 AI 에이전트: install_components({ slugs: ["typewriter"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

복사되는 파일(의존성 포함): tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/motion.js, core/observe.js, components/typewriter/typewriter.js, components/typewriter/typewriter.css.

사용법

기본 마크업입니다. 여기서 시작해 속성, data-*, CSS 변수로 커스터마이즈하세요:

<div id="tw-demo" style="display:grid;gap:1.75rem;width:min(100%,44rem);margin-inline:auto;text-align:center">
  <h2 style="margin:0;font:700 clamp(1.8rem,4.4vw,3rem)/1.1 var(--mv-font-display);letter-spacing:-.035em">
    We build<br>
    <mv-typewriter loop words="sites that convert., apps people keep., brands that stick." colors="var(--mv-accent), var(--mv-info), var(--mv-success)"></mv-typewriter>
  </h2>

  <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(18rem,100%),1fr));gap:.75rem;text-align:start">
    <div style="padding:1rem 1.1rem;border-radius:var(--mv-radius-lg);background:var(--mv-gray-950);border:1px solid var(--mv-border);color:var(--mv-gray-100);font:500 .9rem/1.6 var(--mv-font-mono);box-shadow:var(--mv-shadow-md)">
      <span style="color:var(--mv-gray-400)">~/project $</span>
      <mv-typewriter caret="block" speed="45" delay="600" style="--mv-typewriter-caret:var(--mv-gray-300)">npx mv add typewriter</mv-typewriter>
    </div>
    <div style="padding:1rem 1.1rem;border:1px solid var(--mv-border);border-radius:var(--mv-radius-lg);background:var(--mv-surface);font-size:1.05rem">
      <mv-typewriter caret="underscore" loop pause="1400">
        <span>Hi, I’m Iris.</span>
        <span>I write your briefs.</span>
        <span>I summarize your meetings.</span>
      </mv-typewriter>
    </div>
  </div>

  <div style="display:flex;justify-content:center">
    <button class="mv-button" data-variant="outline" data-size="sm" id="tw-demo-replay">Replay</button>
  </div>
</div>
<script type="module">
  const root = document.getElementById("tw-demo");
  root.querySelector("#tw-demo-replay").addEventListener("click", () => {
    root.querySelectorAll("mv-typewriter").forEach((el) => el.replay());
  });
</script>

API

Attributes

Name유형DefaultDescription
wordsstringPhrases separated by commas (or by | if they contain commas). Otherwise: <span> children (their classes stay on the phrase) or plain text.
loopbooleanDeletes and cycles through the phrases in a loop. Without loop, stops on the last phrase. Hover or focus holds the current phrase.
caretbar | block | underscore | nonebarCaret style: solid while typing, a few blinks at rest, then steady.
speednumber (ms)55Average delay between two letters.
delete-speednumber (ms)28Delay between two deletions.
pausenumber (ms)1800Reading time before deleting.
delaynumber (ms)0Delay before the first letter.
jitternumber 0-10.45Typing irregularity (0 = metronome).
colorslist of CSS colorsColor per phrase, cycling (tokens accepted).
triggerview | load | hover | manualviewTrigger (combinable). view starts on first view, hover replays a finished sequence, manual shows the final text and waits for replay().

Methods

NameDescription
replay()Restarts from the first phrase.

Events

NameDescription
mv-changeNew phrase started (detail.index).
mv-endLast phrase typed (without loop).

CSS classes

NameDescription
mv-typewriter-phraseOne per phrase (generated, aria-hidden). The one on screen holds -typed, -caret and -pending; the others are hidden="until-found".
mv-typewriter-typed / -pendingTyped part and untyped rest of the current phrase; the rest keeps its place but is not painted.
mv-typewriter-caretZero-width caret anchor; the caret is drawn by its ::before.

CSS variables

NameDefaultDescription
--mv-typewriter-caretvar(--mv-accent)Caret color.
--mv-typewriter-blink1.1sBlink period.

Accessibility

Every phrase stays real, complete text: typing only hides the untyped rest of the visible phrase, so the box is reserved at its final size and never shifts. Screen readers read all phrases once, in order, from a visually hidden copy; the animated layer is aria-hidden and has no aria-live. Find in page matches the visible phrase and the hidden ones (hidden="until-found"): a match shows that phrase whole and stops the cycle. Hovering or focusing it (or the link around it) holds the current phrase and types back one being erased. The sequence freezes off screen and in a hidden tab. Reduced motion: the text appears at once, with a steady caret. The caret blinks a few times, then stays lit. Forced colors: the caret uses CanvasText. Print shows the whole phrase.

이 페이지는 AI로 번역되었습니다. 번역 문제 신고