모션은 사용자를 한 상호작용에서 다음 상호작용으로 안내하는 모든 디지털 환경의 핵심 부분입니다. 하지만 웹 플랫폼의 부드러운 애니메이션에는 몇 가지 간격이 있습니다. 여기에는 들어가기 및 나가기 애니메이션을 쉽게 애니메이션 처리하고 대화상자 및 팝오버와 같이 닫을 수 있는 요소의 최상위 레이어로 부드럽게 애니메이션 처리하는 기능이 포함됩니다.
이러한 공백을 메우기 위해 Chrome 116 및 117에는 개별 속성에 대한 원활한 애니메이션과 전환을 지원하는 4가지 새로운 웹 플랫폼 기능이 포함되어 있습니다.
새로운 기능 4가지에는 다음이 포함됩니다.
- 키프레임 타임라인에서
display
및content-visibility
에 애니메이션을 적용하는 기능 (Chrome 116부터) display
와 같은 개별 속성의 전환을 사용 설정하기 위한allow-discrete
키워드가 있는transition-behavior
속성 (Chrome 117부터)display: none
에서 상위 레이어로 들어가기 효과를 애니메이션 처리하는@starting-style
규칙입니다 (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으로 애니메이션 처리한 다음 디스플레이를 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. 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;
}
/* 1. BEFORE-OPEN STATE */
/* Starting point for the transition */
@starting-style {
.item {
opacity: 0;
height: 0;
}
}
/* 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 목록 항목의 진입 상태와 종료 상태가 모두 있습니다.
최상위 레이어로의 요소 애니메이션
요소를 최상위 레이어로 이동하거나 최상위 레이어에서 이동하는 애니메이션을 적용하려면 'open' 상태에서 @starting-style
를 지정하여 브라우저에 애니메이션을 적용할 위치를 알립니다. 대화상자의 경우 열린 상태는 [open]
속성으로 정의됩니다. 팝오버의 경우 :popover-open
가상 클래스를 사용합니다.
대화상자의 간단한 예는 다음과 같습니다.
/* 0. IS-OPEN STATE */
dialog[open] {
translate: 0 0;
}
/* 1. BEFORE-OPEN STATE */
@starting-style {
dialog[open] {
translate: 0 100vh;
}
}
/* 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. IS-OPEN STATE */
/* state when popover is open, BOTH:
what we're transitioning *in* to
and transitioning *out* from */
transform: translateY(0);
opacity: 1;
/* 1. 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;
}
}
/* 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
를 애니메이션 처리하고 애니메이션 처리 시 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. */
그런 다음 JavaScript에서 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
를 추가해야 합니다.
결론
이러한 새로운 플랫폼 기능을 통해 웹 플랫폼에서 원활한 진입 및 종료 애니메이션을 구현하는 데 한 걸음 더 다가갈 수 있습니다. 자세한 내용은 다음 링크를 확인하세요.