Components / Motion / Scramble

Scramble beta

Text that decodes itself: glyphs churn, then settle into the word, left to right.

Preview

It decoded when it scrolled in. Click it to run again.

<p class="k-scr" data-scramble="SEVENTH WELL" aria-label="SEVENTH WELL" style="font-size:19px;font-weight:600">
  <span aria-hidden="true" data-scr-out>SEVENTH WELL</span>
</p>
<p style="font-size:12.5px;color:var(--k-ink-3);margin-top:8px">It decoded when it scrolled in. Click it to run again.</p>
/* KATA Scramble — glyphs churn, then settle. */
.k-scr{font-family:var(--k-mono,monospace);letter-spacing:.04em}
// KATA Scramble — decodes on view; click decodes again.
document.querySelectorAll('[data-scramble]').forEach(function (el) {
  var out = el.querySelector('[data-scr-out]');
  var target = el.getAttribute('data-scramble') || '';
  var GLYPHS = '!<>-_\\/[]{}=+*^?#@$%&';
  var frame = 0, timer = null;
  var reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  function run() {
    if (reduced) { out.textContent = target; return; }
    frame = 0;
    clearInterval(timer);
    timer = setInterval(function () {
      frame++;
      var settled = Math.floor(frame / 2.2);
      var s = '';
      for (var i = 0; i < target.length; i++) {
        if (target[i] === ' ') { s += ' '; continue; }
        s += i < settled ? target[i] : GLYPHS[Math.floor(Math.random() * GLYPHS.length)];
      }
      out.textContent = s;
      if (settled >= target.length) { out.textContent = target; clearInterval(timer); }
    }, 34);
  }
  if ('IntersectionObserver' in window && !reduced) {
    var io = new IntersectionObserver(function (es) { if (es[0].isIntersecting) { run(); io.disconnect(); } }, { threshold: .4 });
    io.observe(el);
  } else { run(); }
  el.addEventListener('click', run);
});

Installation

CLI

node kata-ui.mjs add scramble

Writes the part’s CSS and JS into your project. New to the CLI? See the CLI doc.

Manual

  1. Load tokens.css once, before any part.
  2. Copy the CSS tab into your stylesheet.
  3. Copy the HTML where it belongs. The part has a script — include it after the markup; it initializes itself.

Usage

For short, loud strings — a title, a status line, a launch date. The script runs when the element scrolls into view and again whenever it is clicked. Long sentences scramble into noise; keep it under a dozen characters per burst if you can.

Accessibility

The real string is the element’s text and its aria-label from the start; the churn is aria-hidden theatre in a sibling span. Under prefers-reduced-motion there is no churn at all — the word simply stands there, decoded since birth.

Anatomy

The public surface of this part, read from its own source. Class names are the API — the CSS tab above is the full contract.

.k-scrclass
data-scrambledata hook
data-scr-outdata hook
aria-labelARIA
aria-hiddenARIA

Related parts