라이브 커머스, 쇼핑몰, 인터랙티브 웹 UI에서 종종 볼 수 있는
웹에서 상품을 장바구니에 추가할 때, "슝~ 날아가는 애니메이션"을 본 적 있으신가요?
이번 글에서는 offset-path를 중심으로
1. CSS만으로 만든 기본 예제
2. JavaScript로 두 요소 간 경로를 동적으로 계산한 확장 예제를 각각 소개합니다.
🎯 지원 브라우저:
✅ Chrome, Edge, Opera, Brave
⚠️ Safari는 offset-path 미지원
❌ IE, Firefox 미지원
offset-path와 offset-distance를 이용해 자연스러운 궤적 구현📌 특징:
offset-path에 고정 경로(path)를 미리 지정.active 클래스를 붙여 애니메이션 실행🧱 HTML 구조
<div class="container">
<div class="cart-icon" id="cartIcon"></div>
<button id="start">애니메이션 실행</button>
</div>
🎨 CSS (핵심 스타일)
.container {
position: relative;
height: 500px;
background: #f9f9f9;
}
.cart-icon {
width: 44px;
height: 44px;
background: tomato;
border-radius: 50%;
position: absolute;
offset-rotate: 0deg;
display: none;
}
.cart-icon.active {
display: block;
offset-path: path("M 100 400 C 100 100, 500 100, 500 400");
animation: moveCart 1.2s ease-in-out forwards;
}
🌀 애니메이션 키프레임
@keyframes moveCart {
from {
offset-distance: 0%;
}
to {
offset-distance: 100%;
}
}
🧠 JavaScript
document.getElementById("start").addEventListener("click", () => {
const cart = document.getElementById("cartIcon");
cart.classList.remove("active");
void cart.offsetWidth; // 리플로우
cart.classList.add("active");
});
📌 특징:
getBoundingClientRect()로 두 요소의 좌표 계산offset-path에 동적 경로 삽입🧱 HTML 구조
<div class="container">
<div class="start-point" id="product">상품</div>
<div class="end-point" id="cart">장바구니</div>
<div class="cart-icon" id="badge"></div>
<button id="move">장바구니 담기</button>
</div>
🎨 CSS (핵심 스타일)
.container {
position: relative;
height: 500px;
background: #f0f0f0;
}
.start-point,
.end-point {
position: absolute;
width: 60px;
height: 60px;
background: #ccc;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.start-point {
top: 350px;
left: 100px;
}
.end-point {
top: 100px;
left: 500px;
}
.cart-icon {
position: fixed;
width: 44px;
height: 44px;
background: tomato;
border-radius: 50%;
display: none;
offset-rotate: 0deg;
z-index: 9999;
}
.cart-icon.active {
display: block;
animation: moveCart 1.2s ease-in-out forwards;
}
🌀 애니메이션 키프레임
@keyframes moveCart {
from {
offset-distance: 0%;
}
to {
offset-distance: 100%;
}
}
🧠 JavaScript
const product = document.getElementById("product");
const cart = document.getElementById("cart");
const badge = document.getElementById("badge");
const button = document.getElementById("move");
button.addEventListener("click", () => {
const start = product.getBoundingClientRect();
const end = cart.getBoundingClientRect();
const startX = start.left + start.width / 2;
const startY = start.top + start.height / 2;
const endX = end.left + end.width / 2;
const endY = end.top + end.height / 2;
const peak = 300;
const path = `M ${startX} ${startY} C ${startX} ${startY - peak}, ${endX} ${endY - peak}, ${endX} ${endY}`;
badge.classList.remove("active");
badge.getAnimations().forEach(a => a.cancel());
void badge.offsetWidth;
badge.style.setProperty("offset-path", `path("${path}")`);
badge.classList.add("active");
badge.addEventListener("animationend", () => {
badge.classList.remove("active");
badge.style.removeProperty("offset-path");
}, { once: true });
});
| 항목 | CSS 버전 | JavaScript 확장 버전 |
|---|---|---|
| 동작 방식 | 고정 경로 사용 | 요소 좌표 기반 경로 생성 |
| 유연성 | 제한적 (위치 고정 필요) | 어떤 위치든 대응 가능 |
| 유지보수 | 간단함 | 다소 복잡하지만 강력함 |
| 실전 적용 | 정적인 UI | 동적 UI, 실서비스에 적합 |
| 속성 | 설명 | 예시 |
|---|---|---|
offset-path | 요소가 이동할 경로 (SVG path 가능) | offset-path: path("M 0 0 C ...") |
offset-distance | 경로를 따라 이동하는 거리 비율 | 0% ~ 100% |
offset-rotate | 회전 방향 고정 | 0deg 또는 auto |
animation | 애니메이션 속도 및 반복 설정 | animation: moveCart 1.2s ease |
offset-path는 CSS에서 지정한 SVG path를 따라 이동시킬 수 있는 강력한 기능!display: none으로 숨기고 .active로 트리거하는 방식이 일반적.M x y C x1 y1, x2 y2, x y 형태의 베지어 곡선 경로는 SVG Path Editor를 구글링해서 만들기offset-rotate: auto로 설정하면 이동 방향에 따라 회전도 자동으로 됩니다.offset-path는 현대 CSS에서 매우 강력한 도구입니다.
CSS만으로도 기본 애니메이션은 충분히 만들 수 있고,
JavaScript를 함께 사용하면 더 강력한 동적 인터랙션을 구현할 수 있습니다.