reusable effects and components already scattered across the site (plus a couple of new ones), demoed live with copy-pasteable code. grab whatever's useful for the next thing being built instead of re-deriving it from scratch.
function typeText(el, text, speed, onDone) {
let i = 0;
el.textContent = '';
(function step() {
if (i < text.length) {
el.textContent += text.charAt(i++);
setTimeout(step, speed);
} else if (onDone) onDone();
})();
}
function scrambleText(el, finalText, duration) {
const chars = '!<>-_/[]{}=+*^?#';
let frame = 0;
const totalFrames = Math.round(duration / 30);
const settleAt = finalText.split('').map((_, i) =>
Math.floor((i / finalText.length) * totalFrames));
const iv = setInterval(() => {
let out = '';
for (let i = 0; i < finalText.length; i++) {
out += frame >= settleAt[i] ? finalText[i]
: chars[Math.floor(Math.random() * chars.length)];
}
el.textContent = out;
if (frame++ > totalFrames) clearInterval(iv);
}, 30);
}
.glitch { animation: shake 0.2s cubic-bezier(.36,.07,.19,.97) both; }
@keyframes shake {
10%, 90% { transform: translate3d(-1px, 0, 0); }
20%, 80% { transform: translate3d(2px, 0, 0); }
30%, 50%, 70% { transform: translate3d(-4px, 0, 0); }
40%, 60% { transform: translate3d(4px, 0, 0); }
}
// el.classList.add('glitch'); setTimeout(() => el.classList.remove('glitch'), 200);
#scan {
position: absolute; inset: 0; pointer-events: none;
background: repeating-linear-gradient(0deg,
rgba(34,255,102,0.08) 0px, rgba(34,255,102,0.08) 1px,
transparent 1px, transparent 2px);
}
.cursor {
display: inline-block; width: 10px; height: 1.1em;
background-color: #00ff00; vertical-align: text-bottom;
animation: blink 1s step-end infinite; margin-left: 4px;
}
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
function renderLed(el, n, width) {
const digits = String(n).padStart(width, '0').split('');
el.innerHTML = digits.map(d =>
`<span class="led-digit">${d}</span>`).join('');
}
lines.forEach((text, i) => {
setTimeout(() => {
const el = document.createElement('div');
el.textContent = text;
el.style.animation = 'fadein 0.4s ease forwards';
container.appendChild(el);
}, i * 500);
});
// @keyframes fadein { from{opacity:0;transform:translateY(3px)} to{opacity:1;transform:translateY(0)} }
.chroma-glitch {
color: red;
text-shadow: 1px 1px lime, -1px -1px blue;
animation: chromaGlitch 0.3s infinite;
}
@keyframes chromaGlitch {
0% { transform: translate(0, 0); }
20% { transform: translate(-1px, 1px); }
40% { transform: translate(1px, -1px); }
60% { transform: translate(-1px, 1px); }
80% { transform: translate(1px, 1px); }
100% { transform: translate(0, 0); }
}
.hover-reveal { color: #555; transition: color 0.5s ease; }
.hover-reveal:hover { color: #0f0; }
el.addEventListener('mousemove', e => {
const r = el.getBoundingClientRect();
const dot = document.createElement('div');
dot.className = 'trail-dot';
dot.style.left = (e.clientX - r.left) + 'px';
dot.style.top = (e.clientY - r.top) + 'px';
el.appendChild(dot);
setTimeout(() => dot.remove(), 1000);
});
/* .trail-dot { position:absolute; width:10px; height:10px; background:cyan;
border-radius:50%; pointer-events:none; mix-blend-mode:difference;
animation: fadeOutTrail 1s forwards; }
@keyframes fadeOutTrail { to { opacity:0; transform:scale(3); } } */
const words = ['LOADING', 'BOOTING', 'ERROR', 'SUCCESS', '??!?!'];
const original = document.title;
const iv = setInterval(() => {
document.title = words[Math.floor(Math.random() * words.length)]
+ Math.floor(Math.random() * 99);
}, 300);
setTimeout(() => { clearInterval(iv); document.title = original; }, 5000);
<p style="font-size:4px; color:#111;"> the hidden text, colored to match its background </p> /* only found via Ctrl+A or view-source — never rely on it being unbreakable, it's a "reward the curious" trick, not real security */
@keyframes breathe {
0% { transform: scale(1); }
50% { transform: scale(1.02); }
100% { transform: scale(1); }
}
/* apply to a background container: animation: breathe 10s ease-in-out infinite; */
function triggerAnomaly(message) {
document.body.classList.add('shake');
readout.innerText = message;
readout.style.display = 'block';
let n = 0;
const iv = setInterval(() => {
readout.style.opacity = Math.random() > 0.5 ? '1' : '0';
if (++n > 10) {
clearInterval(iv);
readout.style.opacity = '1';
setTimeout(() => {
readout.style.display = 'none';
document.body.classList.remove('shake');
}, 2000);
}
}, 50);
}
/* .shake reuses the same shake keyframes as the screen glitch card above.
readout is a fixed, centered, high-z-index overlay div. */
// real version: full-viewport, position:fixed, triggered by Shift+F4
bsod.style.animation = 'bsod-flicker 0.15s infinite alternate';
bsod.innerHTML = `<pre>
*** STOP: 0x000000D3 (...)
A problem has been detected and Windows has been shut down...
*** STOP: RUKUS_MODE_EXCEPTION_NOT_HANDLED
</pre>`;
document.addEventListener('keydown', e => {
if (e.shiftKey && e.key === 'F4') bsod.style.display = 'block';
});
/* @keyframes bsod-flicker { from{opacity:.98} to{opacity:1} } */
.glitch-mode { animation: glitchAnim 0.5s infinite, hueShift 1s infinite; filter: contrast(200%); }
@keyframes glitchAnim {
0% { transform: translate(0); }
20% { transform: translate(-2px,2px) rotate(1deg); }
40% { transform: translate(2px,-2px) rotate(-1deg); }
/* ...settles back to 0 by 100% */
}
@keyframes hueShift {
0% { filter: hue-rotate(0deg) contrast(200%); }
50% { filter: hue-rotate(180deg) contrast(200%); }
100% { filter: hue-rotate(360deg) contrast(200%); }
}
// + a <canvas> overlay redrawing random per-pixel noise every 100ms,
// removed after 3s along with the glitch-mode class.
.glitch { position: relative; display: inline-block; }
.glitch::before, .glitch::after {
content: attr(data-text); position: absolute; left: 0; top: 0;
width: 100%; overflow: hidden;
}
.glitch::before { color: cyan; clip-path: inset(0 0 82% 0); animation: glitchTop 3.4s infinite steps(1); }
.glitch::after { color: magenta; clip-path: inset(78% 0 0 0); animation: glitchBottom 3.4s infinite steps(1); }
@keyframes glitchTop {
0%, 92%, 100% { transform: translate(0,0); clip-path: inset(0 0 82% 0); }
93% { transform: translate(-3px,1px); clip-path: inset(0 0 60% 0); }
95% { transform: translate(3px,-1px); clip-path: inset(0 0 88% 0); }
}
/* glitchBottom mirrors this, offset differently — see 404.html */
@media (prefers-reduced-motion: reduce) {
.glitch::before, .glitch::after { animation: none; }
}
.cube { width: 100px; height: 100px; position: relative;
transform-style: preserve-3d; animation: rotate 8s linear infinite; }
.cube-face { position: absolute; width: 100px; height: 100px; border: 2px solid #fff; }
.front { transform: translateZ(50px); }
.back { transform: rotateY(180deg) translateZ(50px); }
.right { transform: rotateY(90deg) translateZ(50px); }
.left { transform: rotateY(-90deg) translateZ(50px); }
.top { transform: rotateX(90deg) translateZ(50px); }
.bottom { transform: rotateX(-90deg) translateZ(50px); }
@keyframes rotate {
from { transform: rotateX(0deg) rotateY(0deg); }
to { transform: rotateX(360deg) rotateY(360deg); }
}
@keyframes crtFlicker {
0%, 100% { opacity: 1; }
42% { opacity: 0.96; }
43% { opacity: 0.4; }
44% { opacity: 0.96; }
}
/* apply: animation: crtFlicker 1.2s infinite; */