Le texte se décode caractère par caractère à l'apparition et au survol.
<button class="scramble" data-text="WeTheLayout">WeTheLayout</button>
.scramble {font-family: "Courier New", monospace;font-size: clamp(2rem, 8vw, 4rem);font-weight: 700;letter-spacing: 0.05em;color: #fff;background: #111;border: none;padding: 0.5em 1em;border-radius: 0.5em;cursor: pointer;}
const CHARS = "!<>-_\\/[]{}—=+*^?#________";function scramble(el) {const target = el.dataset.text;let frame = 0;const queue = [...target].map((char, i) => ({char,start: Math.floor(Math.random() * 20),end: Math.floor(Math.random() * 20) + 20 + i * 2,}));function update() {let output = "";let done = 0;for (const item of queue) {if (frame >= item.end) {done++;output += item.char;} else if (frame >= item.start) {output += CHARS[Math.floor(Math.random() * CHARS.length)];} else {output += "";}}el.textContent = output;frame++;if (done < queue.length) {requestAnimationFrame(update);}}update();}document.querySelectorAll(".scramble").forEach((el) => {scramble(el);el.addEventListener("mouseenter", () => scramble(el));});