Cursor Type <mv-cursor-type>
精密なポインターに文字が反応する 1 つの大きな単語(404、キーワード)。各文字がそれぞれのスプリングで動きます:膨らむ可変ウェイト、ベースラインからの弾性的な伸び、押しのけられて傾きながら動く文字、または隣の文字を左右に広げる Dock 風の拡大鏡。
仕組み
精密なポインターに文字が反応する 1 つの大きな単語(404、キーワード)。各文字がそれぞれのスプリングで動きます:膨らむ可変ウェイト、ベースラインからの弾性的な伸び、押しのけられて傾きながら動く文字、または隣の文字を左右に広げる Dock 風の拡大鏡。タグだけで動作し、スクリーンリーダー向けに実際のテキストを保ち、マウスのない環境ではひとりでにゆっくりと漂います。
| カテゴリー | カーソル |
|---|---|
| タイプ | Web Component(<mv-cursor-type>) |
| ステータス | 安定版 |
| Keywords | cursor, typography, 404, variable-font, weight, elastic, scatter, magnify, dock, spring, headline, accessible |
When to use
- A 404 page or error screen needs one big headline that reacts letter by letter to the mouse
- A launch or showcase title should swell, stretch, scatter or magnify under the cursor without extra setup
- The headline should still feel alive on phones and tablets through a slow automatic drift
Avoid when
- Inline text or a subtle weight shift near the pointer is enough → use Variable Proximity instead
- Body copy or multi-line text; the effect is designed for one large headline
インストール
node scripts/add.mjs cursor-type --out ./src/marvelousMarvelous UI の MCP サーバーを使う AI エージェント:install_components({ slugs: ["cursor-type"], 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/cursor-type/cursor-type.js, components/cursor-type/cursor-type.css。
使い方
クイックスタート、動作する最小限のマークアップ:
<mv-cursor-type>404</mv-cursor-type>基本となるマークアップです。ここから属性、data-*、CSS 変数でカスタマイズしてください:
<div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(19rem,1fr));gap:1rem;width:min(100%,52rem);font-family:'Inter var','Segoe UI Variable Display','Segoe UI Variable',system-ui,sans-serif">
<section style="position:relative;display:grid;place-items:center;min-height:14rem;padding:1.5rem;overflow:hidden;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);background:var(--mv-surface)">
<mv-cursor-type variant="weight" radius="120" style="font-size:clamp(5rem,12vw,7.5rem);letter-spacing:-.04em">404</mv-cursor-type>
<small style="position:absolute;left:1.125rem;bottom:.875rem;color:var(--mv-fg-subtle)">weight: variable weight</small>
</section>
<section style="position:relative;display:grid;place-items:center;min-height:14rem;padding:1.5rem;overflow:hidden;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);background:var(--mv-surface)">
<mv-cursor-type variant="stretch" style="font-size:clamp(4rem,9vw,5.5rem);font-weight:800;letter-spacing:-.03em">Oops</mv-cursor-type>
<small style="position:absolute;left:1.125rem;bottom:.875rem;color:var(--mv-fg-subtle)">stretch: elastic letters</small>
</section>
<section style="position:relative;display:grid;place-items:center;min-height:14rem;padding:1.5rem;overflow:hidden;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);background:var(--mv-bg-emphasis)">
<mv-cursor-type variant="scatter" radius="140" style="font-size:clamp(3.5rem,8vw,4.75rem);font-weight:700;letter-spacing:-.03em">Lost?</mv-cursor-type>
<small style="position:absolute;left:1.125rem;bottom:.875rem;color:var(--mv-fg-muted)">scatter: letters scatter</small>
</section>
<section style="position:relative;display:grid;place-items:center;min-height:14rem;padding:1.5rem;overflow:hidden;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);background:var(--mv-surface)">
<mv-cursor-type variant="magnify" radius="120" style="font-size:clamp(2.75rem,6vw,3.5rem);font-weight:650;letter-spacing:-.02em;color:var(--mv-accent-fg)">Nowhere</mv-cursor-type>
<small style="position:absolute;left:1.125rem;bottom:.875rem;color:var(--mv-fg-subtle)">magnify: dock-style magnifier</small>
</section>
</div>API
Attributes
| Name | タイプ | Default | Description |
|---|---|---|---|
variant | weight | stretch | scatter | magnify | weight | What the letters do near the cursor: swell in weight, stretch tall, scatter away or magnify like a dock. |
radius | number | 180 | Cursor influence radius (px). |
strength | number | 1 | Strength (0 to 3). |
min-weight / max-weight | number | 200 / 900 | weight: weight at rest and under the cursor. A font without a weight axis ⇒ falls back to scaling. |
idle | auto | always | off | auto | Slow virtual cursor: auto where there is no fine hover pointer (touch, pen-only), always = even with a mouse, off = never. Off under reduced motion. |
CSS classes
| Name | Description |
|---|---|
mv-cursor-type-stage / -char / -glyph | Generated parts (position on -char, scale / weight on -glyph). |
CSS variables
| Name | Default | Description |
|---|---|---|
--mv-cursor-type-rest-weight | 200 | weight: weight before the script initializes. |
Accessibility
The word is exposed once through a visually hidden copy of the real text; the animated letters are an aria-hidden duplicate and ignore pointer events. Nothing needs to be operated, so there is nothing to reach by keyboard. Pointer reactions only run under (hover: hover) and (pointer: fine), touch events are ignored, and the system cursor is never hidden or replaced. The pointer is read on the parent, so the field reaches past the word. Reduced motion: letters follow the pointer one to one with no spring lag or overshoot, and the idle drift is off. Colors come from the host text, so forced colors apply unchanged. The frame loop sleeps at rest and pauses off screen.