25 CSS Text Animations 21 / 25

CSS Text Decryption Animation

A sophisticated matrix-style decryption where columns of binary rain resolve into readable text — more structured than scramble, more cinematic than typewriter.

CSS + JS MIT licensed
Live Demo Open in tab
Open in playground

The code

<div class="ta-21">
  <div class="ta-21__stage">
    <p class="ta-21__label">System Boot</p>
    <div class="ta-21__output" id="ta-21-output" aria-label="CLASSIFIED DATA"></div>
    <p class="ta-21__sub">binary rain columns · staggered column resolve · JS timer</p>
  </div>
</div>
.ta-21, .ta-21 *, .ta-21 *::before, .ta-21 *::after {
  margin: 0; padding: 0; box-sizing: border-box;
}
.ta-21 ::selection { background: #14532d; color: #bbf7d0; }

.ta-21 {
  --bg: #010a04;
  --rain: #15803d;
  --bright: #4ade80;
  min-height: 100vh;
  background: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  font-family: 'JetBrains Mono', 'Courier New', monospace;
}

.ta-21__stage { text-align: center; width: 100%; }

.ta-21__label {
  font-size: 0.68rem;
  color: var(--rain);
  letter-spacing: 0.25em;
  text-transform: uppercase;
  margin-bottom: 0.6rem;
}

.ta-21__output {
  font-size: clamp(1.6rem, 5vw, 2.8rem);
  font-weight: 700;
  letter-spacing: 0.15em;
  display: flex;
  justify-content: center;
  gap: 0.05em;
  min-height: 1.2em;
}

.ta-21__col {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  position: relative;
}

.ta-21__char {
  display: inline-block;
  color: var(--rain);
  animation: ta-21-rain 0.08s linear infinite;
  opacity: 0.7;
}

.ta-21__char.decoded {
  color: var(--bright);
  animation: ta-21-flash 0.3s ease-out forwards;
  text-shadow: 0 0 12px var(--bright), 0 0 30px rgba(74,222,128,0.4);
}

.ta-21__sub {
  font-size: 0.65rem;
  color: #052010;
  margin-top: 0.8rem;
  letter-spacing: 0.08em;
}

@keyframes ta-21-rain {
  0%   { opacity: 0.4; }
  50%  { opacity: 1; }
  100% { opacity: 0.4; }
}

@keyframes ta-21-flash {
  0%   { opacity: 0; transform: scaleY(1.3); }
  60%  { opacity: 1; transform: scaleY(1); }
  100% { opacity: 1; transform: scaleY(1); }
}

@media (prefers-reduced-motion: reduce) {
  .ta-21__column, .ta-21__char { animation: none !important; transition: none; }
}
(function() {
  const el = document.getElementById('ta-21-output');
  if (!el) return;

  const finalText = 'CLASSIFIED DATA';
  const bits = '01';
  const columnDelay = 180;

  function decode() {
    el.innerHTML = '';
    const intervals = [];

    [...finalText].forEach((ch, i) => {
      const charEl = document.createElement('span');
      charEl.className = 'ta-21__char';
      charEl.textContent = ch === ' ' ? ' ' : bits[Math.floor(Math.random() * 2)];
      el.appendChild(charEl);

      if (ch === ' ') return;

      const iv = setInterval(() => {
        charEl.textContent = bits[Math.floor(Math.random() * 2)];
      }, 80);
      intervals.push(iv);

      setTimeout(() => {
        clearInterval(iv);
        charEl.textContent = ch;
        charEl.classList.add('decoded');
      }, 500 + i * columnDelay);
    });

    setTimeout(() => {
      intervals.forEach(clearInterval);
      setTimeout(decode, 2800);
    }, 500 + finalText.length * columnDelay + 400);
  }

  decode();
})();

How this works

JavaScript creates a grid where each character position first displays rapidly cycling binary digits (0 and 1) styled as a falling column effect via CSS animation. After a staggered delay proportional to column position, the cycling stops and the final character resolves with a green flash transition. The binary rain uses a fast setInterval per column, independent timers that stop and lock when their column's time comes.

CSS handles all the visual styling: the binary characters use a green monospace font with a pulsing opacity animation to suggest a live data stream. The final resolved characters switch to a different, brighter class that amplifies the glow — making the transition from 'decrypting' to 'decoded' visually distinct. The column-by-column resolution creates a sweeping left-to-right decode front.

Customize

  • Change the decode front direction from left-to-right to right-to-left by reversing the delay calculation: (totalChars - i) * columnDelay.
  • Add a wipe cursor — a bright vertical bar that sweeps across as columns resolve — by positioning a CSS ::before pseudo-element and translating it in sync with the decode front.
  • Mix in a random scatter pattern instead of linear sweep by using Math.random() * maxDelay per column for a simultaneous burst decode.
  • Apply to a table of data values, decrypting each cell independently on different timelines for a data-visualisation reveal effect.
  • Change the rain characters from binary to hexadecimal by updating the character pool to '0123456789ABCDEF' for a network packet aesthetic.

Watch out for

  • Running many independent setInterval timers simultaneously is fine for short demos but doesn't scale to thousands of characters — batch updates using a single master interval instead.
  • The binary rain column needs a fixed character width container — use a monospaced font and set min-width on each character cell to prevent layout jitter as digits change width.
  • Always clear all column intervals when the animation completes or when the element is removed from the DOM to prevent memory leaks in single-page application contexts.

Browser support

ChromeSafariFirefoxEdge
All All All All

Uses only standard setInterval and DOM manipulation. Works in all JavaScript-enabled browsers with no compatibility concerns.

Search CodeFronts

Loading…