Screen Juice: Shake & Flash
Making Impacts Feel Powerful
Direct answer: Screen shake, flash, and hit-stop are extra feedback. They should never change score, collision, or lives. Use a decaying offset for shake, a short overlay for flash, and a few frozen update frames for hit-stop.
"Juice" is the non-essential visual feedback that makes a game feel alive. The two most effective (and easiest) techniques are Screen Shake and Screen Flash.
What you need first
A game loop and a container you can translate. Particles are optional and belong on the next animation page.
After this lesson
You can add a hit punch to Breakout or Galaxy Guardian without moving the ball’s real position.
1. Screen Shake
Screen shake simulates a camera being rattled by an explosion or impact. The key is to apply a random offset to your game container that decays over time.
let shakeIntensity = 0;
let shakeDecay = 0.9;
function triggerShake(amount) {
shakeIntensity = amount;
}
function updateShake() {
if (shakeIntensity > 0) {
// Random offset based on current intensity
const dx = (Math.random() - 0.5) * shakeIntensity * 2;
const dy = (Math.random() - 0.5) * shakeIntensity * 2;
// Apply to game container
gameContainer.style.transform = `translate(${dx}px, ${dy}px)`;
// Decay intensity
shakeIntensity *= shakeDecay;
if (shakeIntensity < 0.5) {
shakeIntensity = 0;
gameContainer.style.transform = 'none';
}
}
}
2. Screen Flash
A screen flash simulates a bright explosion blinding the camera for a split second. It's usually a white overlay that fades opacity from 1 to 0.
.flash-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: white;
opacity: 0;
pointer-events: none;
transition: opacity 0.1s ease-out; /* Fast fade out */
}
.flash-active {
opacity: 0.8;
transition: none; /* Instant fade in */
}
function triggerFlash() {
const overlay = document.getElementById('flashOverlay');
// 1. Instant on
overlay.style.transition = 'none';
overlay.style.opacity = '0.8';
// 2. Force reflow (browser paint)
void overlay.offsetWidth;
// 3. Fade out
overlay.style.transition = 'opacity 0.3s ease-out';
overlay.style.opacity = '0';
}
3. Hit-stop, used sparingly
Hit-stop freezes updates for 2–6 frames when something important connects. The player reads the contact. Do not freeze the whole game for a coin pickup. A brick break or a boss hit can take it; a Snake apple should not.
let hitStop = 0;
function onBrickHit() {
hitStop = 4; // frames
}
function update() {
if (hitStop > 0) {
hitStop -= 1;
return; // draw the last pose, skip movement
}
// normal update
}
When to use it
Use shake and flash on discrete events: a brick break, an explosion, taking damage. Do not leave shake running while the player walks. Motion sickness starts when the camera never settles.
Common mistake: translating the game world and then using the shaken coordinates for collision. Shake the camera or the wrapper, not the ball’s x.
How InstantGames uses this
Breakout already spends juice on paddle and brick contact with particles. A short shake on a full-row clear would fit this lesson; shaking every bounce would not. Galaxy Guardian can flash on a player hit because the event is rare and costly. Snake uses a near-miss warning instead of camera shake — the board is a grid, and sliding it would hide the next cell.
The demo button on this page is deliberately louder than a shipped game. Copy the decay, then cut the intensity.
Compatibility: CSS transforms and Canvas both work in current browsers. Prefer transforming a wrapper around the canvas so you do not rewrite every draw call.
Source and update: Interaction ideas follow common game-feel practice and the MDN Web Docs animation notes. Updated 2026-08-13. This page does not claim a measured juice budget.