블로그 목록
frontend

CSS @property로 그라데이션·각도 애니메이션 만들기 — 변수도 타입이 있으면 트랜지션이 걸린다

CSS 변수로 그라데이션 각도를 애니메이션 걸어본 적 있다면 알 것이다. 안 된다. --angle: 0deg에서 90deg로 트랜지션을 걸어도 각도가 뚝 뛴다. 회전 버튼에 호버 그라데이션을 넣고 싶어서 --angle을 트랜지션 대상에 넣어봐도 무반응이다.

이유는 간단하다. 일반 --변수는 브라우저에게 그냥 문자열이다. 0deg90deg 사이에 어떤 중간값이 있는지 브라우저가 모른다. "0deg"라는 글자에서 "90deg"라는 글자로 넘어갈 뿐, 45도라는 개념이 없다.

@property로 타입 알려주기

@property는 이 변수가 사실은 각도라고, 숫자라고 브라우저에게 알려주는 선언이다. 타입(syntax)만 붙여주면 그때부터 중간값을 계산할 수 있게 된다.

@property --angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

.card {
  background: linear-gradient(var(--angle), #6366f1, #ec4899);
  transition: --angle 0.4s ease;
}

.card:hover {
  --angle: 180deg;
}

이제 호버하면 그라데이션이 뚝 뛰지 않고 부드럽게 돌아간다. 세 필드가 다 필수다. syntax는 타입, inherits는 상속 여부, initial-value는 값이 없을 때의 기본값이다.

진짜 쓸모는 conic-gradient 진행률

가장 잘 먹히는 곳은 원형 진행 표시기다. conic-gradient의 각도를 퍼센트 변수로 돌리면 라이브러리 없이 도넛 프로그레스가 나온다.

@property --progress {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 0%;
}

.ring {
  background: conic-gradient(#22c55e var(--progress), #e5e7eb 0);
  border-radius: 50%;
  transition: --progress 0.6s ease;
}

--progress를 JS에서 65%로 바꾸면 게이지가 스르륵 차오른다. SVG stroke-dashoffset 계산 같은 것 없이 CSS 한 덩어리로 끝난다.

syntax에 넣을 수 있는 타입들

<angle>, <percentage>, <number>, <length>, <color> 등이 있다. <color>를 쓰면 CSS 변수 기반 색 전환도 트랜지션이 걸린다. 값을 제한하고 싶으면 syntax: '<length> | auto'처럼 조합하거나, 특정 키워드만 허용하는 것도 된다.

정리

@property는 Chrome, Safari, Firefox 모두에서 Baseline으로 자리 잡았다. 미지원 환경에서도 변수 자체는 정상 동작하고 애니메이션만 즉시 전환으로 떨어지니 점진적 향상으로 붙이기 좋다. "CSS 변수는 애니메이션이 안 된다"는 오래된 상식은 이제 반쯤 틀린 말이 됐다. 타입만 알려주면 걸린다.