outline-offset effects

outline-offset 응용

Unlike border, outline sits outside the box model and never pushes layout. outline-offset lets you float that line inward or outward from the border edge at will.

Also known as: Focus ring offsetNon-layout border
···
html
<div class="wrap"><div class="box" id="box"></div><div class="label" id="l">outline-offset: 8px</div></div>
css
.wrap{position:relative;display:grid;place-items:center;gap:20px}
.box{width:24vmin;max-width:100px;aspect-ratio:1;border-radius:12px;background:linear-gradient(135deg,#5b5bf7,#18c29c);
  outline:3px solid #f25c8a;outline-offset:8px}
.label{font:600 12px/1.4 monospace;color:var(--muted)}
js
const box = document.getElementById('box');
const l = document.getElementById('l');
let t = 0;
function loop(){
  t += 0.02;
  const off = Math.round(8 + Math.sin(t) * 18);
  box.style.outlineOffset = off + 'px';
  l.textContent = 'outline-offset: ' + off + 'px';
  requestAnimationFrame(loop);
}
loop();

Grow a border and the element gets bigger, or neighbours get pushed — border is part of the box model. outline isn't, so no matter how thick it is, surrounding layout never moves. outline-offset sets how far that line floats from the border edge: positive pushes it outward, negative pulls it inward.

That's exactly why it's the standard choice for focus rings — swapping border on every keyboard focus change causes a tiny reflow that nudges neighbours, while outline never does.

Modern browsers round the outline to match border-radius, but older engines used to draw it as a plain rectangle regardless — worth checking if you depend heavily on the rounded case. Also, if the offset pushes the outline past an ancestor's bounds and that ancestor has overflow: hidden, the outline gets clipped there, unlike a box-shadow's blur spread.

When to use

For focus rings, or any "selected" indicator that must not shift layout. If an ancestor has overflow: hidden, check the offset doesn't get clipped.