그림을 그려보세요. 새 프로젝트에 참여하고 코드베이스를 살펴보고 처음 몇 시간 내에 실망스러울 정도로 친숙한 것을 발견하게 됩니다. 스타일시트 전체에 흩어져 있는 동일한 기본 애니메이션에 대한 여러 @keyframes 정의를 찾을 수 있습니다. 세 가지 다른 페이드인 효과, 두세 가지 슬라이드 변형, 소수의 확대/축소 애니메이션, 최소 두 가지 다른 회전 애니메이션 등이 있습니다. 왜 안 되겠습니까? @keyframes 펄스 { {에서 규모: 1; } ~에게 { 규모: 1.1; } }
@keyframes 더 큰 펄스 { 0%, 20%, 100% { 규모: 1; } 10%, 40% { 규모: 1.2; } }
이 시나리오가 친숙하게 들린다면 여러분은 혼자가 아닙니다. 다양한 프로젝트를 경험한 결과, 제가 제공할 수 있는 가장 일관되고 빠른 승리 중 하나는 키프레임을 통합하고 표준화하는 것입니다. 매우 신뢰할 수 있는 패턴이 되었기 때문에 이제 새 코드베이스에 대한 첫 번째 작업 중 하나로 이 정리를 기대하고 있습니다. 혼돈의 논리 이 중복성은 생각해 보면 완벽하게 이해됩니다. 우리 모두는 일상 작업에서 페이드, 슬라이드, 확대/축소, 회전 및 기타 일반적인 효과와 같은 동일한 기본 애니메이션을 사용합니다. 이러한 애니메이션은 매우 간단하며 @keyframes 정의를 빠르게 작성하여 작업을 완료하는 것이 쉽습니다. 중앙 집중식 애니메이션 시스템이 없으면 개발자는 유사한 애니메이션이 코드베이스의 다른 곳에 이미 존재한다는 사실을 인식하지 못한 채 자연스럽게 이러한 키프레임을 처음부터 작성합니다. 이는 팀이 애플리케이션의 여러 부분에서 병렬로 작업하는 경우가 많기 때문에 구성 요소 기반 아키텍처(요즘 우리 대부분이 수행하는 작업)에서 작업할 때 특히 일반적입니다. 결과는? 애니메이션 혼란. 작은 문제 키프레임 복제와 관련된 가장 명백한 문제는 개발 시간 낭비와 불필요한 코드 팽창입니다. 여러 키프레임 정의는 요구 사항이 변경될 때 업데이트할 여러 위치를 의미합니다. 페이드 애니메이션의 타이밍을 조정해야 합니까? 코드베이스 전체에서 모든 인스턴스를 찾아야 합니다. 완화 기능을 표준화하고 싶으신가요? 모든 변형을 찾는 행운을 빕니다. 이렇게 유지 관리 지점이 늘어나면 단순한 애니메이션 업데이트도 시간이 많이 걸리는 작업이 됩니다. 더 큰 문제 이 키프레임 복제는 표면 아래에 숨어 있는 훨씬 더 교활한 문제인 전역 범위 트랩을 만듭니다. 구성 요소 기반 아키텍처로 작업하는 경우에도 CSS 키프레임은 항상 전역 범위에서 정의됩니다. 즉, 모든 키프레임이 모든 구성 요소에 적용됩니다. 언제나. 예, 애니메이션이 구성요소에 정의한 키프레임을 반드시 사용할 필요는 없습니다. 전역 범위에 로드된 정확히 동일한 이름과 일치하는 마지막 키프레임을 사용합니다. 모든 키프레임이 동일하다면 이는 사소한 문제처럼 보일 수 있습니다. 그러나 특정 사용 사례에 맞게 애니메이션을 사용자 정의하려는 순간 문제가 발생하거나 더 나쁘게는 문제를 일으키는 사람이 될 것입니다. 애니메이션 뒤에 로드된 다른 구성 요소가 키프레임을 덮어쓰거나 구성 요소가 마지막에 로드되어 실수로 해당 키프레임 이름을 사용하는 다른 모든 구성 요소의 애니메이션 동작을 변경하기 때문에 애니메이션이 작동하지 않을 수 있으며 이를 깨닫지 못할 수도 있습니다. 다음은 문제를 보여주는 간단한 예입니다. .컴포넌트-1 { /* 컴포넌트 스타일 */ 애니메이션: 펄스 1초 이지인아웃 무한 대체; }
/* 이 @keyframes 정의는 작동하지 않습니다 */ @keyframes 펄스 { {에서 규모: 1; } ~에게 { 규모: 1.1; } }
/* 나중에 코드에서... */
.comComponent-2 { /* 컴포넌트 스타일 */ 애니메이션: 펄스 1초 이지인아웃 무한; }
/* 이 키프레임은 두 구성요소 모두에 적용됩니다 */ @keyframes 펄스 { 0%, 20%, 100% { 규모: 1; } 10%, 40% { 규모: 1.2; } }
두 구성 요소 모두 동일한 애니메이션 이름을 사용하지만 두 번째 @keyframes 정의가 첫 번째 정의를 덮어씁니다. 이제 어떤 구성 요소가 어떤 키프레임을 정의했는지에 관계없이 구성 요소 1과 구성 요소 2 모두 두 번째 키프레임을 사용합니다. Amit Sheen이 작성한 펜 키프레임 토큰 - 데모 1(포크됨)을 참조하세요. 최악의 부분은요? 이는 종종 로컬 개발에서는 완벽하게 작동하지만 빌드 프로세스가 스타일시트의 로드 순서를 변경하면 프로덕션에서는 이상하게 작동하지 않습니다. 로드되는 구성 요소와 순서에 따라 다르게 동작하는 애니메이션이 생성됩니다. 해결책: 통합 키프레임 이러한 혼란에 대한 답은 놀라울 정도로 간단합니다. 사전 정의된 동적 키프레임을 공유 스타일시트에 저장하는 것입니다. 모든 구성 요소가 자체 애니메이션을 정의하도록 하는 대신 잘 문서화되어 있고 쉽게 사용할 수 있는 중앙 집중식 키프레임을 만듭니다.프로젝트의 특정 요구 사항에 맞게 사용하고 유지 관리할 수 있습니다. 키프레임 토큰이라고 생각하세요. 색상과 간격에 토큰을 사용하고 많은 사람들이 이미 지속 시간 및 여유 기능과 같은 애니메이션 속성에 토큰을 사용하는 것처럼 키프레임에도 토큰을 사용하는 것은 어떨까요? 이 접근 방식은 현재 사용 중인 모든 디자인 토큰 워크플로와 자연스럽게 통합되는 동시에 작은 문제(코드 중복)와 더 큰 문제(전역 범위 충돌)를 한 번에 해결할 수 있습니다. 아이디어는 간단합니다. 모든 공통 애니메이션에 대한 단일 진실 소스를 생성하는 것입니다. 이 공유 스타일시트에는 프로젝트에서 실제로 사용하는 애니메이션 패턴을 포함하는 세심하게 제작된 키프레임이 포함되어 있습니다. 더 이상 코드베이스 어딘가에 페이드 애니메이션이 이미 존재하는지 추측할 필요가 없습니다. 더 이상 실수로 다른 구성요소의 애니메이션을 덮어쓰는 일이 없습니다. 하지만 여기에 핵심이 있습니다. 이는 단순한 정적 복사-붙여넣기 애니메이션이 아닙니다. CSS 사용자 정의 속성을 통해 동적으로 사용자 정의할 수 있도록 설계되어 일관성을 유지하면서 한 곳에서 약간 더 큰 "펄스" 애니메이션이 필요한 경우와 같이 특정 사용 사례에 애니메이션을 적용할 수 있는 유연성을 가질 수 있습니다. 첫 번째 키프레임 토큰 구축 우리가 다루어야 할 가장 쉬운 작업 중 하나는 "페이드인" 애니메이션입니다. 최근 프로젝트 중 하나에서 12개 이상의 개별 페이드인 정의를 발견했는데, 모두 불투명도를 0에서 1까지 애니메이션화했을 뿐입니다. 이제 새 스타일시트를 만들고 kf-tokens.css라고 부르고 프로젝트로 가져온 다음 적절한 주석이 포함된 키프레임을 배치해 보겠습니다. /* 키프레임-토큰.css */
/* * 페이드 인(Fade In) - 페이드 입구 애니메이션 * 사용법: 애니메이션: kf-fade-in 0.3s easy-out; */ @keyframes kf-페이드인 { {에서 불투명도: 0; } ~에게 { 불투명도: 1; } }
이 단일 @keyframes 선언은 코드베이스 전체에 흩어져 있는 모든 페이드인 애니메이션을 대체합니다. 깨끗하고 단순하며 전 세계적으로 적용 가능합니다. 이제 이 토큰이 정의되었으므로 프로젝트 전체의 모든 구성 요소에서 사용할 수 있습니다. .모달 { 애니메이션: kf-fade-in 0.3초 완화; }
.툴팁 { 애니메이션: kf-fade-in 0.2s easy-in-out; }
.알림 { 애니메이션: kf-fade-in 0.5초 완화; }
Amit Sheen이 작성한 펜 키프레임 토큰 - 데모 2(포크됨)를 참조하세요. 참고: 모든 @keyframes 이름에는 kf- 접두사를 사용하고 있습니다. 이 접두사는 프로젝트의 기존 애니메이션과 이름이 충돌하는 것을 방지하고 이러한 키프레임이 키프레임 토큰 파일에서 나온 것임을 즉시 명확하게 하는 네임스페이스 역할을 합니다. 역동적인 슬라이드 만들기 kf-fade-in 키프레임은 간단하고 엉망이 될 여지가 거의 없기 때문에 훌륭하게 작동합니다. 그러나 다른 애니메이션에서는 훨씬 더 역동적이어야 하며 여기서는 CSS 사용자 정의 속성의 엄청난 힘을 활용할 수 있습니다. 여기가 분산된 정적 애니메이션에 비해 키프레임 토큰이 실제로 빛나는 부분입니다. "슬라이드인" 애니메이션이라는 일반적인 시나리오를 살펴보겠습니다. 그런데 어디서부터 미끄러지나요? 오른쪽에서 100px? 왼쪽에서 50%? 화면 상단에서 들어가야 하나요? 아니면 바닥에서 떠오를 수도 있나요? 가능성은 매우 많지만 각 방향과 각 변형에 대해 별도의 키프레임을 생성하는 대신 모든 시나리오에 적응하는 하나의 유연한 토큰을 구축할 수 있습니다. /* * 슬라이드 인 - 방향성 슬라이드 애니메이션 * 방향을 제어하려면 --kf-slide-from을 사용하세요. * 기본값: 왼쪽에서 슬라이드됩니다(-100%). * 사용법: * 애니메이션: kf-slide-in 0.3초 이지아웃; * --kf-slide-from: -100px 0; // 왼쪽에서 슬라이드 * --kf-slide-from: 100px 0; // 오른쪽에서 슬라이드 * --kf-slide-from: 0 -50px; // 위에서부터 슬라이드 */
@keyframes kf-슬라이드인 { {에서 번역: var(--kf-slide-from, -100% 0); } ~에게 { 번역: 0 0; } }
이제 --kf-slide-from 사용자 정의 속성을 변경하기만 하면 모든 슬라이드 방향에 대해 이 단일 @keyframes 토큰을 사용할 수 있습니다. .사이드바 { 애니메이션: kf-slide-in 0.3초 완화; /* 기본값 사용: 왼쪽부터 슬라이드 */ }
.알림 { 애니메이션: kf-slide-in 0.4s easy-out; --kf-슬라이드-에서: 0 -50px; /* 위에서부터 슬라이드 */ }
.모달 { 애니메이션: kf-페이드인 0.5초, kf-슬라이드인 0.5초 입방 베지어(0.34, 1.56, 0.64, 1); --kf-슬라이드-에서: 50px 50px; /* 오른쪽 아래에서 슬라이드 */ }
이 접근 방식은 일관성을 유지하면서 놀라운 유연성을 제공합니다. 하나의 키프레임 선언, 무한한 가능성. Amit Sheen이 작성한 펜 키프레임 토큰 - 데모 3(포크됨)을 참조하세요. 그리고 애니메이션을 더욱 유연하게 만들어 "슬라이드 아웃" 효과도 허용하려면 다음을 수행할 수 있습니다.다음 섹션에서 볼 수 있는 것과 유사하게 --kf-slide-to 사용자 정의 속성을 추가하기만 하면 됩니다. 양방향 확대/축소 키프레임 프로젝트 전반에 걸쳐 복제되는 또 다른 일반적인 애니메이션은 "확대/축소" 효과입니다. 토스트 메시지의 미묘한 확대, 모달의 극적인 확대, 제목의 완만한 축소 효과 등 확대/축소 애니메이션은 어디에나 있습니다. 각 배율 값에 대해 별도의 키프레임을 만드는 대신 하나의 유연한 kf-zoom 키프레임 세트를 만들어 보겠습니다.
/* * 줌 - 스케일 애니메이션 * 스케일 값을 제어하려면 --kf-zoom-from 및 --kf-zoom-to를 사용하십시오. * 기본값: 80%에서 100%(0.8~1)로 확대됩니다. * 사용법: * 애니메이션: kf-zoom 0.2초 완화; * --kf-zoom-from: 0.5; --kf-zoom-to: 1; // 50%에서 100%로 확대 * --kf-zoom-from: 1; --kf-확대: 0; // 100%에서 0%로 확대/축소 * --kf-zoom-from: 1; --kf-zoom-to: 1.1; // 100%에서 110%로 확대 */
@keyframes kf-zoom { {에서 규모: var(--kf-zoom-from, 0.8); } ~에게 { 규모: var(--kf-zoom-to, 1); } }
하나의 정의를 통해 필요한 확대/축소 변형을 얻을 수 있습니다. .토스트 { 애니메이션: kf-슬라이드인 0.2초, kf-zoom 0.4초 완화; --kf-슬라이드에서: 0 100%; /* 위에서부터 슬라이드 */ /* 기본 확대/축소 사용: 80%에서 100%까지 확장 */ }
.모달 { 애니메이션: kf-zoom 0.3s 큐빅-베지어(0.34, 1.56, 0.64, 1); --kf-zoom-from: 0; /* 0%에서 100%까지 극적인 확대/축소 */ }
.제목 { 애니메이션: kf-페이드인 2s, kf-zoom 2s이지 인; --kf-zoom-from: 1.2; --kf-zoom-to: 0.8; /* 완만한 규모 축소 */ }
기본값 0.8(80%)은 토스트 메시지 및 카드와 같은 대부분의 UI 요소에 완벽하게 작동하는 동시에 특별한 경우에 맞게 사용자 정의하기 쉽습니다. Amit Sheen의 펜 키프레임 토큰 - 데모 4 [포크]를 참조하세요. 최근 예제에서 흥미로운 점을 발견했을 수 있습니다. 즉, 애니메이션을 결합해 왔습니다. @keyframes 토큰 작업의 주요 이점 중 하나는 서로 원활하게 통합되도록 설계되었다는 것입니다. 이 부드러운 구성은 우연이 아닌 의도적인 것입니다. 애니메이션 구성이 문제가 될 수 있는 부분을 포함하여 나중에 더 자세히 논의하겠지만 대부분의 조합은 간단하고 구현하기 쉽습니다. 참고: 이 글을 쓰는 동안, 그리고 아마도 글을 쓰기 때문에 나는 입장 애니메이션에 대한 전체 아이디어를 다시 생각하게 되었습니다. CSS의 최근 발전에도 불구하고 여전히 CSS가 필요합니까? 운 좋게도 Adam Argyle은 동일한 질문을 탐구하고 자신의 블로그에 훌륭하게 표현했습니다. 이는 여기에 작성된 내용과 모순되지 않지만 특히 프로젝트가 입구 애니메이션에 크게 의존하는 경우 고려할 가치가 있는 접근 방식을 제시합니다. 연속 애니메이션 '페이드', '슬라이드', '줌'과 같은 시작 애니메이션은 한 번 발생했다가 멈추는 반면, 연속 애니메이션은 주의를 끌거나 진행 중인 활동을 나타내기 위해 무한정 반복됩니다. 내가 접하는 가장 일반적인 두 가지 연속 애니메이션은 "스핀"(표시기 로딩용)과 "펄스"(중요한 요소 강조용)입니다. 이러한 애니메이션은 키프레임 토큰을 생성할 때 독특한 과제를 제시합니다. 일반적으로 한 상태에서 다른 상태로 이동하는 입구 애니메이션과 달리 연속 애니메이션은 동작 패턴을 고도로 맞춤화할 수 있어야 합니다. 스핀 닥터 모든 프로젝트는 여러 스핀 애니메이션을 사용하는 것 같습니다. 일부는 시계 방향으로 회전하고 다른 일부는 시계 반대 방향으로 회전합니다. 일부는 단일 360도 회전을 수행하고 다른 일부는 더 빠른 효과를 위해 여러 번 회전합니다. 각 변형에 대해 별도의 키프레임을 생성하는 대신 모든 시나리오를 처리하는 하나의 유연한 스핀을 구축해 보겠습니다.
/* * 스핀 - 회전 애니메이션 * 회전 범위를 제어하려면 --kf-spin-from 및 --kf-spin-to를 사용하십시오. * 회전량을 제어하려면 --kf-spin-turns를 사용하십시오. * 기본값: 0deg에서 360deg까지 회전(1회전) * 사용법: * 애니메이션: kf-spin 1s 선형 무한; * --kf-spin-turns: 2; // 2회전 * --kf-spin-from: 0deg; --kf-회전: 180deg; // 반회전 * --kf-spin-from: 0deg; --kf-spin-to: -360deg; // 시계 반대 방향 */
@keyframes kf-spin { {에서 회전: var(--kf-spin-from, 0deg); } ~에게 { 회전: calc(var(--kf-spin-from, 0deg) + var(--kf-spin-to, 360deg) * var(--kf-spin-turns, 1)); } }
이제 원하는 스핀 변형을 만들 수 있습니다.
.loading-spinner { 애니메이션: kf-spin 1s 선형 무한; /* 기본값 사용: 0deg에서 360deg로 회전 */ }
.fast-loader { 애니메이션: kf-spin 1.2s easy-in-out 무한 대체; --kf-스핀-턴: 3; /* 사이클당 각 방향에 대해 3번의 완전 회전*/ }
.단계-역방향 { 애니메이션: kf-spin 1.5s 단계(8) 무한; --kf-spin-to: -360deg; /* 시계 반대 방향 */ }
.미묘하게 흔들기 { 애니메이션: kf-spin 2s easy-in-out 무한 대체; --kf-spin-from: -16deg; --kf-스핀-투: 32deg; /* 36도 흔들기: -18도에서 +18도 사이 */ }
Amit Sheen이 작성한 펜 키프레임 토큰 - 데모 5(포크됨)를 참조하세요. 이 접근 방식의 장점은 동일한 키프레임이 스피너 로드, 아이콘 회전, 흔들기 효과 및 복잡한 다중 회전 애니메이션에도 작동한다는 것입니다. 펄스 역설 펄스 애니메이션은 다양한 속성을 "펄스"할 수 있기 때문에 더 까다롭습니다. 일부는 스케일에 펄스를 주고 다른 일부는 불투명도에 펄스를 주며 일부는 밝기나 채도와 같은 색상 속성을 펄스합니다. 각 속성에 대해 별도의 키프레임을 만드는 대신 모든 CSS 속성에서 작동하는 키프레임을 만들 수 있습니다. 다음은 배율 및 불투명도 옵션이 있는 펄스 키프레임의 예입니다.
/* * 펄스 - 펄스 애니메이션 * 스케일 범위를 제어하려면 --kf-pulse-scale-from 및 --kf-pulse-scale-to를 사용하십시오. * 불투명도 범위를 제어하려면 --kf-pulse-opacity-from 및 --kf-pulse-opacity-to를 사용하십시오. * 기본값: 펄스 없음(모든 값은 1) * 사용법: * 애니메이션: kf-pulse 2s easy-in-out 무한 대체; * --kf-pulse-scale-from: 0.95; --kf-펄스-규모-to: 1.05; // 스케일 펄스 * --kf-펄스-불투명도-from: 0.7; --kf-펄스-불투명도: 1; // 불투명 펄스 */
@keyframes kf-펄스 { {에서 규모: var(--kf-pulse-scale-from, 1); 불투명도: var(--kf-pulse-opacity-from, 1); } ~에게 { 규모: var(--kf-pulse-scale-to, 1); 불투명도: var(--kf-pulse-opacity-to, 1); } }
이는 여러 속성에 애니메이션을 적용할 수 있는 유연한 펄스를 생성합니다. .클릭 유도 문구 { 애니메이션: kf-펄스 0.6초 무한 대체; --kf-펄스-불투명도-from: 0.5; /* 불투명도 펄스 */ }
.notification-점 { 애니메이션: kf-pulse 0.6s easy-in-out 무한 대체; --kf-펄스-스케일-에서: 0.9; --kf-펄스-규모-to: 1.1; /* 스케일 펄스 */ }
.text-하이라이트 { 애니메이션: kf-pulse 1.5s 이지아웃 무한; --kf-펄스-스케일-에서: 0.8; --kf-펄스-불투명도-from: 0.2; /* 스케일 및 불투명도 펄스 */ }
Amit Sheen이 작성한 펜 키프레임 토큰 - 데모 6 [포크]를 참조하세요. 이 단일 kf-펄스 키프레임은 미묘한 관심 끌기부터 드라마틱한 하이라이트까지 모든 것을 처리하는 동시에 쉽게 사용자 지정할 수 있습니다. 고급 완화 키프레임 토큰 사용의 가장 큰 장점 중 하나는 애니메이션 라이브러리를 확장하고 탄성 또는 바운스와 같이 대부분의 개발자가 처음부터 작성하지 않아도 되는 효과를 제공하는 것이 얼마나 쉬운지입니다. 다음은 점프 높이를 제어하기 위해 --kf-bounce-from 사용자 정의 속성을 사용하는 간단한 "바운스" 키프레임 토큰의 예입니다. /* * 바운스 - 바운싱 입구 애니메이션 * 점프 높이를 제어하려면 --kf-bounce-from을 사용하세요. * 기본값: 100vh에서 점프(오프스크린) * 사용법: * 애니메이션: kf-bounce 3s이지 인; * --kf-bounce-from: 200px; // 200px 높이에서 점프 */
@keyframes kf-bounce { 0% { 번역: 0 calc(var(--kf-bounce-from, 100vh) * -1); }
34% { 번역: 0 calc(var(--kf-bounce-from, 100vh) * -0.4); }
55% { 번역: 0 calc(var(--kf-bounce-from, 100vh) * -0.2); }
72% { 번역: 0 calc(var(--kf-bounce-from, 100vh) * -0.1); }
85% { 번역: 0 calc(var(--kf-bounce-from, 100vh) * -0.05); }
94% { 번역: 0 calc(var(--kf-bounce-from, 100vh) * -0.025); }
99% { 번역: 0 calc(var(--kf-bounce-from, 100vh) * -0.0125); }
22%, 45%, 64%, 79%, 90%, 97%, 100% { 번역: 0 0; 애니메이션 타이밍 기능: 완화; } }
"elastic"과 같은 애니메이션은 키프레임 내부의 계산으로 인해 조금 더 까다롭습니다. --kf-elastic-from-X 및 --kf-elastic-from-Y를 별도로 정의해야 하며(둘 다 선택 사항) 이를 함께 사용하면 화면의 어느 지점에서든 탄력적인 입구를 만들 수 있습니다.
/* * Elastic In - 탄력있는 입구 애니메이션 * 시작 위치를 제어하려면 --kf-elastic-from-X 및 --kf-elastic-from-Y를 사용하십시오. * Default : 상단 중앙부터 입력 (0, -100vh) * 사용법: * 애니메이션: kf-elastic-in 2s easy-in-out 둘 다; * --kf-elastic-from-X: -50px; * --kf-elastic-from-Y: -200px; // (-50px, -200px)에서 입력 */
@keyframes kf-elastic-in { 0% { 번역: calc(var(--kf-elastic-from-X, -50vw) * 1) calc(var(--kf-elastic-from-Y, 0px) * 1); }
16% { 번역: calc(var(--kf-elastic-from-X, -50vw) * -0.3227) calc(var(--kf-elastic-from-Y, 0px) * -0.3227); }
28% { 번역: calc(var(--kf-elastic-from-X, -50vw) * 0.1312)calc(var(--kf-elastic-from-Y, 0px) * 0.1312); }
44% { 번역: calc(var(--kf-elastic-from-X, -50vw) * -0.0463) calc(var(--kf-elastic-from-Y, 0px) * -0.0463); }
59% { 번역: calc(var(--kf-elastic-from-X, -50vw) * 0.0164) calc(var(--kf-elastic-from-Y, 0px) * 0.0164); }
73% { 번역: calc(var(--kf-elastic-from-X, -50vw) * -0.0058) calc(var(--kf-elastic-from-Y, 0px) * -0.0058); }
88% { 번역: calc(var(--kf-elastic-from-X, -50vw) * 0.0020) calc(var(--kf-elastic-from-Y, 0px) * 0.0020); }
100% { 번역: 0 0; } }
이 접근 방식을 사용하면 단일 사용자 정의 속성만 변경하여 프로젝트 전체에서 고급 키프레임을 쉽게 재사용하고 사용자 정의할 수 있습니다.
.bounce-and-zoom { 애니메이션: kf-bounce 3s이지 인, kf-zoom 3s 선형; --kf-zoom-from: 0; }
.바운스 앤 슬라이드 { 애니메이션 구성: 추가; /* 두 애니메이션 모두 번역을 사용합니다 */ 애니메이션: kf-bounce 3s이지 인, kf-슬라이드인 3s 이지아웃; --kf-슬라이드-에서: -200px; }
.elastic-in { 애니메이션: kf-elastic-in 2s easy-in-out 둘 다; }
Amit Sheen이 작성한 펜 키프레임 토큰 - 데모 7(포크됨)을 참조하세요. 지금까지 우리는 스마트하고 효율적인 방법으로 키프레임을 통합하는 방법을 살펴보았습니다. 물론 프로젝트 요구 사항에 더 잘 맞도록 조정하고 싶을 수도 있지만 몇 가지 일반적인 애니메이션과 일상적인 사용 사례의 예를 다루었습니다. 그리고 이러한 키프레임 토큰을 사용하면 이제 전체 프로젝트에서 일관되고 유지 관리 가능한 애니메이션을 만들기 위한 강력한 구성 요소가 있습니다. 더 이상 중복된 키프레임이 없으며 더 이상 전역 범위 충돌이 없습니다. 모든 애니메이션 요구 사항을 처리할 수 있는 깔끔하고 편리한 방법입니다. 하지만 진짜 질문은 이 빌딩 블록을 어떻게 함께 구성할 것인가입니다. 모든 것을 하나로 합치기 우리는 기본 키프레임 토큰을 결합하는 것이 간단하다는 것을 확인했습니다. 특별한 것은 필요하지 않지만 첫 번째 애니메이션을 정의하고, 두 번째 애니메이션을 정의하고, 필요에 따라 변수를 설정하면 끝입니다. /* 페이드 인 + 슬라이드 인 */ .토스트 { 애니메이션: kf-페이드인 0.4초, kf-슬라이드인 0.4초 입방 베지어(0.34, 1.56, 0.64, 1); --kf-슬라이드-에서: 0 40px; }
/* 확대 + 페이드 인 */ .모달 { 애니메이션: kf-페이드인 0.3초, kf-zoom 0.3s 입방 베지어(0.34, 1.56, 0.64, 1); --kf-zoom-from: 0.7; --kf-zoom-to: 1; }
/* 슬라이드 인 + 펄스 */ .알림 { 애니메이션: kf-슬라이드인 0.5초, kf-pulse 1.2s easy-in-out 무한 대체; --kf-슬라이드-에서: -100px 0; --kf-펄스-스케일-에서: 0.95; --kf-펄스-규모-to: 1.05; }
이러한 조합은 각 애니메이션이 불투명도, 변형(변환/크기 조정) 등 서로 다른 속성을 대상으로 하기 때문에 훌륭하게 작동합니다. 그러나 때때로 충돌이 발생하며 충돌이 발생하는 이유와 처리 방법을 알아야 합니다. 두 애니메이션이 동일한 속성에 애니메이션을 적용하려고 시도하는 경우(예: 둘 다 스케일 애니메이션 또는 둘 다 불투명도 애니메이션) 결과는 예상한 것과 다릅니다. 기본적으로 애니메이션 중 하나만 실제로 해당 속성에 적용됩니다. 이는 애니메이션 목록의 마지막 속성입니다. 이는 CSS가 동일한 속성에 대해 여러 애니메이션을 처리하는 방법에 대한 제한 사항입니다. 예를 들어 kf-pulse 애니메이션만 적용되므로 의도한 대로 작동하지 않습니다. .bad-콤보 { 애니메이션: kf-zoom 0.5초 앞으로, kf-펄스 1.2s 무한 대체; --kf-zoom-from: 0.5; --kf-zoom-to: 1.2; --kf-펄스-스케일-에서: 0.8; --kf-펄스-규모-to: 1.1; }
애니메이션 추가 동일한 속성에 영향을 미치는 여러 애니메이션을 처리하는 가장 간단하고 직접적인 방법은 animation-composition 속성을 사용하는 것입니다. 위의 마지막 예에서 kf-pulse 애니메이션은 kf-zoom 애니메이션을 대체하므로 초기 확대/축소가 표시되지 않으며 예상 배율이 1.2가 되지 않습니다. 추가할 애니메이션 구성을 설정하여 브라우저에 두 애니메이션을 결합하도록 지시합니다. 이는 우리가 원하는 결과를 제공합니다. .comComponent-2 { 애니메이션 구성: 추가; }
Amit Sheen이 작성한 펜 키프레임 토큰 - 데모 8(포크됨)을 참조하세요. 이 접근 방식은 동일한 속성에 대한 효과를 결합하려는 대부분의 경우에 적합합니다. 애니메이션을 정적 속성 값과 결합해야 할 때도 유용합니다. 예를 들어, 변환 속성을 사용하여 원하는 위치에 정확하게 배치하는 요소가 있고 kf-slide-in 키프레임을 사용하여 애니메이션을 적용하려는 경우 애니메이션 구성 없이 눈에 띄게 점프하는 현상이 발생합니다. Amit Sheen이 작성한 펜 키프레임 토큰 - 데모 9(포크됨)를 참조하세요. 추가할 애니메이션 구성을 설정하면 기존 애니메이션과 애니메이션이 원활하게 결합됩니다.변환하므로 요소가 제자리에 유지되고 예상대로 애니메이션이 적용됩니다. 애니메이션 스태거 여러 애니메이션을 처리하는 또 다른 방법은 애니메이션을 "엇갈리게" 하는 것입니다. 즉, 첫 번째 애니메이션이 끝난 후 약간 후에 두 번째 애니메이션을 시작합니다. 모든 경우에 작동하는 솔루션은 아니지만, 시작 애니메이션에 이어 연속 애니메이션이 있을 때 유용합니다. /* 페이드 인 + 불투명도 펄스 */ .알림 { 애니메이션: kf-페이드인 2s 이지아웃, kf-pulse 0.5s 2s easy-in-out 무한 대체; --kf-펄스-불투명도: 0.5; }
Amit Sheen이 작성한 펜 키프레임 토큰 - 데모 10(포크됨)을 참조하세요. 주문 사항 우리가 작업하는 애니메이션의 대부분은 변형 속성을 사용합니다. 대부분의 경우 이것이 더 편리합니다. 또한 변환 애니메이션이 GPU 가속이 가능하므로 성능상의 이점도 있습니다. 그러나 변환을 사용하는 경우 변환을 수행하는 순서가 중요하다는 점을 받아들여야 합니다. 많이. 지금까지 키프레임에서는 개별 변환을 사용했습니다. 사양에 따르면 이들은 항상 고정된 순서로 적용됩니다. 먼저 요소가 이동되고 회전되고 크기가 조정됩니다. 이것은 의미가 있으며 우리 대부분이 기대하는 것입니다. 그러나 변환 속성을 사용하는 경우 함수가 작성되는 순서는 함수가 적용되는 순서입니다. 이 경우 X축에서 무언가를 100픽셀 이동한 다음 45도 회전하면 먼저 45도 회전한 다음 100픽셀 이동하는 것과는 다릅니다. /* 분홍색 사각형: 먼저 이동한 다음 회전 */ .example-1 { 변환: 번역X(100px) 회전(45deg); }
/* 녹색 사각형: 먼저 회전한 다음 이동합니다 */ .example-2 { 변환: 회전(45deg) 변환X(100px); }
Amit Sheen의 펜 키프레임 토큰 - 데모 11 [포크됨]을 참조하세요. 그러나 변환 순서에 따라 모든 개별 변환(키프레임 토큰에 사용한 모든 것)은 변환 기능보다 먼저 발생합니다. 이는 변환 속성에 설정한 모든 작업이 애니메이션 이후에 발생함을 의미합니다. 그러나 예를 들어 kf-spin 키프레임과 함께 변환을 설정하면 애니메이션이 시작되기 전에 변환이 발생합니다. 아직 혼란 스럽습니까?! 이로 인해 다음과 같이 정적 값이 동일한 애니메이션에 대해 다른 결과를 초래할 수 있는 상황이 발생합니다.
/* 두 스피너에 대한 공통 애니메이션 */ .스피너 { 애니메이션: kf-spin 1s 선형 무한; }
/* 핑크 스피너: 회전 전 이동(개별 변환) */ .spinner-핑크 { 번역: 100% 50%; }
/* 녹색 스피너: 회전 후 이동(함수 순서) */ .spinner-녹색 { 변환: 변환(100%, 50%); }
Amit Sheen이 작성한 펜 키프레임 토큰 - 데모 12(포크됨)를 참조하세요. 첫 번째 스피너(분홍색)가 kf-spin의 회전 전에 발생하는 변환을 가져오므로 먼저 해당 위치로 이동한 다음 회전하는 것을 볼 수 있습니다. 두 번째 스피너(녹색)는 개별 변환 후에 발생하는 Translate() 함수를 가져오므로 요소가 먼저 회전한 다음 현재 각도를 기준으로 이동하여 넓은 궤도 효과를 얻습니다. 아니요, 이것은 버그가 아닙니다. 이는 CSS에 대해 알아야 할 사항 중 하나일 뿐이며 여러 애니메이션이나 여러 변환 작업을 할 때 명심해야 합니다. 필요한 경우 Rotate() 함수를 사용하여 요소를 회전하는 추가 kf-spin-alt 키프레임 세트를 만들 수도 있습니다. 모션 감소 대체 키프레임에 대해 이야기하는 동안 "애니메이션 없음" 옵션을 무시할 수 없습니다. 키프레임 토큰을 사용할 때의 가장 큰 장점 중 하나는 접근성을 구현할 수 있다는 점이며 실제로는 매우 쉽습니다. 접근성을 염두에 두고 키프레임을 설계함으로써 모션 감소를 선호하는 사용자가 추가 작업이나 코드 중복 없이 더 부드럽고 덜 산만한 환경을 얻을 수 있도록 보장할 수 있습니다. "모션 감소"의 정확한 의미는 애니메이션마다, 프로젝트마다 조금씩 다를 수 있지만 다음은 명심해야 할 몇 가지 중요한 사항입니다. 키프레임 음소거 일부 애니메이션은 부드러워지거나 느려질 수 있지만 모션 감소가 요청되면 완전히 사라져야 하는 애니메이션도 있습니다. 펄스 애니메이션이 좋은 예입니다. 이러한 애니메이션이 모션 감소 모드에서 실행되지 않도록 하려면 적절한 미디어 쿼리로 간단히 래핑하면 됩니다.
@media (prefers-reduced-motion: no-preference) { @keyfrmaes kf-펄스 { {에서 규모: var(--kf-pulse-scale-from, 1); 불투명도: var(--kf-pulse-opacity-from, 1); } ~에게 { 규모: var(--kf-pulse-scale-to, 1); 불투명:var(--kf-펄스-불투명도, 1); } } }
이렇게 하면 선호-감소-모션을 감소로 설정한 사용자는 애니메이션을 볼 수 없으며 자신의 선호도에 맞는 경험을 얻을 수 있습니다. 인스턴트 인 입구 애니메이션과 같이 간단히 제거할 수 없는 일부 키프레임이 있습니다. 가치는 변해야 하고, 살아 있어야 합니다. 그렇지 않으면 요소의 값이 올바르지 않게 됩니다. 그러나 감소된 모션에서는 초기 값으로부터의 전환이 즉각적이어야 합니다. 이를 달성하기 위해 값이 즉시 최종 상태로 이동하는 추가 키프레임 세트를 정의합니다. 이것이 기본 키프레임이 됩니다. 그런 다음 이전 예와 마찬가지로 기본 설정 없음으로 설정된 Prefers-Reduced-Motion에 대한 미디어 쿼리 내에 일반 키프레임을 추가합니다. /* 움직임을 줄이기 위해 즉시 팝업 */ @keyframes kf-zoom { 에서, 까지 { 규모: var(--kf-zoom-to, 1); } }
@media (prefers-reduced-motion: no-preference) { /* 원본 확대/축소 키프레임 */ @keyframes kf-zoom { {에서 규모: var(--kf-zoom-from, 0.8); } ~에게 { 규모: var(--kf-zoom-to, 1); } } }
이렇게 하면 모션 감소를 선호하는 사용자는 요소가 최종 상태로 즉시 나타나는 것을 볼 수 있고 다른 모든 사람은 애니메이션 전환을 볼 수 있습니다. 부드러운 접근 방식 약간의 움직임을 유지하고 싶지만 원본 애니메이션보다 훨씬 부드럽고 차분한 경우가 있습니다. 예를 들어, 바운스 입구를 부드러운 페이드인으로 대체할 수 있습니다.
@keyframes kf-bounce { /* 움직임 감소를 위한 부드러운 페이드인 */ }
@media (prefers-reduced-motion: no-preference) { @keyframes kf-bounce { /* 원본 바운스 키프레임 */ } }
이제 모션 감소가 활성화된 사용자는 여전히 외관감을 느낄 수 있지만 바운스나 탄성 애니메이션의 강렬한 움직임은 없습니다. 빌딩 블록이 준비되면 다음 질문은 이를 실제 워크플로의 일부로 만드는 방법입니다. 유연한 키프레임을 작성하는 것도 중요하지만 대규모 프로젝트에서 이를 안정적으로 만들려면 제가 힘들게 배워야 했던 몇 가지 전략이 필요합니다. 구현 전략 및 모범 사례 키프레임 토큰의 견고한 라이브러리가 확보되면 실제 과제는 이를 일상 작업에 적용하는 방법입니다.
모든 키프레임을 한 번에 적용하고 문제가 해결되었다고 선언하고 싶은 유혹이 있지만 실제로는 점진적인 채택을 통해 최상의 결과를 얻을 수 있다는 것을 알게 되었습니다. 페이드 또는 슬라이드와 같은 가장 일반적인 애니메이션부터 시작하세요. 이는 대규모 재작성을 요구하지 않고도 즉각적인 가치를 보여주는 손쉬운 승리입니다. 네이밍 역시 주목할 만한 점이다. 일관된 접두사 또는 네임스페이스를 사용하면 어떤 애니메이션이 토큰이고 어떤 애니메이션이 로컬 일회성인지 분명하게 알 수 있습니다. 또한 우발적인 충돌을 방지하고 새로운 팀원이 공유 시스템을 한눈에 인식할 수 있도록 도와줍니다. 문서화는 코드 자체만큼 중요합니다. 각 키프레임 토큰 위에 짧은 설명만 추가해도 나중에 추측하는 데 드는 시간을 절약할 수 있습니다. 개발자는 토큰 파일을 열고, 필요한 효과를 검색하고, 사용 패턴을 구성 요소에 직접 복사할 수 있어야 합니다. 유연성은 이러한 접근 방식을 노력할 가치가 있게 만드는 요소입니다. 합리적인 사용자 정의 속성을 노출함으로써 팀이 시스템을 중단하지 않고 애니메이션을 조정할 수 있는 공간을 제공합니다. 동시에 지나치게 복잡하지 않도록 노력하십시오. 중요한 손잡이만 제공하고 나머지는 자기 의견을 유지하도록 하세요. 마지막으로 접근성을 기억하세요. 모든 애니메이션에 모션 축소 대안이 필요한 것은 아니지만 많은 애니메이션이 필요합니다. 이러한 조정 사항을 조기에 적용한다는 것은 나중에 다시 조정할 필요가 없다는 것을 의미하며 사용자가 언급하지 않더라도 주의를 기울인다는 것을 보여줍니다.
내 경험에 따르면 키프레임 토큰을 디자인 토큰 작업 흐름의 일부로 처리하는 것이 키프레임 토큰을 고정시키는 요인입니다. 일단 배치되면 특수 효과 같은 느낌이 사라지고 제품이 움직이고 반응하는 방식이 자연스럽게 확장되는 디자인 언어의 일부가 됩니다. 마무리 애니메이션은 인터페이스 구축에서 가장 즐거운 부분 중 하나일 수 있지만 구조가 없으면 좌절감을 주는 가장 큰 원인 중 하나가 될 수도 있습니다. 키프레임을 토큰으로 처리하면 일반적으로 지저분하고 관리하기 어려운 것을 명확하고 예측 가능한 시스템으로 바꿀 수 있습니다. 실제 가치는 단지 몇 줄의 코드를 저장하는 데에만 있는 것이 아닙니다. 페이드, 슬라이드, 확대/축소 또는 회전을 사용할 때 프로젝트 전반에 걸쳐 이것이 어떻게 작동할지 정확히 알 수 있다는 확신이 있습니다. 끝없는 변형의 혼란 없이 사용자 정의 속성에서 나오는 유연성이 바로 그것입니다. 그리고 그것은 추가되는 것이 아니라 기초에 내장된 접근성에 있습니다.나중에 생각. 나는 이러한 아이디어가 다른 팀과 다른 코드베이스에서 작동하는 것을 보았고 패턴은 항상 동일했습니다. 토큰이 배치되면 키프레임은 더 이상 흩어진 트릭 모음이 아니며 디자인 언어의 일부가 됩니다. 이를 통해 제품이 더욱 의도적이고 일관되며 생동감 넘치는 느낌을 받게 됩니다. 이 글에서 한 가지만 말씀드리자면 애니메이션은 우리가 이미 색상, 타이포그래피, 간격에 부여한 것과 동일한 관리와 구조를 가질 자격이 있다는 것입니다. 키프레임 토큰에 대한 소액의 투자는 인터페이스가 움직일 때마다 성과를 거두게 됩니다.