슬로우 인 슬로우 아웃

Slow in and slow out

동작의 시작과 끝 부근에는 그림을 촘촘히, 중간에는 성기게 배치해 가속·감속을 표현하는 원칙. CSS ease-in-out의 직계 조상입니다.

다른 이름: Ease in / ease out (traditional animation)
···
html
<div class="rows">
  <div class="row">
    <span class="tag">Linear</span>
    <div class="track" id="trackLin"><i class="ball"></i></div>
  </div>
  <div class="row">
    <span class="tag">Slow in / slow out</span>
    <div class="track" id="trackEase"><i class="ball ease"></i></div>
  </div>
</div>
css
.rows{position:absolute;inset:12% 8%;display:flex;flex-direction:column;justify-content:space-around}
.row{display:flex;flex-direction:column;gap:8px}
.tag{font:700 10px/1 ui-monospace,monospace;color:var(--muted)}
.track{position:relative;height:20px}
.track::before{content:'';position:absolute;top:50%;left:0;right:0;height:2px;margin-top:-1px;background:var(--line)}
.tick{position:absolute;top:50%;width:2px;height:10px;margin-top:-5px;background:var(--muted);opacity:.55}
.ball{position:absolute;top:50%;left:0;width:20px;height:20px;margin-top:-10px;border-radius:50%;background:var(--accent);
  box-shadow:0 2px 6px rgba(0,0,0,.2);animation:moveTrack 2.2s linear infinite}
.ball.ease{background:var(--accent-3);animation:moveTrack 2.2s ease-in-out infinite}
@keyframes moveTrack{from{left:0}to{left:calc(100% - 20px)}}
js
function easeInOutQuad(t) { return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2; }
const linTrack = document.getElementById('trackLin');
const easeTrack = document.getElementById('trackEase');
for (let i = 0; i <= 8; i++) {
  const fLin = i / 8;
  const fEase = easeInOutQuad(i / 8);
  const t1 = document.createElement('i');
  t1.className = 'tick';
  t1.style.left = 'calc((100% - 20px) * ' + fLin + ' + 9px)';
  linTrack.appendChild(t1);
  const t2 = document.createElement('i');
  t2.className = 'tick';
  t2.style.left = 'calc((100% - 20px) * ' + fEase + ' + 9px)';
  easeTrack.appendChild(t2);
}

등속으로 움직이는 물체는 실제 세계에 거의 없습니다. 뭔가를 집어 드는 손도, 문을 여는 팔도 천천히 시작해 빨라졌다가 다시 천천히 멈춥니다. 애니메이터는 이 감각을 "그림(프레임)을 얼마나 촘촘하게 배치하는가"로 표현했습니다 — 느린 구간은 그림 사이 거리(스페이싱)가 좁고, 빠른 구간은 넓습니다.

같은 시간 간격으로 찍은 점들을 늘어놓아 보면 이 원리가 바로 보입니다: 등속(linear)은 점들이 일정한 간격으로, 슬로우 인 슬로우 아웃은 양 끝에서 점들이 뭉치고 중간에서 벌어집니다. CSS에서는 이게 그대로 이징 커브(ease, ease-in-out, cubic-bezier)가 됐습니다.

데모의 두 트랙은 같은 거리를 같은 시간에 이동하지만, 위는 linear라 점들이 고르게 퍼져 있고 기계적으로 느껴집니다. 아래는 ease-in-out이라 점들이 양 끝에 뭉쳐 있어 시작과 끝이 부드럽습니다.

언제 쓰나

사용자가 만든 동작(클릭, 드래그 종료)에는 슬로우 인 슬로우 아웃이 자연스럽습니다. 로딩 스피너처럼 끝없이 반복되는 동작엔 linear가 오히려 어울립니다.