Add a little weirdness to your blog: triple-click an image and it crackles with error energy and glows for a brief moment. This post shows the exact code, how it works, and a plain-language walkthrough of the JavaScript so non-coders can follow along.
originally posted as the 21st post for Blaugust
What weâre building
- You wrap an image in a simple container:
<div class="egg">âŚ</div>
. - If someone clicks the image three times quickly, the container gets a temporary class (
egg-active
). - CSS sees that class and runs a short glitch/crackle + glow animation.
- People who prefer reduced motion get a calmer glow, no jitter.
HTML
Wrap any image you want to enchant:
<div class="egg center">
<img src="your-image.jpg" alt="Describe the image here" />
</div>
If you already use a
.center
class to center images, apply it to the container (.egg
) instead of the<img>
. See the CSS below.
CSS
Drop this into your site CSS. It handles the glow, the glitch slice, and respects prefers-reduced-motion
.
:root {
--egg-glow: var(--accent-color, #8cffd0);
--egg-glow-2: #ff3b3b; /* secondary 'error' tint */
--egg-flash-duration: 900ms;
}
/* The container is the âeffect layerâ */
.egg {
position: relative;
display: inline-block;
}
.center {
display: block;
margin-left: auto !important;
margin-right: auto !important;
width: 50% !important; /* adjust to taste */
}
/* Fill the container width with image */
.egg img {
display: block;
max-width: 100%;
height: auto;
transition: filter 120ms ease;
}
/* Overlay layers for both animation layers*/
.egg::before,
.egg::after {
content: "";
position: absolute;
inset: 0;
pointer-events: none;
opacity: 0;
mix-blend-mode: screen; /* works on light/dark backgrounds */
}
.egg::before {
background:
repeating-linear-gradient(
0deg,
rgba(255,255,255,0.0) 0 2px,
rgba(255,255,255,0.03) 2px 3px
); /* subtle scanlines */
}
.egg::after {
background:
radial-gradient(60% 40% at 50% 50%, var(--egg-glow) 0%, transparent 70%),
radial-gradient(40% 30% at 55% 45%, var(--egg-glow-2) 0%, transparent 60%);
filter: blur(8px) saturate(1.2);
}
/* Active state: brief jitter + glow */
.egg.egg-active img {
animation: egg-jitter 90ms steps(2, end) 0s 6;
filter:
drop-shadow(0 0 0.5rem var(--egg-glow))
drop-shadow(0 0 1.2rem var(--egg-glow-2));
}
.egg.egg-active::before,
.egg.egg-active::after {
opacity: 1;
animation:
egg-slice var(--egg-flash-duration) ease-out,
egg-pulse var(--egg-flash-duration) ease-out;
}
/* Animations */
@keyframes egg-jitter {
0% { transform: translate(0, 0) }
20% { transform: translate(-1px, 0.5px) }
40% { transform: translate( 1px, -0.5px) }
60% { transform: translate(-0.5px, -1px) }
80% { transform: translate( 0.5px, 1px) }
100% { transform: translate(0, 0) }
}
/* Simulated âerrorâ slices scanning through */
@keyframes egg-slice {
0% { clip-path: inset(0 0 90% 0) }
15% { clip-path: inset(85% 0 0 0) }
30% { clip-path: inset(0 0 80% 0) }
45% { clip-path: inset(70% 0 0 0) }
60% { clip-path: inset(0 0 65% 0) }
75% { clip-path: inset(50% 0 0 0) }
100% { clip-path: inset(0 0 0 0) }
}
/* Glow that blooms and fades */
@keyframes egg-pulse {
0% { opacity: 0; filter: blur(12px) saturate(1.2) }
15% { opacity: 1; filter: blur(10px) saturate(1.4) }
60% { opacity: 0.7; filter: blur(8px) saturate(1.3) }
100% { opacity: 0; filter: blur(6px) saturate(1.1) }
}
/* Respect motion preferences */
@media (prefers-reduced-motion: reduce) {
.egg.egg-active img {
animation: none;
filter: drop-shadow(0 0 0.9rem var(--egg-glow));
}
.egg.egg-active::before,
.egg.egg-active::after {
animation: none;
opacity: 1;
}
}
Customize the look
- Change
--egg-glow
to piggyback on your siteâs accent colors if you're using root color variable. - Change
--egg-flash-duration
for longer/shorter effects. - Tone down the jitter by changing the
egg-jitter
duration or number of iterations (the6
).
JavaScript
The more complex script I've had to figure out... it listens for triple-clicks on any .egg
container and toggles the active class briefly.
<script>
(function () {
const TRIPLE_WINDOW_MS = 500; // time window to detect 3 rapid clicks
const ACTIVE_MS = 900; // how long the effect class stays on
// Delegate clicks so any .egg on the page just works
document.addEventListener('click', (e) => {
const container = e.target.closest('.egg');
if (!container) return;
const now = performance.now();
const state = container._eggState || (container._eggState = { last: 0, count: 0, timer: null });
// Reset if too slow between clicks
if (now - state.last > TRIPLE_WINDOW_MS) state.count = 0;
state.last = now;
state.count++;
if (state.count === 3) {
state.count = 0; // ready for the next triple
// retrigger animation if spam-clicked
container.classList.remove('egg-active');
// force reflow so CSS animations restart cleanly
// eslint-disable-next-line no-unused-expressions
container.offsetWidth;
container.classList.add('egg-active');
clearTimeout(state.timer);
state.timer = setTimeout(() => {
container.classList.remove('egg-active');
}, ACTIVE_MS);
}
}, { passive: true });
})();
</script>
Plain-language translation of the JavaScript
- We listen for clicks anywhere on the page.
If the click happened inside a box with the class.egg
, we care; otherwise we ignore it. - Store the last click on the respective
.egg
container.
That memory stores when the last click happened and how many recent clicks weâve seen. - If clicks are too far apart, reset.
If more than half a second passes between clicks, we reset the count to zero. - If we reach three fast clicks, we trigger the effect.
We add a CSS class (egg-active
) for just under a second. That class makes the glow and crackle happen. - If someone triple-clicks again right away, the animation restarts cleanly.
We briefly remove the class and re-add it so CSS restarts the animation from the beginning. - After the effect time ends, we clean up.
We remove the class so the image returns to normal.
Accessibility notes
Reduced motion respected:
People withprefers-reduced-motion: reduce
get a calm glow without jitter. This keeps the vibe without the agitation.No hidden content gates:
The triple-click is fun, but it doesnât hide information or block interaction if someone never triggers it.Alt text:
Donât forget a goodalt
for the image itselfâeaster egg or not, the content matters.