이 가이드에서는 고성능 CSS 애니메이션을 만드는 방법을 설명합니다.
이러한 권장사항의 이론적 배경을 알아보려면 일부 애니메이션이 느린 이유는 무엇인가요?를 참고하세요.
브라우저 호환성
이 가이드에서 권장하는 모든 CSS 속성은 교차 브라우저 지원이 우수합니다.
transform
opacity
will-change
요소 이동
요소를 이동하려면 transform
속성의 translate
또는 rotation
키워드 값을 사용합니다.
예를 들어 항목을 뷰로 슬라이드하려면 translate
를 사용합니다.
.animate {
animation: slide-in 0.7s both;
}
@keyframes slide-in {
0% {
transform: translateY(-1000px);
}
100% {
transform: translateY(0);
}
}
rotate
를 사용하여 요소를 회전합니다. 다음 예에서는 요소를 360도 회전합니다.
.animate {
animation: rotate 0.7s ease-in-out both;
}
@keyframes rotate {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
요소 크기 조절
요소의 크기를 조정하려면 transform
속성의 scale
키워드 값을 사용합니다.
.animate {
animation: scale 1.5s both;
}
@keyframes scale {
50% {
transform: scale(0.5);
}
100% {
transform: scale(1);
}
}
요소의 공개 상태 변경
요소를 표시하거나 숨기려면 opacity
을 사용합니다.
.animate {
animation: opacity 2.5s both;
}
@keyframes opacity {
0% {
opacity: 1;
}
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
레이아웃 또는 페인트를 트리거하는 속성 피하기
애니메이션에 CSS 속성(transform
및 opacity
제외)을 사용하기 전에 속성이 렌더링 파이프라인에 미치는 영향을 확인합니다.
꼭 필요한 경우가 아니라면 레이아웃 또는 페인트를 트리거하는 속성은 사용하지 마세요.
레이어 강제 생성
일부 애니메이션이 느린 이유는 무엇인가요?에서 설명한 대로 새 레이어에 요소를 배치하면 브라우저가 나머지 레이아웃을 다시 그릴 필요 없이 요소를 다시 그릴 수 있습니다.
브라우저는 일반적으로 새 레이어에 배치해야 하는 항목을 올바르게 결정할 수 있지만 will-change
속성을 사용하여 수동으로 레이어를 만들 수 있습니다.
이름에서 알 수 있듯이 이 속성은 브라우저에 이 요소가 어떤 방식으로든 변경될 예정이라고 알립니다.
CSS에서는 모든 선택기에 will-change
를 적용할 수 있습니다.
body > .sidebar {
will-change: transform;
}
그러나 사양에서는 항상 변경될 예정인 요소에 대해서만 이 작업을 실행해야 한다고 제안합니다. 예를 들어 이는 사용자가 슬라이드인/아웃할 수 있는 사이드바의 경우 true일 수 있습니다. 자주 변경되지 않는 요소의 경우 변경이 발생할 가능성이 높을 때 JavaScript를 사용하여 will-change
를 적용하는 것이 좋습니다. 브라우저가 필요한 최적화를 실행할 수 있도록 충분한 시간을 주고 변경이 중지되면 속성을 삭제합니다.
will-change
를 지원하지 않는 브라우저(Internet Explorer 등)에서 레이어 생성을 강제로 적용하려면 transform: translateZ(0)
를 설정하면 됩니다.
느리거나 글리치가 있는 애니메이션 디버그
Chrome DevTools 및 Firefox DevTools에는 애니메이션이 느려지거나 글리치가 발생하는 이유를 파악하는 데 도움이 되는 여러 도구가 있습니다.
애니메이션이 레이아웃을 트리거하는지 확인
transform
이외의 항목을 사용하여 요소를 이동하는 애니메이션은 느릴 수 있습니다. 다음 예에서는 transform
를 사용하는 애니메이션을 top
및 left
를 사용하는 애니메이션과 비교합니다.
.box {
position: absolute;
top: 10px;
left: 10px;
animation: move 3s ease infinite;
}
@keyframes move {
50% {
top: calc(90vh - 160px);
left: calc(90vw - 200px);
}
}
.box {
position: absolute;
top: 10px;
left: 10px;
animation: move 3s ease infinite;
}
@keyframes move {
50% {
transform: translate(calc(90vw - 200px), calc(90vh - 160px));
}
}
다음 두 가지 Glitch 예시에서 이를 테스트하고 DevTools를 사용하여 성능을 살펴볼 수 있습니다.
Chrome DevTools
- 성능 패널을 엽니다.
- 애니메이션이 실행되는 동안 런타임 성능을 기록합니다.
- 요약 탭을 검사합니다.
요약 탭에서 렌더링 값이 0이 아닌 경우 애니메이션으로 인해 브라우저에서 레이아웃이 작동한다는 의미일 수 있습니다.
Firefox DevTools
Firefox DevTools의 Waterfall은 브라우저가 어디에서 시간을 보내는지 이해하는 데 도움이 될 수 있습니다.
- 실적 패널을 엽니다.
- 애니메이션이 진행되는 동안 성능을 녹화합니다.
- 녹화를 중지하고 워터폴 탭을 검사합니다.
스타일 다시 계산 항목이 표시되면 브라우저가 애니메이션을 렌더링하기 위해 렌더링 폭포식 구조의 시작 부분으로 돌아가야 함을 의미합니다.
드롭된 프레임 확인
- Chrome DevTools에서 렌더링 탭을 엽니다.
- FPS 미터 체크박스를 사용 설정합니다.
- 애니메이션이 실행되는 동안 값을 확인하세요.
FPS 측정기 UI 상단의 프레임 라벨에 주목하세요.
그러면 50% 1 (938 m) dropped of 1878
과(와) 같은 값이 표시됩니다. 고성능 애니메이션은 99%
와 같이 비율이 높습니다. 즉, 드롭되는 프레임이 거의 없고 애니메이션이 부드럽게 표시됩니다.
애니메이션이 페인트를 트리거하는지 확인
일부 속성은 브라우저에서 페인트하는 데 다른 속성보다 비용이 더 많이 듭니다. 예를 들어, 그림자처럼 흐리게 만드는 효과 적용은 빨간색 상자를 그리는 것보다 시간이 더 많이 소요됩니다. 이러한 차이점이 CSS에서 항상 명확하게 드러나는 것은 아니지만 브라우저 DevTools를 사용하면 다시 페인트해야 할 영역과 기타 페인팅 관련 성능 문제를 식별하는 데 도움이 될 수 있습니다.
Chrome DevTools
- Chrome DevTools에서 렌더링 탭을 엽니다.
- 페인트 플래시를 선택합니다.
- 화면에서 포인터를 움직입니다.
전체 화면이 깜박이거나 변경되어서는 안 되는 영역이 강조 표시되면 자세히 살펴보세요.
특정 속성이 페인팅 관련 성능 문제를 일으키는지 확인해야 하는 경우 Chrome DevTools의 페인트 프로파일러를 사용하면 됩니다.
Firefox DevTools
- 설정을 열고 페인트 플래시 전환의 도구 상자 버튼을 추가합니다.
- 검사하려는 페이지에서 버튼을 사용 설정하고 마우스를 이동하거나 스크롤하여 강조 표시된 영역을 확인합니다.
결론
가능하면 애니메이션을 opacity
및 transform
로 제한하여 렌더링 경로의 컴포지션 단계에서 애니메이션을 유지합니다. DevTools를 사용하여 애니메이션의 영향을 받는 경로의 단계를 확인합니다.
페인트 프로파일러를 사용하여 페인트 작업이 특히 비용이 많이 드는지 확인합니다. 문제가 있는 경우 다른 CSS 속성으로 동일한 모양과 느낌을 더 나은 성능으로 제공할 수 있는지 확인합니다.
will-change
속성은 성능 문제가 발생한 경우에만 가급적 사용하지 마세요.