beta
Pixel Transition <mv-pixel-transition>
Alterna entre duas faces por meio de uma grade de pixels: pixels quadrados crescem sobre a primeira face em ordem aleatória, radial (a partir do ponteiro), diagonal ou por linhas, as faces se trocam sob uma cobertura completa e depois os pixels encolhem até sumir. Um único valor de progresso controla cada quadro, então, se o mouse sair no meio da transição, ela volta atrás suavemente.
| Categoria | Transições |
|---|---|
| Tipo | Web Component (<mv-pixel-transition>) |
| Status | beta |
| Keywords | safe-rewrite, pixel, transition, reveal, hover, card, swap, canvas, retro |
When to use
- A card should swap to a second face through a retro pixel dissolve on hover or focus
- A team or product tile should reveal hidden details with a radial pixel effect from the pointer
- Two images or states should toggle manually with a playful, interruptible pixel transition
Avoid when
- A two-sided card should flip in 3D rather than dissolve → use Flip Card instead
- Users should compare two images side by side with a draggable divider → use Image Compare instead
- The hidden face holds essential information on touch-first pages; hover reveals are easy to miss
Instalação
node scripts/add.mjs pixel-transition --out ./src/marvelousAgente de IA com o servidor MCP do Marvelous UI: install_components({ slugs: ["pixel-transition"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Arquivos copiados (dependências incluídas): tokens/tokens.css, core/base.css, core/canvas.js, core/dom.js, core/element.js, core/focus.js, core/motion.js, components/pixel-transition/pixel-transition.js, components/pixel-transition/pixel-transition.css.
Uso
Marcação de referência, para usar como ponto de partida e personalizar com atributos, data-* e variáveis CSS:
<div style="display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1rem;width:100%;max-width:820px">
<mv-pixel-transition grid="10" colors="oklch(0.97 0.02 85), oklch(0.88 0.08 70), oklch(0.8 0.12 55)" style="aspect-ratio:3/4">
<div style="display:grid;place-items:center;background:linear-gradient(160deg,oklch(0.62 0.19 285),oklch(0.45 0.17 300));color:white;text-align:center;padding:1rem">
<div><p style="margin:0;font:800 3rem/1 var(--mv-font-display)">?</p><p style="margin:.5rem 0 0;font-size:.85rem;opacity:.85">Hover the card</p></div>
</div>
<div style="display:grid;align-content:end;gap:.35rem;padding:1.1rem;background:linear-gradient(180deg,transparent 30%,oklch(0 0 none / .55)),radial-gradient(circle at 30% 30%,oklch(0.85 0.12 80),oklch(0.55 0.16 40));color:white">
<strong style="font-size:1.05rem">Maya Chen</strong>
<span style="font-size:.8rem;opacity:.9">Art Director · Tokyo</span>
</div>
</mv-pixel-transition>
<mv-pixel-transition trigger="click" pattern="radial" grid="14" duration="800" colors="oklch(0.72 0.15 160), oklch(0.62 0.14 175), oklch(0.8 0.12 140)" style="aspect-ratio:3/4">
<div style="display:grid;place-items:center;background:var(--mv-bg-muted);border:1px solid var(--mv-border);border-radius:inherit;text-align:center;padding:1rem">
<div><p style="margin:0;font-weight:600">Pro plan</p><p style="margin:.35rem 0 0;font-size:.8rem;color:var(--mv-fg-muted)">Click to see the price</p></div>
</div>
<div style="display:grid;place-items:center;background:oklch(0.3 0.06 170);color:white;text-align:center;padding:1rem">
<div><p style="margin:0;font:800 2.4rem/1 var(--mv-font-display)">$19</p><p style="margin:.35rem 0 0;font-size:.8rem;opacity:.8">per month, cancel anytime</p></div>
</div>
</mv-pixel-transition>
<mv-pixel-transition pattern="diagonal" grid="16" duration="600" colors="#0f172a, #1e293b, #334155" style="aspect-ratio:3/4">
<div style="display:grid;place-items:center;background:oklch(0.95 0.03 90);color:oklch(0.3 0.05 60);padding:1rem;text-align:center">
<p style="margin:0;font:700 1.35rem/1.2 var(--mv-font-display)">Day</p>
</div>
<div style="display:grid;place-items:center;background:oklch(0.2 0.04 265);color:oklch(0.9 0.05 265);padding:1rem;text-align:center">
<p style="margin:0;font:700 1.35rem/1.2 var(--mv-font-display)">Night ✦</p>
</div>
</mv-pixel-transition>
</div>API
Attributes
| Name | Tipo | Default | Description |
|---|---|---|---|
trigger | hover | click | manual | hover | Trigger (hover: also keyboard focus, and a tap on touch screens; click: click, Enter or Space; manual: toggle()/show() or the flipped attribute). |
pattern | random | radial | diagonal | rows | random | Order in which pixels appear (radial starts from where the pointer entered or clicked, the center otherwise). |
grid | number | 12 | Number of pixel columns, 2 to 60 (square pixels, rows follow). |
duration | number | 700 | Total duration of one switch (ms). |
colors | list of CSS colors | var(--mv-pixel-transition-color) | One or more colors (tokens accepted, they follow the theme), spread across the pixels. |
flipped | boolean | Back face shown (reflected by the component, writable). | |
data-state | front | back | Set by the component. |
Methods
| Name | Description |
|---|---|
toggle() | Switches to the other face. |
show(face) | Shows “front” or “back”. |
Events
| Name | Description |
|---|---|
mv-change | detail: { face, flipped }. At the moment the faces swap. |
Content structure
| Name | Description |
|---|---|
(child 1 / child 2) | Front face, then back face; the element takes the size of the larger one. |
CSS variables
| Name | Default | Description |
|---|---|---|
--mv-pixel-transition-color | var(--mv-fg) | Default pixel color. |
Accessibility
The hidden face is inert and aria-hidden. Without focusable content, the element becomes focusable (Enter/Space); in click mode it has role=button and aria-pressed. In hover mode, keyboard focus also reveals the back face and a tap toggles. Reduced motion: instant swap, no pixels. Forced colors: no painted pixels, the faces swap half-way. The frame loop only runs during a switch.