Damage Numbers

데미지 숫자

Numbers that pop up from the hit point and float upward as they fade — crits get a bigger size and a different color.

Also known as: 플로팅 텍스트Combat text데미지 텍스트
···
html
<div class="dnwrap"><div class="dntarget" id="target"></div><div class="dnlayer" id="layer"></div></div>
css
.dnwrap{position:relative;width:100%;height:100%}
.dntarget{position:absolute;left:50%;top:56%;width:clamp(28px,14vmin,52px);height:clamp(28px,14vmin,52px);margin:-26px 0 0 -26px;border-radius:8px;background:var(--surface);border:2px solid var(--line)}
.dnlayer{position:absolute;inset:0;pointer-events:none}
.dn{position:absolute;left:50%;top:50%;font:800 clamp(13px,4.4vmin,20px)/1 monospace;color:var(--fg);
  transform:translate(-50%,-50%) scale(0.4);opacity:0;transition:transform .5s cubic-bezier(.2,1.4,.4,1), opacity .5s ease-out}
.dn.show{transform:translate(-50%,-160%) scale(1);opacity:1}
.dn.fade{opacity:0;transform:translate(-50%,-260%) scale(0.9)}
.dn.crit{font-size:clamp(18px,6.4vmin,30px);color:var(--accent-2)}
js
const layer=document.getElementById('layer');
const target=document.getElementById('target');
function spawn(val, crit){
  const el=document.createElement('div');
  el.className='dn'+(crit?' crit':'');
  el.textContent=(crit?'-':'-')+val;
  const jitter=(Math.random()*40-20);
  el.style.left='calc(50% + '+jitter+'px)';
  layer.appendChild(el);
  requestAnimationFrame(function(){ el.classList.add('show'); });
  setTimeout(function(){ el.classList.add('fade'); }, 500);
  setTimeout(function(){ el.remove(); }, 950);
  target.style.transform='scale(0.88)';
  setTimeout(function(){ target.style.transform='scale(1)'; }, 90);
}
target.style.transition='transform .12s ease-out';
let n=0;
function tick(){
  n++;
  const crit = n % 3 === 0;
  spawn(crit ? Math.floor(Math.random()*60+80) : Math.floor(Math.random()*20+8), crit);
  setTimeout(tick, crit ? 900 : 550);
}
setTimeout(tick, 400);

Damage numbers spawn at the hit point in world space, get projected to screen space, and live briefly as they float upward and fade out. A quick scale punch on spawn — popping slightly larger before settling — reads far livelier than just appearing at full size.

The cheapest way to separate a normal hit from a crit is size and color: scale the crit number 1.4–2x larger, give it the accent color, and add a bit of rotation or wobble so it's unmistakably not an ordinary hit. Numbers spawning at the exact same spot tend to overlap and blur together, so scattering them slightly along the x-axis is common.

Too many numbers at once — an AoE, a fast combo — can bury the screen and hide what actually matters, like health or incoming danger. Capping how many show at a time, or summing hits within a short window into one number, keeps it readable.

When to use

Any combat game with numeric damage. Not applicable to puzzle or adventure genres without a damage stat.