Juice

주스 (juice)

Layering extra, non-functional feedback — squash, shake, particles, color pops — onto an action that works identically without it, purely to make it feel better.

Also known as: 게임 주스Juiciness입력 피드백 과잉
···
html
<div class="jrow">
<div class="jcol"><div class="jlabel">PLAIN</div><button class="jbtn plain" id="pbtn">HIT</button></div>
<div class="jcol"><div class="jlabel">JUICED</div><div class="jstage"><div class="jparticles" id="jp"></div><button class="jbtn juicy" id="jbtn">HIT</button></div></div>
</div>
css
.jrow{display:flex;gap:clamp(10px,5vmin,26px);align-items:center;justify-content:center;width:100%}
.jcol{display:flex;flex-direction:column;align-items:center;gap:6px}
.jlabel{font:700 clamp(8px,2.4vmin,10px) monospace;color:var(--muted);letter-spacing:.1em}
.jbtn{border:none;border-radius:10px;padding:clamp(10px,4.4vmin,16px) clamp(14px,5.6vmin,22px);font:800 clamp(11px,3.4vmin,14px) inherit;cursor:default;color:#fff}
.plain{background:var(--muted)}
.juicy{background:var(--accent-2);position:relative;z-index:2;box-shadow:0 8px 18px color-mix(in srgb,var(--accent-2) 35%,transparent)}
.jstage{position:relative}
.jparticles{position:absolute;inset:-60%;pointer-events:none}
.jp{position:absolute;width:6px;height:6px;border-radius:50%;background:var(--accent-3);left:50%;top:50%;opacity:0}
js
const pbtn=document.getElementById('pbtn');
const jbtn=document.getElementById('jbtn');
const jp=document.getElementById('jp');
pbtn.style.transition='transform .05s';
jbtn.style.transition='transform .09s cubic-bezier(.3,1.6,.4,1), background .15s';
function plainHit(){
  pbtn.style.transform='scale(0.96)';
  setTimeout(function(){ pbtn.style.transform='scale(1)'; }, 90);
}
function burst(){
  for(let i=0;i<8;i++){
    const p=document.createElement('div');
    p.className='jp';
    jp.appendChild(p);
    const ang=(i/8)*Math.PI*2, dist=26+Math.random()*14;
    p.style.transition='transform .45s ease-out, opacity .45s ease-out';
    requestAnimationFrame(function(){
      p.style.opacity='1';
      p.style.transform='translate('+(Math.cos(ang)*dist)+'px,'+(Math.sin(ang)*dist)+'px)';
      setTimeout(function(){ p.style.opacity='0'; }, 200);
    });
    setTimeout(function(){ p.remove(); }, 500);
  }
}
function juicyHit(){
  jbtn.style.transform='scale(0.8) rotate(-3deg)';
  jbtn.style.background='var(--accent-3)';
  burst();
  setTimeout(function(){
    jbtn.style.transform='scale(1.12) rotate(2deg)';
    setTimeout(function(){
      jbtn.style.transform='scale(1)';
      jbtn.style.background='var(--accent-2)';
    }, 110);
  }, 70);
}
function loop(){ plainHit(); juicyHit(); setTimeout(loop, 1300); }
setTimeout(loop, 500);

"Juice" is game-dev shorthand for taking an action that works fine with a single flat response and returning it through several exaggerated sensory channels instead — visual, sometimes audio. Press a button and, beyond just registering the press, it squashes slightly, flashes color, throws off a few particles, nudges the screen. None of it changes what the game does; together it's what makes an interaction feel good in the hand.

The trick is layering intensity, not picking one technique. A single scale punch (squash-and-stretch) alone already beats nothing, but stack a color flash, particles, sound, and a screen nudge on the exact same beat and the payoff compounds. Juice isn't really one technique's name — it's the habit of stacking several small ones at once.

Overdo it and it backfires: if every click shakes the screen and pops particles, the moments that actually matter — a crit, a death — get lost in the same noise as everything else. Save the heavy juice for rare, meaningful actions (a win, a level up, a crit) and keep frequent, minor ones (walking, a plain UI click) light.

When to use

Any interaction that should respond immediately to input — but scale the intensity inversely to how often it happens.