모션은 모든 디지털 경험의 핵심으로, 사용자를 한 상호작용에서 다음 상호작용으로 안내합니다. 하지만 웹 플랫폼에서는 자연스러운 애니메이션에 약간의 차이가 있습니다. 이러한 기능으로는 진입 및 이탈 애니메이션에 쉽게 애니메이션을 적용하고 대화상자 및 팝오버와 같이 닫을 수 있는 요소를 위해 상단 레이어로 또는 상단 레이어에서 부드럽게 애니메이션 처리할 수 있는 기능이 포함됩니다.
이러한 공백을 메우기 위해 Chrome 116 및 117에는 개별 속성에 매끄러운 애니메이션과 전환을 지원하는 4가지 새로운 웹 플랫폼 기능이 포함되어 있습니다.
새로운 4가지 기능은 다음과 같습니다.
- 키프레임 타임라인에서
display
및content-visibility
에 애니메이션을 적용하는 기능 (Chrome 116부터) display
와 같은 개별 속성을 전환할 수 있도록 하는allow-discrete
키워드가 있는transition-behavior
속성 (Chrome 117부터)@starting-style
규칙은display: none
에서 최상위 레이어로 항목 효과를 애니메이션으로 보여줍니다 (Chrome 117부터).- 애니메이션 도중 상단 레이어 동작을 제어하는
overlay
속성 (Chrome 117부터) ## 키프레임에 애니메이션 표시
Chrome 116부터 키프레임 규칙에서 display
및 content-visibility
를 사용할 수 있습니다. 그러면 키프레임이 발생하는 시점에 서로 변경됩니다. 이를 지원하는 데 새로운 값이 추가로 필요하지는 않습니다.
.card {
animation: fade-out 0.5s forwards;
}
@keyframes fade-out {
100% {
opacity: 0;
display: none;
}
}
위의 예에서는 0.5초 동안 불투명도를 0으로 애니메이션 처리한 다음 display display를 none으로 설정합니다. 또한 forwards
키워드는 애니메이션이 최종 상태로 유지되도록 하여 적용되는 요소가 display: none
및 opacity: 0
로 유지되도록 합니다.
다음은 전환으로 할 수 있는 작업을 모방한 간단한 예입니다 (전환 섹션의 데모 참고). 그러나 전환은 다음 예와 같이 더 복잡한 애니메이션을 만들 수 없습니다.
.card {
animation: spin-and-delete 1s ease-in forwards;
}
@keyframes spin-and-delete {
0% {
transform: rotateY(0);
filter: hue-rotate(0);
}
80% {
transform: rotateY(360deg);
filter: hue-rotate(180deg);
opacity: 1;
}
100% {
opacity: 0;
display: none;
}
}
spin-and-delete
애니메이션은 종료 애니메이션입니다. 먼저 카드가 y축에서 회전하고 색조 순환을 통해 실행된 다음 80%
에서 타임라인을 통해 불투명도를 1에서 0으로 전환합니다. 마지막으로 카드가 display: block
에서 display: none
로 전환됩니다.
이러한 이탈 애니메이션의 경우 요소에 직접 적용하는 대신 애니메이션 트리거를 설정할 수 있습니다. 예를 들어 다음과 같이 애니메이션 적용을 위한 클래스를 트리거하는 버튼에 이벤트 리스너를 연결합니다.
.spin-out {
animation: spin-and-delete 1s ease-in forwards;
}
document.querySelector('.delete-btn').addEventListener('click', () => {
document.querySelector('.card').classList.add('spin-out');
})
이제 위의 예의 최종 상태는 display:none
입니다. 더 나아가 애니메이션이 먼저 완료될 수 있도록 시간 제한으로 DOM 노드를 제거하려는 경우가 많이 있습니다.
불연속 애니메이션 전환
키프레임으로 불연속 속성에 애니메이션을 적용할 때와 달리 불연속 속성을 전환하려면 allow-discrete
전환 동작 모드를 사용해야 합니다.
transition-behavior
속성
allow-discrete
모드는 불연속 전환을 가능하게 하는 모드이며 transition-behavior
속성의 값입니다. transition-behavior
는 normal
와 allow-discrete
, 이렇게 두 가지 값을 허용합니다.
.card {
transition: opacity 0.25s, display 0.25s;
transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */
}
.card.fade-out {
opacity: 0;
display: none;
}
transition
약식에서도 이 값을 설정하므로 속성을 생략하고 대신 각 전환의 transition
약식 끝에 있는 allow-discrete
키워드를 대신 사용할 수 있습니다.
.card {
transition: opacity 0.5s, display 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
여러 불연속 속성에 애니메이션을 적용하는 경우 애니메이션을 적용할 각 속성 뒤에 allow-discrete
를 포함해야 합니다. 예를 들면 다음과 같습니다.
.card {
transition: opacity 0.5s, display 0.5s allow-discrete, overlay 0.5s allow-discrete;
}
.card.fade-out {
opacity: 0;
display: none;
}
항목 애니메이션의 @starting-style
규칙
지금까지 이 도움말에서는 종료 애니메이션을 다루었습니다. 항목 애니메이션을 만들려면 @starting-style
규칙을 사용해야 합니다.
@starting-style
를 사용하여 요소가 페이지에서 열리기 전에 브라우저가 조회할 수 있는 스타일을 적용합니다. 이것이 '개방 전' 상태입니다 (애니메이션을 시작할 때).
/* 0. BEFORE-OPEN STATE */
/* Starting point for the transition */
@starting-style {
.item {
opacity: 0;
height: 0;
}
}
/* 1. IS-OPEN STATE */
/* The state at which the element is open + transition logic */
.item {
height: 3rem;
display: grid;
overflow: hidden;
transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete;
}
/* 2. EXITING STATE */
/* While it is deleting, before DOM removal in JS, apply this
transformation for height, opacity, and a transform which
skews the element and moves it to the left before setting
it to display: none */
.is-deleting {
opacity: 0;
height: 0;
display: none;
transform: skewX(50deg) translateX(-25vw);
}
이제 이러한 TODO 목록 항목에 진입 및 종료 상태가 모두 있습니다.
상단 레이어로 또는 최상위 레이어에서 요소에 애니메이션 적용
상단 레이어에서 요소에 애니메이션을 적용하려면 '열림' 상태에서 @starting-style
를 지정하여 애니메이션을 적용할 위치를 브라우저에 알립니다. 대화상자의 경우 열린 상태는 [open]
속성으로 정의됩니다. 팝오버의 경우 :popover-open
의사 클래스를 사용합니다.
대화상자의 간단한 예는 다음과 같습니다.
/* 0. BEFORE-OPEN STATE */
@starting-style {
dialog[open] {
translate: 0 100vh;
}
}
/* 1. IS-OPEN STATE */
dialog[open] {
translate: 0 0;
}
/* 2. EXIT STATE */
dialog {
transition: translate 0.7s ease-out, overlay 0.7s ease-out allow-discrete, display 0.7s ease-out allow-discrete;
translate: 0 100vh;
}
다음 예에서는 진입 효과와 종료 효과가 다릅니다. 표시 영역의 하단에서 위쪽으로 애니메이션을 적용하여 진입하고 표시 영역의 상단으로 효과를 종료합니다. 또한 더 시각적인 캡슐화를 위해 중첩된 CSS로 작성됩니다.
팝오버를 애니메이션화할 때는 이전에 사용한 open
속성 대신 :popover-open
의사 클래스를 사용합니다.
.settings-popover {
&:popover-open {
/* 0. BEFORE-OPEN STATE */
/* Initial state for what we're animating *in* from,
in this case: goes from lower (y + 20px) to center */
@starting-style {
transform: translateY(20px);
opacity: 0;
}
/* 1. IS-OPEN STATE */
/* state when popover is open, BOTH:
what we're transitioning *in* to
and transitioning *out* from */
transform: translateY(0);
opacity: 1;
}
/* 2. EXIT STATE */
/* Initial state for what we're animating *out* to ,
in this case: goes from center to (y - 50px) higher */
transform: translateY(-50px);
opacity: 0;
/* Enumerate transitioning properties,
including display and allow-discrete mode */
transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}
숙박 시설 overlay
개
마지막으로 상단 레이어에서 popover
또는 dialog
를 페이드 아웃하려면 전환 목록에 overlay
속성을 추가합니다. popover
및 dialog
는 상위 클립 및 변환을 이스케이프 처리하고, 콘텐츠를 상단 레이어에 배치합니다. overlay
를 전환하지 않으면 요소가 즉시 잘리고, 변형되고, 덮인 상태로 되돌아가고 전환이 발생하지 않습니다.
[open] {
transition: opacity 1s, display 1s allow-discrete;
}
대신 전환이나 애니메이션에 overlay
를 포함하여 나머지 지형지물과 함께 overlay
에 애니메이션을 적용하고 애니메이션화할 때 최상위 레이어에 계속 표시되도록 하세요. 이렇게 하면 훨씬 더 매끄럽게 표시됩니다.
[open] {
transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}
또한 상단 레이어에서 여러 요소가 열려 있는 경우 오버레이를 사용하면 상단 레이어 안팎으로의 부드러운 전환을 제어할 수 있습니다. 이 간단한 예에서 차이를 확인할 수 있습니다. 전환할 때 두 번째 팝오버에 overlay
를 적용하지 않은 경우 전환을 시작하기 전에 먼저 상단 레이어에서 다른 팝오버 뒤로 이동합니다. 이 과정은 순조롭게 진행되지는 않습니다.
뷰 전환 참고 사항
DOM에서 요소를 추가 및 삭제하는 등 DOM을 변경하는 경우, 매끄러운 애니메이션을 위한 또 다른 좋은 솔루션은 뷰 전환입니다. 다음은 뷰 전환을 사용하여 빌드된 위의 두 가지 예입니다.
이 첫 번째 데모에서는 @starting-style
및 기타 CSS 변환을 설정하는 대신 뷰 전환이 전환을 처리합니다. 뷰 전환은 다음과 같이 설정됩니다.
먼저 CSS에서 각 카드에 개별 view-transition-name
를 지정합니다.
.card-1 {
view-transition-name: card-1;
}
.card-2 {
view-transition-name: card-2;
}
/* etc. */
그런 다음 자바스크립트에서 뷰 전환에서 DOM 변형 (이 경우 카드 삭제)을 래핑합니다.
deleteBtn.addEventListener('click', () => {
// Check for browser support
if (document.startViewTransition) {
document.startViewTransition(() => {
// DOM mutation
card.remove();
});
}
// Alternative if no browser support
else {
card.remove();
}
})
이제 브라우저가 각 카드의 페이드 아웃과 변이를 새로운 위치로 처리할 수 있습니다.
이 작업의 또 다른 예는 목록 항목 추가/삭제 데모를 사용하는 것입니다. 이 경우 생성된 각 카드에 고유한 view-transition-name
를 추가해야 합니다.
결론
이러한 새로운 플랫폼 기능을 통해 웹 플랫폼에서의 원활한 시작 및 종료 애니메이션에 한 걸음 더 가까워졌습니다. 자세히 알아보려면 다음 링크를 확인하세요.