Binary
import { useEffect, useState } from 'react';
const css = `
.loader-binary {
display: inline-flex;
flex-direction: column;
gap: 8px;
align-items: center;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.loader-binary__bits { display: flex; gap: 4px; }
.loader-binary__bit {
display: grid;
place-items: center;
width: 14px;
height: 22px;
border-radius: 3px;
background: light-dark(#f3f4f7, #1a1c1f);
box-shadow: inset 0 0 0 1px light-dark(#dbdde1, #2e3035);
color: light-dark(#cbced3, #393c41);
font-size: 11px;
transition: background-color 0.12s ease, color 0.12s ease, box-shadow 0.12s ease;
}
.loader-binary__bit:nth-child(4) { margin-right: 4px; }
.loader-binary__bit[data-on] {
background: light-dark(#373a40, #f1f2f3);
color: light-dark(#fbfcfd, #121417);
box-shadow: 0 0 6px color-mix(in oklab, light-dark(#373a40, #f1f2f3) 22%, transparent);
}
.loader-binary__hex { font-size: 10px; letter-spacing: 0.12em; color: light-dark(#5f626a, #a7abb2); }
.loader-binary__hex b { color: light-dark(#373a40, #f1f2f3); font-weight: 600; }
`;
export function BinaryLoader() {
const [n, setN] = useState(0);
useEffect(() => {
if (matchMedia('(prefers-reduced-motion: reduce)').matches) return setN(0x2a);
const id = window.setInterval(() => setN((v) => (v + 1) % 256), 110);
return () => clearInterval(id);
}, []);
return (
<>
<style>
{css}
</style>
<div className="loader-binary" role="status" aria-label="Loading">
<span className="loader-binary__bits" aria-hidden="true">
{Array.from({ length: 8 }, (_, i) => {
const on = (n >> (7 - i)) & 1;
return (
<span key={i} className="loader-binary__bit" data-on={on || undefined}>
{on}
</span>
);
})}
</span>
<span className="loader-binary__hex" aria-hidden="true">
0x<b>{n.toString(16).toUpperCase().padStart(2, '0')}</b> · {String(n).padStart(3, '0')}
</span>
</div>
</>
);
}Markup where the component goes, CSS in your stylesheet, script before </body>. In Vue, Svelte or Angular, call initLoaderBinary(el) on the mounted element instead.
<div class="loader-binary" role="status" aria-label="Loading">
<span class="loader-binary__bits" aria-hidden="true">
<span class="loader-binary__bit">0</span>
<span class="loader-binary__bit">0</span>
<span class="loader-binary__bit">0</span>
<span class="loader-binary__bit">0</span>
<span class="loader-binary__bit">0</span>
<span class="loader-binary__bit">0</span>
<span class="loader-binary__bit">0</span>
<span class="loader-binary__bit">0</span>
</span>
<span class="loader-binary__hex" aria-hidden="true">0x<b>00</b> · 000</span>
</div>.loader-binary {
display: inline-flex;
flex-direction: column;
gap: 8px;
align-items: center;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.loader-binary__bits { display: flex; gap: 4px; }
.loader-binary__bit {
display: grid;
place-items: center;
width: 14px;
height: 22px;
border-radius: 3px;
background: light-dark(#f3f4f7, #1a1c1f);
box-shadow: inset 0 0 0 1px light-dark(#dbdde1, #2e3035);
color: light-dark(#cbced3, #393c41);
font-size: 11px;
transition: background-color 0.12s ease, color 0.12s ease, box-shadow 0.12s ease;
}
.loader-binary__bit:nth-child(4) { margin-right: 4px; }
.loader-binary__bit[data-on] {
background: light-dark(#373a40, #f1f2f3);
color: light-dark(#fbfcfd, #121417);
box-shadow: 0 0 6px color-mix(in oklab, light-dark(#373a40, #f1f2f3) 22%, transparent);
}
.loader-binary__hex { font-size: 10px; letter-spacing: 0.12em; color: light-dark(#5f626a, #a7abb2); }
.loader-binary__hex b { color: light-dark(#373a40, #f1f2f3); font-weight: 600; }function initLoaderBinary(root) {
var bits = root.querySelectorAll('.loader-binary__bit');
var hex = root.querySelector('.loader-binary__hex b');
var dec = hex && hex.nextSibling;
if (bits.length !== 8 || !hex || !dec) return;
function show(n) {
bits.forEach(function (b, i) {
var on = (n >> (7 - i)) & 1;
b.textContent = String(on);
b.toggleAttribute('data-on', !!on);
});
hex.textContent = n.toString(16).toUpperCase().padStart(2, '0');
dec.textContent = ' · ' + String(n).padStart(3, '0');
}
if (matchMedia('(prefers-reduced-motion: reduce)').matches) {
show(0x2a);
return;
}
var n = 0;
var timer = setInterval(function () { show((n = (n + 1) % 256)); }, 110);
return function () { clearInterval(timer); };
}
document.querySelectorAll('.loader-binary').forEach(initLoaderBinary);Goal: Create a "Binary" loader.
Visual behavior: A byte counting up in lit bits, nibble by nibble, with its hex and decimal value counting beside it. It wraps from 255 back to zero and keeps going.
Technique:
- Eight bit cells in two nibbles (a gap after the fourth); a cell whose bit is set gets a light fill, dark text and a faint glow.
- An interval adds one every 110ms modulo 256; each bit is (n >> (7 - i)) & 1.
- Below, the value prints as 0xHH and as three decimal digits; quick background and colour transitions soften the flicker of the low bits.
Accessibility: The root has role="status" and aria-label="Loading"; everything inside is decorative. Under prefers-reduced-motion it shows a still 0x2A.
My stack: {{USER_STACK}}
My styling: {{USER_STYLING}}
My constraints: {{USER_CONSTRAINTS}}
My colors: neutral only. Black, white and grays, no hues. Use the color values above as written, or my project's closest neutral tokens.
Return a single self-contained component. No dependencies.Goal: Create a "Binary" loader.
Visual behavior: A byte counting up in lit bits, nibble by nibble, with its hex and decimal value counting beside it. It wraps from 255 back to zero and keeps going.
Technique:
- Eight bit cells in two nibbles (a gap after the fourth); a cell whose bit is set gets a light fill, dark text and a faint glow.
- An interval adds one every 110ms modulo 256; each bit is (n >> (7 - i)) & 1.
- Below, the value prints as 0xHH and as three decimal digits; quick background and colour transitions soften the flicker of the low bits.
Accessibility: The root has role="status" and aria-label="Loading"; everything inside is decorative. Under prefers-reduced-motion it shows a still 0x2A.
My stack: {{USER_STACK}}
My styling: {{USER_STYLING}}
My constraints: {{USER_CONSTRAINTS}}
My colors: use my project's existing color tokens. The color values above are grayscale placeholders. Map each one by its role (surface, text, border, accent, glow) to my theme, and keep their relative lightness so contrast and the effect still read.
Return a single self-contained component. No dependencies.Paste into Claude, ChatGPT or Cursor after filling in {{USER_STACK}}, {{USER_STYLING}} and {{USER_CONSTRAINTS}}. Neutral keeps the greys you see here; Match my project asks the model to map them onto your own colour tokens.
Free to use in any project, commercial included. MIT-0, no attribution required. Licence
About this component
A byte counting up in lit bits, nibble by nibble, with its hex and decimal value counting beside it. It wraps from 255 back to zero and keeps going.
- Dependencies
- None
- Difficulty
- Beginner
- Triggers
- continuous, loop, state change
- Techniques
- interval, css transition
- Reduced motion
- Respected
- Theme
- Light and dark (follows your page's color-scheme)
The root has role="status" and aria-label="Loading"; everything inside is decorative. Under prefers-reduced-motion it shows a still 0x2A.