Text Scramble

텍스트 스크램블

Characters flicker through random glyphs before "decoding" into the final word — the hacker-movie terminal look.

Also known as: Scramble textDecrypt text effect
···
html
<span id="txsEl">HOVER ME</span>
css
#txsEl{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:clamp(18px,6.5vmin,30px);
  font-weight:700;letter-spacing:.04em;color:var(--fg);cursor:pointer}
js
let auto=true;
addEventListener('pointerdown',()=>{auto=false;},{capture:true});
addEventListener('pointermove',()=>{auto=false;},{capture:true});
const el=document.getElementById('txsEl');
const CHARS='ABCDEFGHIJKLMNOPQRSTUVWXYZ#%&$*+-01';
const phrases=['HOVER ME','SCRAMBLE','DECODED','TRY ME'];
let phraseIdx=0, running=false;
function scrambleTo(text){
  if(running) return; running=true;
  const len=Math.max(el.textContent.length,text.length);
  const totalFrames=24;
  let frame=0;
  function step(){
    let out='';
    for(let i=0;i<len;i++){
      if(i<text.length && frame/totalFrames > i/len) out+=text[i];
      else out+=CHARS[Math.floor(Math.random()*CHARS.length)];
    }
    el.textContent=out;
    frame++;
    if(frame<=totalFrames) requestAnimationFrame(step);
    else el.textContent=text, running=false;
  }
  step();
}
el.addEventListener('pointerenter',()=>{
  auto=false;
  phraseIdx=(phraseIdx+1)%phrases.length;
  scrambleTo(phrases[phraseIdx]);
});
async function autoSeq(){
  while(auto){
    await new Promise(res=>{ const s=performance.now(); (function st(now){ if(!auto) return res(); if(now-s<1400) requestAnimationFrame(st); else res(); })(performance.now()); });
    if(!auto) break;
    phraseIdx=(phraseIdx+1)%phrases.length;
    scrambleTo(phrases[phraseIdx]);
  }
}
autoSeq();

For each character position in the target string, decide which frame it should "lock in" on (left to right in order, or randomized), and until that frame, draw a different random glyph (uppercase letters, digits, symbols) from a character pool every frame. Once locked, that position freezes on its final character.

Pick a total frame count (typically 20–30 animation frames) and compare each character's index against overall progress so positions lock left-to-right in order — that reads like a typewriter decoding left to right.

If the starting and target strings differ in length (e.g. "HOVER ME" → "DECODED"), loop to the longer length and let the shorter string's extra slots fill with random glyphs before fading out, so the transition still feels natural.

When to use

Use it sparingly — a hero headline on a code/terminal-themed page, a button label changing state. Don't use it in body copy.