Reaction systems that don't melt browsers
25 October 2022
I spent three days watching particles crawl across screens.
A corporate live event platform needed reactions — hearts, applause, confetti — but every implementation either looked boring or made laptops sound like jet engines. Users would click a heart button and wait two seconds for the animation to start, or get bombarded with so many particles they couldn’t see the actual event content.
Make them too subtle and they feel lifeless. Make them too flashy and you’ve built a screen saver that happens to interrupt people trying to watch presentations.
The performance trap
Every particle system I tried started with the wrong assumption: more particles = better experience. Five hundred confetti pieces looked amazing on my development machine. On a 2017 MacBook watching through Chrome with twelve other tabs open, it looked like a slideshow.
The number of particles wasn’t the only problem I found. Most particle libraries optimize for visual complexity, not performance under real conditions. I realized users weren’t watching on clean test environments. They were multitasking, running Slack, maybe screen sharing the event to colleagues.
I needed reactions that felt immediate and satisfying but still worked when resources got tight.
Building constraints first
I started with limits instead of “what looks cool”:
- Maximum 80 particles per reaction, regardless of animation type
- 2-second maximum lifespan for any particle
- No more than 350 total particles for the most intensive effect (confetti)
- Animations must feel instant on click
The constraint that mattered most was the 2-second lifespan. Particles that stick around create visual noise and eat memory. I decided to use fewer particles that appear and disappear cleanly rather than a screen full of lingering effects.
particles: {
life: {
duration: { value: 2 },
count: 1,
},
// ...
}
Different reactions need different approaches
I realized each reaction needed different behavior. Hearts should feel warm and personal — floating gently upward like in a casual chat. Applause should feel energetic but not distracting from speakers. Confetti could briefly take over the screen for celebrations.
I ended up with three distinct particle behaviors:
// Hearts: gentle, personal
move: {
direction: 'top',
speed: 6,
straight: false, // slight wobble
}
// Applause: quick burst, multiple images
images: [
{ src: '/images/emoji/clap.png' },
{ src: '/images/emoji/clap-light.png' },
// Different skin tones for inclusivity
]
// Confetti: brief screen takeover
number: { value: 350 },
life: { duration: { value: 2 } },
// But only for 2 seconds
The applause reaction uses multiple emoji variations, including different skin tones. This small detail makes the reaction feel more inclusive without adding complexity.
Guest vs authenticated reactions
Authenticated users get the full particle effects when they react. I made guest reactions from other users more subtle — showing engagement without letting someone else’s clicks take over your screen.
Guest reactions use a contained emitter system that shows single particles floating up from the bottom corner:
position: {
x: Math.random() * 10 + 1, // Small random spread
y: 100, // Always from bottom
},
particles: {
size: { value: 16 }, // Smaller than user reactions
move: {
speed: Math.random() * 6 + 3, // Varied speed feels natural
straight: true,
},
}
This creates ambient feedback without overwhelming the interface. You feel the room’s energy without losing focus on the content.
Toggle everything
The most important feature was the simplest: a toggle to disable all reaction animations. Some users wanted to participate but couldn’t handle the visual effects. Others were on connections where any animation hurt performance.
<button @click="toggleGuestReactions()">
{{ showGuestReactions ? 'Disable Reactions' : 'Enable Reactions' }}
</button>
The result
The final system feels immediate without being overwhelming. Click a heart, see particles instantly. Watch other people’s reactions as subtle ambient feedback. Toggle it off if you need to focus or your laptop is struggling.
Most importantly, it never gets in the way of the actual event content. The reactions enhance the experience for people who want them, and disappear completely for those who don’t.
The constraint that mattered most: reactions should never matter more than why people showed up in the first place.