1. 소개
이 섹션은 규범적이지 않습니다.
이 명세는 개발자가 문서의 다양한 상태 간에 뷰 전환이라 불리는 애니메이션 시각적 전환을 생성할 수 있도록 하는 DOM API와 관련 CSS 기능을 도입합니다.
1.1. 시각적 전환과 DOM 업데이트의 분리
전통적으로, 두 문서 상태 간의 시각적 전환을 만들기 위해서는 두 상태가 동시에 DOM에 존재하는 기간이 필요했습니다. 실제로는 두 상태를 모두 표현할 수 있는 특정 DOM 구조를 만드는 과정을 포함하는 경우가 많았습니다. 예를 들어, 한 요소가 컨테이너 사이를 “이동”하는 경우, 전환 기간 동안 해당 요소가 어느 컨테이너에도 속하지 않게 위치시켜야 하는 경우가 많았으며, 이는 각 컨테이너나 상위 요소에 의한 잘림(clipping)을 방지하기 위함입니다.
이러한 중간 상태는 순수 시각적 효과를 위해 DOM 구조를 손상시키므로 UX 및 접근성 문제를 유발하는 경우가 많았습니다.
뷰 전환은 DOM이 상태 간 즉시 전환될 수 있도록 하여 이러한 문제의 중간 상태를 피하고, 또 다른 레이어에서 이전 상태의 정적 시각 캡처와 새 상태의 실시간 캡처를 사용하여 두 상태 간의 커스터마이즈 가능한 시각적 전환을 수행합니다. 이러한 캡처는 의사 요소의 트리로 표현되며(자세한 내용은 § 3.2 뷰 전환 의사 요소 참고), 이전 시각적 상태와 새로운 상태가 동시에 존재할 수 있어, 크로스 페이드와 같이 이전 상태에서 새로운 크기와 위치로 애니메이션하는 효과를 구현할 수 있습니다.
1.2. 뷰 전환 커스터마이징
기본적으로,
document.
은 두 DOM 상태 사이의 페이지 전체 크로스 페이드로 구성된 뷰 전환을 생성합니다.
개발자는 view-transition-name CSS 속성을 사용하여
개별적으로 캡처될 요소를 선택할 수 있으며,
이렇게 선택된 요소들은 페이지의 나머지 부분과 독립적으로 애니메이션할 수 있습니다.
전환 상태(이전 시각 캡처와 새로운 시각 캡처가 동시에 존재하는 상태)는 의사 요소로 표현되므로,
개발자는 CSS 애니메이션 및 웹 애니메이션과 같은 익숙한 기능을 활용해
각 전환을 커스터마이즈할 수 있습니다.
startViewTransition()
1.3. 뷰 전환 라이프사이클
성공적인 뷰 전환은 다음과 같은 단계로 진행됩니다:
-
개발자가
document.
을 호출하면,startViewTransition
(updateCallback
)ViewTransition
객체 viewTransition이 반환됩니다. -
현재 상태가 “이전” 상태로 캡처됩니다.
-
렌더링이 일시 중지됩니다.
-
개발자의
updateCallback
함수(제공된 경우)가 호출되어, 문서 상태를 업데이트합니다. -
viewTransition.
이 완료됩니다.updateCallbackDone
-
현재 상태가 “새로운” 상태로 캡처됩니다.
-
전환 의사 요소가 생성됩니다. 해당 구조에 대한 개요는 § 3.2 뷰 전환 의사 요소를 참고하세요.
-
렌더링이 재개되어 전환 의사 요소가 표시됩니다.
-
viewTransition.
가 완료됩니다.ready
-
의사 요소가 애니메이션되어 완료될 때까지 진행됩니다.
-
전환 의사 요소가 제거됩니다.
-
viewTransition.
가 완료됩니다.finished
1.4. 향상 기능으로서의 전환
View Transition API 설계의 핵심은
애니메이션 전환이 문서 상태 변화에 대한 시각적 향상이라는 점입니다.
즉, 잘못된 설정이나 디바이스 제약 등으로 인해 시각적 전환 생성에 실패하더라도,
UpdateCallback
은 여전히 호출되며,
전환 애니메이션이 미리 불가능하다는 것이 알려진 경우에도 마찬가지입니다.
예를 들어, 개발자가 skipTransition()
을 뷰 전환 라이프사이클 초기에 호출하면,
뷰 전환 트리 생성 등
애니메이션 전환과 관련된 단계들은 수행되지 않습니다.
하지만 UpdateCallback
은 여전히 호출됩니다.
건너뛰는 것은 시각적 전환뿐이며,
기본적인 상태 변화는 그대로 진행됩니다.
Note: 만약 DOM 변경까지 건너뛰어야 한다면,
다른 기능을 통해 처리해야 합니다.
은 이를 처리하는 데 사용할 수 있는 기능의 예시입니다.
navigateEvent
.signal
View Transition API는 UpdateCallback
을
통해
DOM 변경을 비동기적으로 허용하지만,
API는 전환 자체에 필요한 스케줄링을 제외하고
DOM 변경을 큐잉하거나 별도로 스케줄링하는 역할을 하지 않습니다.
일부 비동기적 DOM 변경은(예: 독립적인 컴포넌트 내에서 발생하는 경우) 동시에 처리될 수 있지만,
다른 경우에는 큐잉되거나 이전 변경을 중단해야 할 수도 있습니다.
이는 애플리케이션 전체를 더 포괄적으로 관리하는 기능이나 프레임워크가 담당하는 것이 가장 적합합니다.
1.5. 렌더링 모델
뷰 전환은 UA에서 생성한 의사 요소를 사용해 요소의 렌더링 상태를 복제하는 방식으로 작동합니다. 요소 자체나 자손에 적용되는 렌더링의 측면들, 예를 들어 filter나 opacity 같은 시각 효과, overflow나 clip-path에 의한 클리핑 등은 이미지 캡처 단계에서 이미지 생성 시 적용됩니다.
하지만 mix-blend-mode 같이 요소가 포함될 때 그리기 방식을 정의하는 속성은 이미지에 적용할 수 없습니다. 이러한 속성은 요소에 해당하는 ::view-transition-group() 의사 요소에 적용되며, 이 의사 요소는 요소와 동일한 박스를 생성하기 위한 것입니다.
만약 ::view-transition-group()이 "새로운" 상태에 해당하는 요소가 있다면, 브라우저는 ::view-transition-group()에 복사된 속성을 DOM 요소의 "새로운" 상태와 동기화합니다. 만약 ::view-transition-group()이 "이전"과 "새로운" 상태 모두에 해당한다면, 그리고 복사되는 속성이 보간(interpolatable) 가능하다면, 브라우저는 해당 속성을 부드럽게 애니메이션하는 기본 애니메이션도 설정합니다.
1.6. 예시
function spaNavigate( data) { updateTheDOMSomehow( data); }
뷰 전환을 다음과 같이 추가할 수 있습니다:
function spaNavigate( data) { // 이 API를 지원하지 않는 브라우저에 대한 폴백: if ( ! document. startViewTransition) { updateTheDOMSomehow( data); return ; } // 전환을 사용한 경우: document. startViewTransition(() => updateTheDOMSomehow( data)); }
이렇게 하면 빠른 크로스 페이드가 기본 전환으로 적용됩니다:
크로스 페이드는 의사 요소 트리에 CSS 애니메이션을 적용해 구현되므로, CSS를 활용해 커스터마이즈할 수 있습니다. 예시:
::view-transition-old ( root), ::view-transition-new ( root) { animation-duration : 5 s ; }
이렇게 하면 더 느린 전환이 됩니다:
@keyframes fade-in{ from{ opacity : 0 ; } } @keyframes fade-out{ to{ opacity : 0 ; } } @keyframes slide-from-right{ from{ transform : translateX ( 30 px ); } } @keyframes slide-to-left{ to{ transform : translateX ( -30 px ); } } ::view-transition-old ( root) { animation : 90 ms cubic-bezier ( 0.4 , 0 , 1 , 1 ) both fade-out, 300 ms cubic-bezier ( 0.4 , 0 , 0.2 , 1 ) both slide-to-left; } ::view-transition-new ( root) { animation : 210 ms cubic-bezier ( 0 , 0 , 0.2 , 1 ) 90 ms both fade-in, 300 ms cubic-bezier ( 0.4 , 0 , 0.2 , 1 ) both slide-from-right; }
결과는 다음과 같습니다:
.main-header{ view-transition-name : main-header; } .main-header-text{ view-transition-name : main-header-text; /* 동일한 텍스트를 가정해 요소 크기를 일관되게 설정: */ width: fit-content; }
이 그룹들은 기본적으로 “이전”에서 “새로운” 상태로 크기와 위치를 전환하며, 시각적 상태는 크로스 페이드됩니다:
이 경우, 사이드바가 "이전"과 "새로운" 상태 모두에 있다면 정적으로 유지하는 것이 더 보기 좋습니다. 그렇지 않으면 애니메이션으로 등장하거나 사라지도록 처리해야 합니다.
:only-child 의사 클래스는 이러한 상태에 맞는 애니메이션을 만들 때 사용할 수 있습니다:
.sidebar{ view-transition-name : sidebar; } @keyframes slide-to-right{ to{ transform : translateX ( 30 px ); } } /* 등장 전환 */ ::view-transition-new ( sidebar) :only-child{ animation : 300 ms cubic-bezier ( 0 , 0 , 0.2 , 1 ) both fade-in, 300 ms cubic-bezier ( 0.4 , 0 , 0.2 , 1 ) both slide-from-right; } /* 퇴장 전환 */ ::view-transition-old ( sidebar) :only-child{ animation : 150 ms cubic-bezier ( 0.4 , 0 , 1 , 1 ) both fade-out, 300 ms cubic-bezier ( 0.4 , 0 , 0.2 , 1 ) both slide-to-right; }
사이드바가 "이전"과 "새로운" 상태 모두에 있을 때는 기본 애니메이션이 적합합니다.
먼저 CSS에서 “이전”과 “새로운” 상태가 기본 블렌딩 없이 서로 겹칠 수 있도록 하고, 기본 크로스 페이드 애니메이션을 방지합니다:
::view-transition-image-pair ( root) { isolation : auto; } ::view-transition-old ( root), ::view-transition-new ( root) { animation : none; mix-blend-mode : normal; }
그리고 JavaScript:
// 마지막 클릭 이벤트 저장 let lastClick; addEventListener( 'click' , event=> ( lastClick= event)); function spaNavigate( data) { // 이 API를 지원하지 않는 브라우저에 대한 폴백: if ( ! document. startViewTransition) { updateTheDOMSomehow( data); return ; } // 클릭 위치를 가져오거나 없으면 화면 중앙으로 대체 const x= lastClick? . clientX?? innerWidth/ 2 ; const y= lastClick? . clientY?? innerHeight/ 2 ; // 가장 먼 코너까지의 거리 계산 const endRadius= Math. hypot( Math. max( x, innerWidth- x), Math. max( y, innerHeight- y) ); // 전환 생성: const transition= document. startViewTransition(() => { updateTheDOMSomehow( data); }); // 의사 요소가 생성될 때까지 대기: transition. ready. then(() => { // 루트의 새로운 뷰에 애니메이션 적용 document. documentElement. animate( { clipPath: [ \`circle(0 at ${ x} px ${ y} px)\`, \`circle( ${ endRadius} px at ${ x} px ${ y} px)\`, ], }, { duration: 500, easing: 'ease-in', // 애니메이션할 의사 요소 지정 pseudoElement: '::view-transition-new(root)', } ); }); }
그리고 결과는 다음과 같습니다:
2. CSS 속성
2.1. 개별적으로 전환되는 하위 트리 태깅: view-transition-name 속성
이름: | view-transition-name |
---|---|
값: | none | <custom-ident> |
초기값: | none |
적용 대상: | 모든 요소 |
상속됨: | 아니오 |
백분율: | 해당 없음 |
계산된 값: | 명시된 그대로 |
정규화 순서: | 문법에 따름 |
애니메이션 타입: | 불연속(discrete) |
참고: view-transition-name은 불연속적으로 애니메이션 가능하지만, 그것을 애니메이션한다고 해서 실행 중인 뷰 전환에 영향을 주진 않습니다. 오히려 시간이 흐르면서, 또는 타임라인에 따라 해당 값을 변화시킬 수 있는 방법입니다. 예를 들어 view-transition-name을 스크롤 기반 애니메이션에 따라 변경하는 경우를 생각할 수 있습니다.
view-transition-name 속성은 요소를 뷰 전환에서 캡처 대상으로 “태그”하며, 지정된 뷰 전환 이름 아래에서 뷰 전환 트리 내에서 독립적으로 추적됩니다. 이렇게 캡처된 요소는 페이지의 나머지 부분과 독립적으로 애니메이션됩니다.
- none
-
요소는 뷰 전환에 독립적으로 참여하지 않습니다.
- <custom-ident>
-
요소는 지정된 뷰 전환 이름과 함께, 이전 또는 새로운 요소로서 뷰 전환에 독립적으로 참여합니다.
여기서 none 및 auto 값은 <custom-ident>에서 제외됩니다.
참고: 이 이름이 고유하지 않은 경우(즉, 두 요소가 동시에 동일한 뷰 전환 이름을 지정하면) 뷰 전환이 중단됩니다.
참고: 이 API에서는, 만약 한 요소가 이전 상태에서 뷰 전환 이름 foo를 갖고, 다른 요소가 새로운 상태에서 뷰 전환 이름 foo를 갖는다면, 두 요소는 동일한 요소의 서로 다른 시각적 상태로 간주되어, 뷰 전환 트리에서 쌍(pair)으로 처리됩니다. 요소 자체가 반드시 동일 객체를 참조하지 않더라도, 개념적으로 동일한 페이지 엔티티의 시각적 상태로 보는 것이 유용합니다.
요소의 주 박스(principal box)가 분절(fragmented)되거나, 내용이 건너뜀(skipped)이거나, 렌더링되지 않은 경우에는 이 속성은 효과가 없습니다. 자세한 사항은 § 7 알고리즘을 참고하세요.
2.1.1. 렌더링 통합
요소가 뷰 전환에서 캡처되었거나, 뷰 전환 중이거나, view-transition-name의 계산된 값이 none이 아닌 경우(언제든):
3. 의사 요소
3.1. 의사 요소 트리
참고: 이것은 의사 요소 트리에 대한 일반적인 정의입니다. 다른 기능에서 이 동작이 필요하다면, 이러한 정의는 [css-pseudo-4]로 이동될 수 있습니다.
의사 요소 루트는 트리 기반 의사 요소의 한 종류로, 트리 루트가 되어 트리 내의 트리 기반 의사 요소를 포함합니다. 이를 의사 요소 트리라고 합니다.
의사 요소 트리는 그 자손 트리 기반 의사 요소의 문서 순서를 정의합니다.
의사 요소가 의사 요소 트리에 참여할 때, 그 기원 의사 요소(originating pseudo-element)가 부모가 됩니다.
자손 pseudo가 의사 요소 루트의 다른 형제(sibling)가 없다면, :only-child가 그 pseudo에 매치됩니다.
참고:
::view-transition-new(ident):only-child
는 ::view-transition-image-pair(ident)
가 단일 자식만 포함할 때에만 ::view-transition-new(ident)
를 선택합니다.
즉, 형제 ::view-transition-old(ident)
가 없는 경우입니다.
3.2. 뷰 전환 의사 요소
뷰 전환의 시각화는 아래에 정의된 뷰 전환 의사 요소로 구성된 의사 요소 트리인 뷰 전환 트리로 표현됩니다. 이 트리는 전환 의사 요소 설정 단계에서 생성되며, ::view-transition 의사 요소 아래에 루트로서 위치합니다. 기원(originating)은 루트 요소입니다. 모든 뷰 전환 의사 요소는 그 궁극적 기원 요소, 즉 문서 요소에서 선택됩니다.
뷰 전환 트리는 접근성 트리에는 노출되지 않습니다.
::view-transition ├─ ::view-transition-group(name) │ └─ ::view-transition-image-pair(name) │ ├─ ::view-transition-old(name) │ └─ ::view-transition-new(name) └─ …other groups…
view-transition-name을 가진 각 요소는 개별적으로 캡처되며, 고유한 view-transition-name마다 ::view-transition-group()이 생성됩니다.
편의를 위해 문서 요소에는 view-transition-name "root"가 UA 스타일시트에서 부여됩니다.
캡처에 “이전” 또는 “새로운” 상태가 없는 경우 ::view-transition-old() 또는 ::view-transition-new()가 존재하지 않을 수 있습니다.
생성된 각각의 의사 요소는 CSS로 외형, 동작 또는 애니메이션을 커스터마이즈할 수 있습니다. 이를 통해 전환을 완전히 커스터마이즈할 수 있습니다.
3.2.1. 이름 있는 뷰 전환 의사 요소
여러 뷰 전환 의사 요소는 이름 있는 뷰 전환 의사 요소입니다. 이들은 함수형(functional) 트리 기반 뷰 전환 의사 요소로, 뷰 전환 이름과 연결됩니다. 이 의사 요소들은 <pt-name-selector>를 인자로 받고, 문법은 다음과 같습니다:
::view-transition-pseudo(<pt-name-selector>)
여기서 <pt-name-selector>는 뷰 전환 이름을 선택하며, 문법 정의는 다음과 같습니다:
<pt-name-selector> = '*' | <custom-ident>
named view transition pseudo-element 셀렉터(selector)는 해당하는 의사 요소(pseudo-element)의 <pt-name-selector>가 그 의사 요소(pseudo-element)의 view transition name과 일치할 때만 매칭됩니다. 즉, *이거나 일치하는 <custom-ident>일 때입니다.
참고: 뷰 전환 이름은 해당 뷰 전환 의사 요소를 생성한 view-transition-name으로 설정됩니다.
이름 있는 뷰 전환 의사 요소 선택자가 <custom-ident> 인자를 가지면 타입 선택자와 동일한 특이성(specificity)을 갖습니다. 이름 있는 뷰 전환 의사 요소 선택자가 * 인자를 가지면 특이성은 0입니다.
3.2.2. 뷰 전환 트리 루트: ::view-transition 의사 요소
::view-transition 의사 요소는 트리 기반 의사 요소이며 동시에 의사 요소 루트입니다. 기원 요소는 문서의 문서 요소이고, 포함 블록(containing block)은 스냅샷 포함 블록입니다.
참고: 이 요소는 모든 ::view-transition-group() 의사 요소의 부모 역할을 합니다.
3.2.3. 뷰 전환 이름 하위 트리 루트: ::view-transition-group() 의사 요소
::view-transition-group() 의사 요소는 이름 있는 뷰 전환 의사 요소로서, 일치하는 이름의 뷰 전환 캡처를 나타냅니다. ::view-transition-group() 의사 요소는 뷰 전환 이름마다 하나씩, ::view-transition 의사 요소의 자식으로 생성되며, 해당 ::view-transition-image-pair()를 포함합니다.
“이전”과 “새로운” 상태가 모두 있을 경우, 동적 뷰 전환 스타일시트의 스타일이 이 의사 요소의 width 및 height를 이전 요소의 border box 크기에서 새로운 요소의 border box 크기로 애니메이션합니다.
또한 transform 속성은 이전 요소의 화면 공간 변환에서 새로운 요소의 화면 공간 변환으로 애니메이션됩니다.
이 스타일은 애니메이션 속성 값이 전환 시작 시점에 결정되므로, 동적으로 생성됩니다.
3.2.4. 뷰 전환 이미지 페어 분리: ::view-transition-image-pair() 의사 요소
::view-transition-image-pair() 의사 요소는 이름 있는 뷰 전환 의사 요소로서, “이전/새로운” 뷰 전환 캡처 쌍을 나타냅니다. 이 의사 요소는 해당 ::view-transition-group() 의사 요소의 자식으로 생성되며, ::view-transition-old() 의사 요소 및/또는 ::view-transition-new() 의사 요소를 (순서대로) 포함합니다.
3.2.5. 뷰 전환 이전 상태 이미지: ::view-transition-old() 의사 요소
::view-transition-old() 의사 요소는 “이전” 상태의 시각적 스냅샷을 대체 요소로 나타내는 비어 있는 이름 있는 뷰 전환 의사 요소입니다. 나타낼 “이전” 상태가 없으면 생략됩니다. 각 ::view-transition-old() 의사 요소는 해당 ::view-transition-image-pair() 의사 요소의 자식입니다.
이 요소의 외형은 다른 대체 요소와 마찬가지로 object-*
속성으로 조작할 수 있습니다.
참고: 이미지의 콘텐츠와 고유 크기(natural dimensions)는 이미지 캡처 단계에서 캡처되며, 전환 의사 요소 설정 단계에서 설정됩니다.
참고: 이 의사 요소에 애니메이션을 추가하는 동적 뷰 전환 스타일시트의 추가 스타일은 전환 의사 요소 설정 및 의사 요소 스타일 업데이트에 자세히 설명되어 있습니다.
3.2.6. 뷰 전환 신규 상태 이미지: ::view-transition-new() 의사 요소
::view-transition-new() 의사 요소는 (유사한 ::view-transition-old() 의사 요소와 같이) “신규” 상태의 시각적 스냅샷을 대체 요소로 나타내는 비어 있는 이름 있는 뷰 전환 의사 요소입니다. 나타낼 “신규” 상태가 없으면 생략됩니다. 각 ::view-transition-new() 의사 요소는 해당 ::view-transition-image-pair() 의사 요소의 자식입니다.
참고: 이미지의 콘텐츠와 고유 크기(natural dimensions)는 이미지 캡처 단계에서 캡처되며, 전환 의사 요소 설정 및 의사 요소 스타일 업데이트에서 설정 및 갱신됩니다.
4. 뷰 전환 레이아웃
뷰 전환 의사 요소는 일반 요소와 같이 스타일링, 레이아웃 및 렌더링되지만, 스냅샷 포함 블록에서 시작되고 초기 포함 블록에서 시작하지 않으며, 문서의 나머지 위에 뷰 전환 레이어에 페인팅됩니다.
4.1. 스냅샷 포함 블록
스냅샷 포함 블록은 창에서 페이지 콘텐츠가 표시될 수 있는 모든 영역을 덮는 사각형이며 (따라서 루트 스크롤바나 인터랙티브 위젯과 관계없이 일관적입니다). 이는 문서 요소의 이전 이미지와 새로운 요소에 대해 일관성을 높여줍니다.
iframe의 경우 스냅샷 포함 블록은 해당 초기 포함 블록에 해당합니다.
스냅샷 포함 블록 원점은 스냅샷 포함 블록의 왼쪽 위 모서리를 의미합니다.
스냅샷 포함 블록 크기는 스냅샷 포함 블록의 너비와 높이를 튜플(tuple)로 나타냅니다.
스냅샷 포함 블록은 절대 위치 포함 블록이자 고정 위치 포함 블록으로 간주되며, ::view-transition 및 그 하위 요소들에 적용됩니다.
4.2. 뷰 전환 페인팅 순서
이 명세는 뷰 전환 레이어라는 새로운 스태킹 레이어를 CSS2§E Elaborate Description of Stacking Contexts에서 정의된 페인팅 순서의 끝에 추가합니다. [CSS2]
::view-transition 의사 요소는 뷰 전환 레이어라는 새로운 스태킹 컨텍스트를 생성하며, 이 레이어는 문서의 다른 모든 콘텐츠(상단 레이어 포함) 이후에 페인팅되고, 해당 콘텐츠에 적용된 필터와 효과 이후에 렌더링됩니다. (뷰 전환 레이어는 이러한 필터 및 효과의 적용 대상이 아니지만, ::view-transition-old() 및 ::view-transition-new() 의사 요소의 렌더링된 내용에는 영향을 줄 수 있습니다.)
참고: 이 기능의 목적은 페이지의 콘텐츠(상단 레이어 포함)를 캡처할 수 있도록 하는 것입니다. 이를 위해 뷰 전환 레이어는 캡처된 스태킹 컨텍스트의 일부가 될 수 없습니다. 그렇지 않으면 순환 의존성이 생기기 때문입니다. 따라서 뷰 전환 레이어는 모든 다른 콘텐츠의 형제(sibling)입니다.
Document
의
활성 뷰
전환의 단계가
"animating
"일 때,
해당 Document
내에서 뷰
전환에서 캡처된 모든 요소와 그 요소 내용이,
전환 루트 의사 요소의 포함 자손을 제외하고,
페인팅되지 않으며(visibility:
hidden과 같이),
히트 테스트에도 응답하지 않습니다(pointer-events: none과 같이).
참고: 전환에 참여하는 요소는 DOM 위치에서 페인팅을 건너뛰어야 합니다. 해당 이미지가 ::view-transition-new() 의사 요소에서 페인팅되기 때문입니다. 마찬가지로, 히트 테스트도 건너뛰어야 하는데, 요소의 DOM 위치가 콘텐츠가 렌더링되는 위치와 일치하지 않기 때문입니다. 단, 이러한 요소에 대한 접근성 기술이나 접근성 트리 접근 방식에는 변화가 없습니다.
5. 사용자 에이전트 스타일시트
글로벌 뷰 전환 사용자 에이전트 스타일시트는 다음 규칙을 포함하는 사용자 에이전트 출처 스타일시트입니다:
:root{ view-transition-name : root; } :root::view-transition{ position : fixed; inset : 0 ; } :root::view-transition-group ( *) { position : absolute; top : 0 ; left : 0 ; animation-duration : 0.25 s ; animation-fill-mode : both; } :root::view-transition-image-pair ( *) { position : absolute; inset : 0 ; animation-duration : inherit; animation-fill-mode : inherit; animation-delay : inherit; } :root::view-transition-old ( *), :root::view-transition-new ( *) { position : absolute; inset-block-start : 0 ; inline-size : 100 % ; block-size : auto; animation-duration : inherit; animation-fill-mode : inherit; animation-delay : inherit; } /* 기본 크로스 페이드 전환 */ @keyframes -ua-view-transition-fade-out{ to{ opacity : 0 ; } } @keyframes -ua-view-transition-fade-in{ from{ opacity : 0 ; } } /* 이미지가 2개일 때 블렌딩을 위한 키프레임 */ @keyframes -ua-mix-blend-mode-plus-lighter{ from{ mix-blend-mode : plus-lighter} to{ mix-blend-mode : plus-lighter} }
설명 요약
이 UA 스타일시트는 여러 작업을 수행합니다:-
::view-transition을 스냅샷 포함 블록 전체를 덮도록 레이아웃하여 각 :view-transition-group() 자식이 그에 상대적으로 배치될 수 있도록 합니다.
-
::view-transition-image-pair() 의사 요소에서 레이아웃 간섭을 줄여, 저자가 ::view-transition-old() 및 ::view-transition-new()를 대부분의 경우 ::view-transition-group()의 직접 자식처럼 다룰 수 있도록 합니다.
-
트리 전체에 애니메이션 타이밍을 상속시켜, 기본적으로 ::view-transition-group()에 설정된 애니메이션 타이밍이 모든 하위 요소에 적용되도록 합니다.
-
요소 캡처 ::view-transition-old()와 ::view-transition-new()의 크기와 위치가 ::view-transition-group()에 설정된 크기와 위치와(가능한 한 비율을 깨뜨리지 않고) 일치하도록 스타일링합니다. 이러한 요소의 크기 지정은 논리 좌표와 물리 좌표의 매핑에 따라 다르기 때문에, 동적 뷰 전환 스타일시트가 DOM 요소에서 관련 스타일을 복사합니다.
-
각 ::view-transition-group()에 기본 0.25초 크로스 페이드 애니메이션을 설정합니다.
추가 스타일은 사용자 에이전트 출처에 뷰 전환 중 동적 뷰 전환 스타일시트를 통해 동적으로 추가됩니다.
6. API
6.1. Document
에
대한 추가 사항
partial interface Document {ViewTransition startViewTransition (optional UpdateCallback ); };
updateCallback callback =
UpdateCallback Promise <any > ();
-
viewTransition
=document
.startViewTransition
(updateCallback
) -
새로운 뷰 전환을 시작합니다(이미
document
에 활성 뷰 전환이 있다면 취소됨).updateCallback
이 제공되면, 현재 문서 상태가 캡처된 후 비동기적으로 호출됩니다. 그리고updateCallback
에서 반환된 promise가 완료되면, 문서의 새로운 상태가 캡처되고 전환이 시작됩니다.updateCallback
은 항상 호출되며, 전환이 불가능한 경우(예: 중복된view-transition-name
값 등)에도 마찬가지입니다. 전환은 상태 변화의 향상(enhancement)이므로, 전환 생성 실패가 상태 변화를 막지는 않습니다. 이에 대한 자세한 내용은 § 1.4 향상 기능으로서의 전환을 참고하세요.updateCallback
에서 반환된 promise가 reject되면, 전환은 건너뜁니다.
6.1.1. startViewTransition()
메서드 단계
startViewTransition(updateCallback)
의 메서드 단계는
다음과 같습니다:
-
transition을 this의 관련 Realm에서 새로운
ViewTransition
객체로 만든다. -
updateCallback이 제공된 경우, transition의 update callback을 updateCallback으로 설정한다.
-
document를 this의 관련 글로벌 객체의 연관된 document로 한다.
-
document의 visibility state가 "
hidden
"이면, skip transition을 "InvalidStateError
"DOMException
과 함께, 반환하고 transition을 리턴한다. -
document의 활성 뷰 전환이 null이 아니라면, 그 뷰 전환을 건너뛴다("
AbortError
"DOMException
this의 관련 Realm에서).참고: 이렇게 하면 두 개의 비동기 update callback이 동시에 실행될 수 있습니다 (따라서 순서가 뒤섞일 수도 있음): 하나는 document의 현재 활성 뷰 전환용, 또 하나는 이번 transition용입니다. 이 기능의 설계에 따라, 개발자가 이러한 DOM 변경을 올바르게 스케줄링하기 위해 다른 기능 또는 프레임워크를 사용한다고 가정합니다.
-
document의 활성 뷰 전환을 transition으로 설정한다.
참고: 뷰 전환 처리는 뷰 전환 설정에서, 보류 중인 전환 작업 수행을 통해 계속됩니다.
-
transition을 반환한다.
6.2. ViewTransition
인터페이스
[Exposed =Window ]interface {
ViewTransition readonly attribute Promise <undefined >;
updateCallbackDone readonly attribute Promise <undefined >;
ready readonly attribute Promise <undefined >;
finished undefined skipTransition (); };
ViewTransition
인터페이스는 단일 동일 문서 뷰 전환을 나타내며
제어합니다.
즉, 시작과 끝 문서가 동일하지만, 문서의 DOM 구조가 변경될 수 있는 전환입니다.
-
viewTransition
.updateCallbackDone
-
updateCallback
에서 반환한 promise가 완료되면 fulfill되고, reject되면 reject되는 promise입니다.참고: View Transition API는 DOM 변경을 감싸고 시각적 전환을 생성합니다. 하지만 때때로 전환 애니메이션의 성공/실패가 아니라 DOM 변경이 언제/어떻게 발생하는지만 알고 싶은 경우가 있습니다.
updateCallbackDone
은 그런 용도입니다. -
viewTransition
.ready
-
전환을 위한 의사 요소가 생성되고 애니메이션이 시작될 준비가 되었을 때 fulfill되는 promise입니다.
전환을 시작할 수 없는 경우 reject됩니다. 이는 잘못된 설정(예: 중복된 'view-transition-name')이나
updateCallbackDone
에서 reject된 promise 등일 수 있습니다.ready
가 fulfill되는 시점은 뷰 전환 의사 요소에 Web Animation API로 애니메이션을 적용할 수 있는 이상적인 기회입니다. -
viewTransition
.finished
-
최종 상태가 사용자에게 완전히 보이고 상호작용 가능해지면 fulfill되는 promise입니다.
오직
updateCallback
에서 반환된 promise가 reject된 경우에만 reject됩니다. 이는 최종 상태가 생성되지 않았음을 나타냅니다.그 외에 전환 시작 실패나
skipTransition()
으로 건너뛴 경우에도, 최종 상태에는 도달하므로finished
는 fulfill됩니다. -
viewTransition
.skipTransition
() -
전환을 즉시 완료하거나 시작을 방지합니다.
이것은
updateCallback
이 호출되는 것을 절대 막지 않습니다. DOM 변경은 전환과 독립적이기 때문입니다. 자세한 내용은 § 1.4 향상 기능으로서의 전환을 참고하세요.ready
가 resolve되기 전에 호출하면ready
는 reject됩니다.finished
가 아직 resolve되지 않았다면,updateCallbackDone
과 함께 fulfill 또는 reject됩니다.
ViewTransition
은
다음을 가집니다:
- named elements
-
map으로, 키는 view transition name이고 값은 캡처된 요소입니다. 최초에는 새로운 map입니다. 참고: 이는
ViewTransition
에 연결되어 있으므로, 뷰 전환 초기화가 호출될 때 정리됩니다. - phase
-
다음 순서의 단계 중 하나이며, 최초에는 "
pending-capture
":-
"
pending-capture
". -
"
update-callback-called
". -
"
animating
". -
"
done
".
참고: 이 API를 사용하는 개발자는 대부분의 경우 각 단계에 대해 신경 쓰지 않아도 됩니다. 단계는 자동으로 진행됩니다. 다만 각 단계에서 어떤 단계가 발생하는지(스냅샷 캡처, 의사 요소 DOM 생성 등)는 이해하는 것이 중요합니다. 아래 단계 설명은 구현자가 명세에 부합하는 구현을 할 수 있도록 최대한 명확한 절차를 제시하려는 목적입니다.
-
- update callback
-
UpdateCallback
또는 null. 최초에는 null. - ready promise
-
Promise
. 최초에는 새로운 promise이며, this의 관련 Realm에서 생성됩니다. - update callback done promise
-
Promise
. 최초에는 새로운 promise이며, this의 관련 Realm에서 생성됩니다.참고: ready promise와 update callback done promise는 즉시 생성되므로, reject되면
unhandledrejection
이 발생할 수 있습니다. 만약 getter(예:updateCallbackDone
)가 접근되지 않아도 마찬가지입니다. - finished promise
-
Promise
. 최초에는 새로운 promise이며, this의 관련 Realm에서 handled로 표시됩니다.참고: 이 promise는 handled로 표시되어 중복
unhandledrejection
을 방지하며, 이 promise는 오직 update callback done promise와 함께 reject됩니다. - transition root pseudo-element
-
::view-transition. 최초에는 새로운 ::view-transition입니다.
- initial snapshot containing block size
-
두 숫자(너비, 높이)로 이루어진 tuple 또는 null. 최초에는 null.
참고: 이는 스냅샷 포함 블록 크기 변화를 감지하는 데 사용됩니다. 변화가 있으면 전환을 skip합니다. 이 동작에 대한 논의 참고.
finished
의
getter
단계는 this의 finished promise를 반환하는 것입니다.
ready
의
getter
단계는 this의 ready
promise를 반환하는 것입니다.
updateCallbackDone
의
getter
단계는 this의 update callback done promise를 반환하는 것입니다.
6.2.1.
skipTransition()
메서드 단계
skipTransition()
의 메서드 단계는 다음과 같습니다:
-
this의 phase가 "
done
"이 아니라면, 뷰 전환을 건너뛴다(this에 대해 "AbortError
"DOMException
과 함께).
7. 알고리즘
7.1. 데이터 구조
7.1.1. Document
에
대한 추가 사항
Document
는 추가적으로 다음을 가집니다:
- active view transition
-
ViewTransition
또는 null. 최초에는 null. - 뷰 전환 렌더링 억제(rendering suppression for view transitions)
-
boolean. 최초에는 false.
Document
의 뷰 전환 렌더링 억제가 true인 동안, 모든 포인터 히트 테스트는 문서 요소(document element)만을 대상으로 하며, 다른 요소는 무시됩니다.참고: 이는 포인터 캡처된 포인터에는 영향을 주지 않습니다.
- 동적 뷰 전환 스타일시트(dynamic view transition style sheet)
-
스타일시트(style sheet). 최초에는 사용자 에이전트 출처에 새로운 스타일시트로, 글로벌 뷰 전환 사용자 에이전트 스타일시트 뒤에 배치됩니다.
참고: 이는 전환과 관련된 동적 스타일을 보관하는 용도로 사용됩니다.
- show view transition tree
-
boolean. 최초에는 false.
이 값이 true일 때, this의 active view transition의 transition root pseudo-element가 this의 문서 요소(document element)의 자식으로 렌더링되며, this의 문서 요소(document element)가 기원 요소(originating element)가 됩니다.
참고: transition root pseudo-element의 문서 요소 내 위치는 중요하지 않습니다. transition root pseudo-element의 포함 블록은 스냅샷 포함 블록이기 때문입니다.
7.1.2. 요소에 대한 추가 사항
요소는 뷰 전환에서 캡처됨(captured in a view transition)이라는 boolean을 갖습니다. 최초에는 false.
참고: 이 명세는 요소의 CSS 정의를 사용하며, 여기에는 의사 요소도 포함됩니다.
7.1.3. 캡처된 요소
캡처된 요소(captured element)는 다음을 포함하는 구조체(struct)입니다:
- old image
-
2D 비트맵 또는 null. 최초에는 null.
- old width
- old height
-
unrestricted double
, 최초에는 0. - old transform
- old writing-mode
-
Null 또는 writing-mode, 최초에는 null.
- old direction
-
Null 또는 direction, 최초에는 null.
- old text-orientation
-
Null 또는 text-orientation, 최초에는 null.
- old mix-blend-mode
-
Null 또는 mix-blend-mode, 최초에는 null.
- old backdrop-filter
-
Null 또는 backdrop-filter, 최초에는 null.
- old color-scheme
-
Null 또는 color-scheme, 최초에는 null.
- new element
-
요소 또는 null. 최초에는 null.
또한, 캡처된 요소는 다음 스타일 정의(style definitions)를 가집니다:
- group keyframes
-
CSSKeyframesRule
또는 null. 최초에는 null. - group animation name rule
-
CSSStyleRule
또는 null. 최초에는 null. - group styles rule
-
CSSStyleRule
또는 null. 최초에는 null. - image pair isolation rule
-
CSSStyleRule
또는 null. 최초에는 null. - image animation name rule
-
CSSStyleRule
또는 null. 최초에는 null.
참고: 이는 문서(document)의 동적 뷰 전환 스타일시트에서 스타일을 업데이트하고 나중에 제거할 때 사용됩니다.
7.2. 보류 중인 전환 작업 수행
보류 중인 전환
작업 수행(perform pending transition operations)을 Document
document에 대해 실행할 때, 다음 단계를 수행합니다:
-
document의 active view transition이 null이 아니면:
-
document의 active view transition의 phase가 "
pending-capture
"라면, 뷰 전환 설정(setup view transition)을 document의 active view transition에 대해 실행합니다. -
그 외에 document의 active view transition의 phase가 "
animating
"이라면, transition frame 처리(handle transition frame)를 document의 active view transition에 대해 실행합니다.
-
7.3. 뷰 전환 설정
ViewTransition
transition에 대해 실행하려면,
다음 단계를 수행합니다:
참고: 이 알고리즘은 문서의 현재 상태를 캡처하고,
전환의 UpdateCallback
를
호출한 뒤,
문서의 새로운 상태를 캡처합니다.
-
document를 transition의 관련 글로벌 객체의 연관된 document로 한다.
-
이전 상태 캡처를 transition에 대해 실행한다.
실패가 반환되면, 뷰 전환 건너뛰기를 transition에 대해 "
InvalidStateError
"DOMException
(in transition의 관련 Realm)로 실행하고 반환한다. -
document의 뷰 전환 렌더링 억제를 true로 설정한다.
-
글로벌 태스크 큐를 DOM 조작 태스크 소스에, transition의 관련 글로벌 객체를 넘겨서 다음 단계를 실행하도록 큐잉한다:
참고: 이미지 캡처에서 텍스처 읽기가 비동기일 수 있으므로 태스크를 큐잉합니다. HTML 명세의 렌더 단계는 동기처럼 동작합니다.
ViewTransition
transition에 대해 실행하려면,
다음 단계를 수행합니다:
-
transition의 phase가 "
done
"이면 반환.참고: transition이 이 시점 전에 건너뛰기 되었을 때 발생.
-
뷰 전환 렌더링 억제를 false로 설정한다.
-
transition의 초기 스냅샷 포함 블록 크기가 스냅샷 포함 블록 크기와 다르면, 뷰 전환 건너뛰기를 transition에 대해 실행하고 반환.
-
신규 상태 캡처를 transition에 대해 실행한다.
실패가 반환되면 뷰 전환 건너뛰기를 transition에 대해 "
InvalidStateError
"DOMException
(transition의 관련 Realm)로 실행하고 반환. -
resolve transition의 update callback done promise를 undefined로.
-
각 capturedElement를 transition의 named elements의 values에서 반복:
-
capturedElement의 new element가 null이 아니면, capturedElement의 new element의 뷰 전환에서 캡처됨을 true로 설정한다.
-
-
전환 의사 요소 설정을 transition에 대해 실행한다.
-
의사 요소 스타일 업데이트를 transition에 대해 실행한다.
실패가 반환되면 뷰 전환 건너뛰기를 transition에 대해 "
InvalidStateError
"DOMException
(transition의 관련 Realm)로 실행하고 반환.참고: 위 단계에서는 스타일/레이아웃 중 계산된 정보를 얻기 위해 문서 라이프사이클 단계를 실행해야 할 수도 있습니다.
-
transition의 phase를 "
animating
"으로 설정한다. -
resolve transition의 ready promise를 실행한다.
7.3.1. 이전 상태 캡처
ViewTransition
transition에 대해 실행하려면:
-
document를 transition의 관련 글로벌 객체의 연관된 document로 한다.
-
namedElements를 transition의 named elements로 한다.
-
usedTransitionNames를 새로운 문자열 set으로 한다.
-
captureElements를 새로운 요소 리스트(list)로 한다.
-
document를 transition의 관련 글로벌 객체의 연관된 document로 한다.
-
스냅샷 포함 블록 크기가 구현 정의 최대치를 초과하면 실패 반환.
-
transition의 초기 스냅샷 포함 블록 크기를 스냅샷 포함 블록 크기로 설정한다.
-
각 element를 모든 요소 중 connected이고, node document가 document와 동일한 경우, 페인트 순서로 반복:
페인트 순서로 반복하는 것은 namedElements에 이 순서를 캐시하기 위함입니다. 이것은 ::view-transition-group 의사 요소의 DOM 순서를 정의하며, 페인트 스택 맨 아래 요소가 ::view-transition의 첫 번째 의사 자식이 되도록 합니다.-
이 element의 flat tree 상위 요소 중 하나라도 내용 건너뜀(skips its contents)이면 continue.
-
element가 box fragment를 2개 이상 가지면, continue.
참고: 향후 버전에서는 분절된 요소에 대한 전환을 지원할 수도 있습니다. #8900 참고.
참고: 여기서 언급하는 box fragment는 inline box가 line box로 분할되는 것은 아닙니다. 그런 인라인들은 전환에 참여할 수 있습니다.
-
transitionName을 element의 계산값 view-transition-name으로 한다.
-
transitionName이 none이거나, element가 렌더링되지 않은 경우이면, continue.
-
usedTransitionNames에 포함된 transitionName이 있으면 실패 반환.
-
Append transitionName을 usedTransitionNames에 추가.
-
element의 뷰 전환에서 캡처됨을 true로 설정.
-
Append element를 captureElements에 추가.
이 알고리즘은 별도의 루프로 계속되어, 뷰 전환에서 캡처됨이 이 캡처에 참여하는 모든 요소에 설정된 뒤, 알고리즘의 후속 단계에서 읽히도록 보장합니다. -
-
각 element를 captureElements에서 반복:
-
capture를 새로운 캡처된 요소 구조체로 한다.
-
originalRect를 element가 문서 요소라면 스냅샷 포함 블록으로, 아니면 요소의 border box로 한다.
-
capture의 old height를 originalRect의
height
로 설정. -
capture의 old transform을 <transform-function> 값으로 설정(스냅샷 포함 블록 원점에서 현재 시각적 위치로 border box를 매핑함).
-
capture의 old writing-mode를 element의 계산값 writing-mode로 설정.
-
capture의 old direction을 element의 계산값 direction로 설정.
-
capture의 old text-orientation을 element의 계산값 text-orientation로 설정.
-
capture의 old mix-blend-mode를 element의 계산값 mix-blend-mode로 설정.
-
capture의 old backdrop-filter를 element의 계산값 backdrop-filter로 설정.
-
capture의 old color-scheme를 element의 계산값 color-scheme로 설정.
-
transitionName을 element의 계산값 view-transition-name로 한다.
-
namedElements[transitionName] = capture로 설정.
-
-
각 element를 captureElements에서 반복:
-
element의 뷰 전환에서 캡처됨을 false로 설정.
-
7.3.2. 신규 상태 캡처
ViewTransition
transition에 대해 실행하려면:
-
document를 transition의 관련 글로벌 객체의 연관된 document로 한다.
-
namedElements를 transition의 named elements로 한다.
-
usedTransitionNames를 새로운 문자열 set로 한다.
-
각 element를 모든 요소 중 connected이고, node document가 document와 동일한 경우, 페인트 순서로 반복:
-
이 element의 flat tree 상위 요소 중 하나라도 내용 건너뜀(skips its contents)이면 continue.
-
transitionName을 element의 계산값 view-transition-name으로 한다.
-
transitionName이 none이거나, element가 렌더링되지 않은 경우이면, continue.
-
usedTransitionNames에 포함된 transitionName이 있으면 실패 반환.
-
Append transitionName을 usedTransitionNames에 추가.
-
namedElements[transitionName]이 존재하지 않으면, namedElements[transitionName]에 새로운 캡처된 요소 구조체를 추가.
참고: 일부러 이 구조체를 정렬된 맵의 끝에 추가합니다. 즉, 새로운 DOM에만 존재하는 이름(등장 애니메이션)이 이전 DOM에만 있는 이름(퇴장 애니메이션) 및 둘 다 있는 이름(페어 애니메이션) 위에 페인팅됩니다. 모든 경우에 올바른 레이어링이 아닐 수도 있습니다. issue 8941 참고.
-
namedElements[transitionName]의 new element를 element로 설정.
-
7.3.3. 전환 의사 요소 설정
ViewTransition
transition에 대해 실행하려면:
참고: 이 알고리즘은 전환을 위한 의사 요소 트리를 생성하며, 초기 스타일을 생성합니다. 의사 트리 구조는 § 3.2 뷰 전환 의사 요소에 자세히 설명되어 있습니다.
-
document를 this의 관련 글로벌 객체의 연관된 document로 한다.
-
document의 show view transition tree를 true로 설정.
-
각 transitionName → capturedElement를 transition의 named elements에서 반복:
-
group을 새로운 ::view-transition-group()으로 생성, view transition name을 transitionName으로 설정.
-
group을 transition의 transition root pseudo-element에 추가.
-
imagePair를 새로운 ::view-transition-image-pair()로 생성, view transition name을 transitionName으로 설정.
-
imagePair를 group에 추가.
-
capturedElement의 old image가 null이 아니면:
-
old를 새로운 ::view-transition-old()로 생성, view transition name을 transitionName으로 설정, capturedElement의 old image를 대체(replaced) 콘텐츠로 표시.
-
old를 imagePair에 추가.
-
-
capturedElement의 new element가 null이 아니면:
-
new를 새로운 ::view-transition-new()로 생성, view transition name을 transitionName으로 설정.
참고: 이 의사 요소의 스타일링은 의사 요소 스타일 업데이트에서 처리됩니다.
-
new를 imagePair에 추가.
-
-
capturedElement의 old image가 null이면:
-
Assert: capturedElement의 new element가 null이 아님.
-
capturedElement의 image animation name rule을 새로운
CSSStyleRule
로 생성, 아래 CSS를 표현하고, document의 동적 뷰 전환 스타일시트에 추가::root:
:view-transition-new ( transitionName) { animation-name : -ua-view-transition-fade-in; } 참고: 위 코드 예시는 변수 치환이 필요합니다.
-
-
capturedElement의 new element가 null이면:
-
capturedElement의 image animation name rule을 새로운
CSSStyleRule
로 생성, 아래 CSS를 표현하고, document의 동적 뷰 전환 스타일시트에 추가::root:
:view-transition-old ( transitionName) { animation-name : -ua-view-transition-fade-out; } 참고: 위 코드 예시는 변수 치환이 필요합니다.
-
capturedElement의 old image와 new element가 모두 null이 아니면:
-
transform을 capturedElement의 old transform으로 한다.
-
width를 capturedElement의 old width로 한다.
-
height를 capturedElement의 old height로 한다.
-
backdropFilter를 capturedElement의 old backdrop-filter로 한다.
-
capturedElement의 group keyframes를 새로운
CSSKeyframesRule
로 생성, 아래 CSS를 표현하고, document의 동적 뷰 전환 스타일시트에 추가:@keyframes -ua-view-transition-group-anim-transitionName{ from{ transform : transform; width : width; height : height; backdrop-filter : backdropFilter; } } 참고: 위 코드 예시는 변수 치환이 필요합니다.
-
capturedElement의 group animation name rule을 새로운
CSSStyleRule
로 생성, 아래 CSS를 표현하고, document의 동적 뷰 전환 스타일시트에 추가::root:
:view-transition-group ( transitionName) { animation-name : -ua-view-transition-group-anim-transitionName; } 참고: 위 코드 예시는 변수 치환이 필요합니다.
-
capturedElement의 image pair isolation rule을 새로운
CSSStyleRule
로 생성, 아래 CSS를 표현하고, document의 동적 뷰 전환 스타일시트에 추가::root:
:view-transition-image-pair ( transitionName) { isolation : isolate; } 참고: 위 코드 예시는 변수 치환이 필요합니다.
-
capturedElement의 image animation name rule을 새로운
CSSStyleRule
로 생성, 아래 CSS를 표현하고, document의 동적 뷰 전환 스타일시트에 추가::root:
:view-transition-old ( transitionName) { animation-name : -ua-view-transition-fade-out, -ua-mix-blend-mode-plus-lighter; } :root::view-transition-new ( transitionName) { animation-name : -ua-view-transition-fade-in, -ua-mix-blend-mode-plus-lighter; } 참고: 위 코드 예시는 변수 치환이 필요합니다.
참고: mix-blend-mode: plus-lighter는 old/new 이미지의 동일 픽셀 블렌딩 시 동일한 색상값이 결과로 나오고, “정확한” 크로스 페이드를 달성합니다.
-
-
7.4. update callback 호출
ViewTransition
transition에 대해 실행하려면:
참고: 이 단계는 모든 ViewTransition
에
대해 반드시 실행됩니다,
전환이 건너뛰기(skipped)되어도 마찬가지입니다.
그 이유는 § 1.4 향상 기능으로서의 전환에서 설명됩니다.
-
Assert: transition의 phase가 "
done
" 또는 "update-callback-called
" 이전임을 확인. -
callbackPromise를 null로 한다.
-
transition의 update callback이 null이면, callbackPromise를 undefined로 resolve된 promise로 설정, transition의 관련 Realm에서 실행.
-
그 외에는 callbackPromise를 callback 함수 호출의 결과로 설정.
-
transition의 phase가 "
done
"이 아니면, transition의 phase를 "update-callback-called
"로 설정. -
fulfillSteps를 다음 단계로 정의:
-
뷰 전환 활성화를 transition에 대해 실행.
-
resolve transition의 update callback done promise를 undefined로.
참고: 이전 단계에서 이미 promise가 resolve되었다면 이 단계는 no-op입니다.
-
-
rejectSteps를 reason을 인자로 다음 단계로 정의:
-
reject transition의 update callback done promise를 reason으로.
-
transition의 phase가 "
done
"이면 반환.참고: transition이 이 시점 전에 건너뛰기 되었을 때 발생.
-
handled로 표시 transition의 ready promise를.
참고: transition의 update callback done promise가
unhandledrejection
을 제공합니다. 중복을 방지하는 단계입니다. -
뷰 전환 건너뛰기를 transition에 reason과 함께 실행.
-
-
promise settle 후 단계 실행을 callbackPromise에 대해 fulfillSteps와 rejectSteps로 등록.
-
타임아웃 후 전환을 건너뛰려면, 사용자 에이전트는 아래 단계를 병렬로 실행할 수 있다:
-
구현 정의 지속 시간만큼 대기.
-
글로벌 태스크 큐를 DOM 조작 태스크 소스에, transition의 관련 글로벌 객체를 넘겨서 다음 단계를 실행하도록 큐잉:
-
transition의 phase가 "
done
"이면 반환.참고: transition 이 시점 전에 건너뛰기 되었을 때 발생.
-
뷰 전환 건너뛰기를 transition에 "
TimeoutError
"DOMException
과 함께 실행.
-
-
7.5. 뷰 전환 건너뛰기
ViewTransition
transition에 대해 reason과 함께 실행하려면:
-
document를 transition의 관련 글로벌 객체의 연관된 document로 한다.
-
transition의 phase가 "
update-callback-called
" 이전이면, 글로벌 태스크 큐를 DOM 조작 태스크 소스에, transition의 관련 글로벌 객체를 넘겨서 update callback 호출을 실행. -
뷰 전환 렌더링 억제를 false로 설정.
-
document의 active view transition이 transition이면, 뷰 전환 초기화를 transition에 대해 실행.
-
transition의 phase를 "
done
"으로 설정. -
reject transition의 ready promise를 reason으로 처리.
참고: ready promise가 이 시점에서 이미 resolve되어 있을 수 있음.
skipTransition()
이 애니메이션 시작 후 호출된 경우, 이 단계는 no-op. -
resolve transition의 finished promise를 update callback done promise settle 후 처리 결과로:
-
promise가 fulfill되면 undefined 반환.
참고: transition의 update callback done promise가 여기서 명시적으로 처리되지 않으므로, transition의 update callback done promise가 reject되면, transition의 finished promise도 같은 이유로 reject됨.
-
7.6. 뷰 전환 page-visibility 변경 단계
Document
document에 대해 다음과 같이 동작한다:
-
document의 visibility state가 "
hidden
"이면:-
document의 active view transition이 null이 아니면, 뷰 전환 건너뛰기를 document의 active view transition에 "
InvalidStateError
"DOMException
과 함께 실행.
-
-
그 외에는 assert: active view transition이 null이어야 함.
참고: 이 단계는 HTML 명세에서 호출됨.
7.7. 이미지 캡처
-
element가 문서 요소라면:
-
문서의 영역을 렌더링한다 (캔버스 배경 및 상단 레이어 콘텐츠 포함) 스냅샷 포함 블록과 교차되는 부분을 스냅샷 포함 블록 크기의 투명 캔버스에 렌더링하며, 캡처 렌더링 특성과 다음 추가 특성을 따른다:
-
element의 스크롤 박스 바깥 영역은 스크롤된 것처럼 렌더링하지만 레이아웃 뷰포트를 실제로 이동하거나 크기 변경하지 않는다. 이로 인해
IntersectionObserver
등 스크롤/리사이즈 관련 이벤트가 발생하면 안 됨.사용자가 보는 화면과 캡처된 스냅샷의 예시. 이 예시에서는 루트가 유일하게 전환 이름을 갖는 요소임을 가정. -
스크롤할 수 없는 영역(범위를 벗어난 경우)은 캔버스 배경을 렌더링한다.
사용자가 보는 화면과 캡처된 스냅샷의 예시. 이 예시에서는 루트가 유일하게 전환 이름을 갖는 요소임을 가정.
-
-
이 캔버스를 이미지로 반환. 이미지의 자연 크기는 스냅샷 포함 블록과 동일.
-
-
그 외에는:
-
element 및 그 자손을 element가 node document에서 보이는 크기와 동일하게 무한 투명 캔버스에 렌더링하며, 캡처 렌더링 특성을 따른다.
-
이 캔버스에서 element의 잉크 오버플로우 사각형을 포함하는 부분을 이미지로 반환한다. 이 이미지의 자연 크기는 해당 principal border box와 동일하며, 원점은 border box의 원점과 일치해야 하며, 이미지는 border box의 내용과 캡처된 잉크 오버플로우가 이 경계 바깥에 표시됨을 의미.
참고: 이 이미지가 대체 요소로 자연 크기로 렌더링되면, 요소의 principal box의 크기와 내용이 표시되고, 캡처된 잉크 오버플로우는 content box 바깥에 넘쳐 보임.
-
7.7.1. 캡처 렌더링 특성
-
참조된 요소에 transform이 적용되어 있으면(혹은 상위에 적용된 경우) transform은 무시된다.
참고: 이 transform은 연관된 ::view-transition-group 의사 요소의
transform
속성으로 스냅샷에 적용됨. -
요소 및 자손에 적용된 효과(예: opacity 및 filter)는 캡처에 적용되며, 상위에서 요소에 적용된 효과는 무시된다.
-
구현체는 잉크 오버플로우 사각형이 구현 정의 최대치를 초과하면 렌더링 내용을 잘라낼 수 있다. 단, 캡처된 이미지는 최소한 스냅샷 포함 블록과 교차하는 element의 콘텐츠는 포함해야 한다. 구현체는 잉크 오버플로우 영역이 크고 변환된 경우 래스터화 품질을 조정할 수 있다.
-
각 descendant를 shadow-including descendant
Element
및 의사 요소로 반복, descendant가 뷰 전환에서 캡처됨이면 descendant의 페인팅을 건너뜀.참고: 이는 해당 자손이 자신의 스냅샷을 생성해 독립적으로 표시 및 애니메이션되기 때문.
7.8. 전환 프레임 처리
ViewTransition
transition에 대해 실행하려면:
-
document를 transition의 관련 글로벌 객체의 연관된 document로 한다.
-
hasActiveAnimations을 boolean, 최초에는 false로 한다.
-
각 element를 transition의 transition root pseudo-element의 포함 자손에서 반복:
-
animation들 중 timeline이 document timeline이고 document와 연결되어 있으며, associated effect 중 적어도 하나의 effect target이 element인 경우, 아래 조건 중 하나라도 true이면 hasActiveAnimations을 true로 설정:
-
animation의 play state가 paused 또는 running이다.
-
document의 pending animation event queue에 animation과 연결된 이벤트가 있다.
-
-
-
hasActiveAnimations이 false라면:
-
transition의 phase를 "
done
"으로 설정. -
뷰 전환 초기화를 transition에 대해 실행.
-
resolve transition의 finished promise.
-
반환.
-
-
transition의 초기 스냅샷 포함 블록 크기가 스냅샷 포함 블록 크기와 다르면, 뷰 전환 건너뛰기를 transition에 대해 실행하고 반환.
-
의사 요소 스타일 업데이트를 transition에 대해 실행.
실패가 반환되면 뷰 전환 건너뛰기를 transition에 대해 "
InvalidStateError
"DOMException
(transition의 관련 Realm)로 실행하고 반환.참고: 위 내용은 들어오는 요소의 크기나 위치가 변경되면 새로운 keyframe이 생성된다는 의미입니다. 이로 인해 시각적 점프가 발생할 수 있습니다. 부드럽게 retarget할 수도 있지만 복잡성을 정당화할 use-case가 없어 구현하지 않았습니다. 자세한 내용은 issue 7813 참고.
7.9. 의사 요소 스타일 업데이트
ViewTransition
transition에 대해 실행하려면:
-
각 transitionName → capturedElement를 transition의 named elements에서 반복:
-
width, height, transform, writingMode, direction, textOrientation, mixBlendMode, backdropFilter, colorScheme을 모두 null로 초기화한다.
-
capturedElement의 new element가 null이면:
-
width를 capturedElement의 old width로 설정.
-
height를 capturedElement의 old height로 설정.
-
transform을 capturedElement의 old transform으로 설정.
-
writingMode를 capturedElement의 old writing-mode로 설정.
-
direction을 capturedElement의 old direction으로 설정.
-
textOrientation을 capturedElement의 old text-orientation으로 설정.
-
mixBlendMode를 capturedElement의 old mix-blend-mode로 설정.
-
backdropFilter를 capturedElement의 old backdrop-filter로 설정.
-
colorScheme을 capturedElement의 old color-scheme로 설정.
-
-
그 외의 경우:
-
아래 조건 중 하나라도 true이면 실패 반환:
-
capturedElement의 new element의 flat tree 상위에 내용 건너뜀(skips its contents)이 있다.
-
capturedElement의 new element가 렌더링되지 않음.
-
capturedElement가 box fragment를 2개 이상 가짐.
참고: 다른 렌더링 제한 사항은 capturedElement의 new element가 뷰 전환에서 캡처됨인 것으로 보장됨.
-
-
width를 capturedElement의 new element의 현재 border box의 너비로 설정.
-
height를 capturedElement의 new element의 현재 border box의 높이로 설정.
-
transform을 capturedElement의 new element의 border box를 스냅샷 포함 블록 원점에서 현재 시각적 위치로 매핑하는 변환으로 설정.
-
writingMode를 capturedElement의 계산값 writing-mode로 설정(capturedElement의 new element 기준).
-
direction을 capturedElement의 계산값 direction으로 설정(capturedElement의 new element 기준).
-
textOrientation을 capturedElement의 계산값 text-orientation으로 설정(capturedElement의 new element 기준).
-
mixBlendMode를 capturedElement의 계산값 mix-blend-mode로 설정(capturedElement의 new element 기준).
-
backdropFilter를 capturedElement의 계산값 backdrop-filter로 설정(capturedElement의 new element 기준).
-
colorScheme을 capturedElement의 계산값 color-scheme로 설정(capturedElement의 new element 기준).
-
-
capturedElement의 group styles rule이 null이면, capturedElement의 group styles rule을 새로운
CSSStyleRule
로 생성, 아래 CSS를 표현하고, transition의 관련 글로벌 객체의 연관된 document의 동적 뷰 전환 스타일시트에 추가.그 외에는 capturedElement의 group styles rule을 아래 CSS와 일치하도록 갱신:
:root:
:view-transition-group ( transitionName) { width : width; height : height; transform : transform; writing-mode : writingMode; direction : direction; text-orientation : textOrientation; mix-blend-mode : mixBlendMode; backdrop-filter : backdropFilter; color-scheme : colorScheme; } 참고: 위 코드 예시는 변수 치환이 필요합니다.
-
capturedElement의 new element가 null이 아니면:
-
new를 ::view-transition-new()로 하고 view transition name을 transitionName으로 한다.
-
new의 대체 요소(replaced element) 콘텐츠를 capturedElement의 이미지 캡처 결과(대상: capturedElement의 new element)로 설정.
-
-
이 알고리즘은 사용자 에이전트 출처에서 웹 API를 통해 그 효과가 관찰될 수 있다면 반드시 실행되어야 함.
참고: 예시로
window.getComputedStyle(document.documentElement, "::view-transition")
같은 웹 API가 있음.
7.10. 뷰 전환 초기화
ViewTransition
transition에 대해 실행하려면:
-
document를 transition의 관련 글로벌 객체의 연관된 document로 한다.
-
assert: document의 active view transition이 transition이어야 한다.
-
각 capturedElement를 transition의 named elements의 values에서 반복:
-
capturedElement의 new element가 null이 아니면, capturedElement의 new element의 뷰 전환에서 캡처됨을 false로 설정.
-
각 style을 capturedElement의 style definitions에서 반복:
-
style이 null이 아니고, document의 동적 뷰 전환 스타일시트에 포함되어 있다면, style을 document의 동적 뷰 전환 스타일시트에서 제거한다.
-
-
-
document의 show view transition tree를 false로 설정.
-
document의 active view transition을 null로 설정.
개인정보 보호 고려사항
이 명세는 추가적인 개인정보 보호 고려사항을 도입하지 않습니다.
보안 고려사항
이미지 캡처 알고리즘으로 생성된 이미지는 교차 출처 데이터(문서에 교차 출처 리소스가 포함된 경우)나 방문한 링크와 같은 민감 정보를 포함할 수 있습니다. 구현체는 이 데이터가 문서에서 접근할 수 없도록 반드시 보장해야 합니다. 이 데이터에 대한 접근은 문서의 기본 렌더링에서도 이미 차단되어야 하므로, 이를 준수하는 것은 가능해야 합니다.
부록 A. 변경 내역
이 부록은 정보 제공용입니다.
2022-05-30 Working Draft에서의 변경 사항 (원문 보기)
-
크로스 페이드 중 plus-lighter 블렌딩을 추가하는 keyframe을 사용. 이슈 8924 참고.
-
mix-blend-mode를 ::view-transition-group에 복사하는 속성 목록에 추가. 이슈 8962 참고.
-
text-orientation을 ::view-transition-group에 복사하는 속성 목록에 추가. 이슈 8230 참고.
-
값을 읽기 전에 뷰 전환에서 캡처됨을 올바르게 설정하도록 old capture 알고리즘을 리팩터링.
-
startViewTransition()
파라미터를 non-nullable로 변경. 이슈 9460 참고. -
back-drop filter를 transform/size와 유사하게 애니메이션. 이슈 9358 참고.
-
DOM 요소에서
color-scheme
을 ::view-transition-group()으로 복사. 이슈 9276 참고. -
문서가 숨겨질 때 아웃바운드 크로스 문서 전환이 프로그래밍 뷰 전환에 앞서도록 자동 건너뛰기 전환을 노출. 이슈 9512 참고.
-
view-transition-name이 애니메이션 가능해야 하는 이유에 대해 설명을 추가.
-
view-transition-name: auto
는 잘못된 값이어야 함. 이슈 9639 참고. -
엔트리 애니메이션의 페인트 순서에 대한 설명 노트 추가. 이슈 9672 참고.
-
named elements가 어떻게 정리되는지 설명하는 노트 추가. 이슈 9669 참고.
-
알고리즘을 리팩터링하여 특히 updateCallbackDone의 타이밍을 명확하게 함. 이슈 9762 참고.
-
(::view-transition)-image-pair, -old, -new UA 스타일시트 규칙에 animation-delay inherit 추가. 이슈 9817 참고.
-
문서가 숨겨질 때 애니메이션을 자동 건너뛰도록 함. 이슈 9543 참고.
-
L1 명세를 깨끗하게 유지하기 위해 크로스 문서 뷰 전환 참조 제거. 이슈 9886 참고.
-
페이지가 숨겨질 때 활성 전환을 건너뛰는 알고리즘을 내보냄. 이슈 9543 참고.
2022-05-25 Working Draft에서의 변경 사항 (원문 보기)
-
::view-transition-new UA 스타일시트의 오타 수정. PR 참고.
2022-11-24 Working Draft에서의 변경 사항 (원문 보기)
-
렌더링이 억제될 때 포인터 이벤트는 documentElement로 처리. 이슈 7797 참고.
-
UA 스타일시트에서 html 관련 내용을 제거하여 SVG Document의 ViewTransitions 지원.
-
updateDOMCallback을
UpdateCallback
으로 이름 변경. 이슈 8144 참고. -
snapshot viewport를 스냅샷 포함 블록으로 이름 변경.
-
뷰포트 크기가 변경되면 전환을 건너뛰도록 함. 이슈 8045 참고.
-
:only-child 지원 추가. 이슈 8057 참고.
-
pseudo-element root 아래에 의사 요소 트리 개념 추가. 이슈 8113 참고.
-
전환을 건너뛰는 경우
UpdateCallback
이 자신의 태스크에서 호출됨(동기 아님). 이슈 7904 참고 -
이미지 캡처 시 최소한 뷰포트 내 부분 이미지는 캡처되어야 하며 필요시 다운스케일. 이슈 8561 참고.
-
캡처 이미지에 잉크 오버플로우를 적용하는 것은 구현 정의이며, 이미지의 자연 크기에는 영향을 주지 않음. 이슈 8597 참고.
-
분절된 요소(fragmented elements)는 뷰 전환에 참여하지 않음. 이슈 8339 참고.
-
"snapshot root"를 "snapshot containing block"으로 이름 변경, 그리고 그 자손에 대해 절대 위치 포함 블록 및 고정 위치 포함 블록으로 지정. 이슈 8505 참고.
2022-10-25 Working Draft (FPWD)에서의 변경 사항 (원문 보기)
-
동적 뷰 전환 스타일시트 개념 추가(현재 문서에 스코프된 동적으로 생성되는 UA 스타일).
-
스냅샷 뷰포트 개념 추가. 이슈 7859 참고.
-
건너뛴 전환에서 promise resolve/reject 타이밍을 명확하게 설명. 이슈 7956 참고.
-
content-visibility:auto인 상위 요소에서 내용을 건너뛰는 경우 하위 요소는 무시. 이슈 7874 참고.
-
의사 DOM의 UA 스타일이 개발자 관찰 가능한 API와 동기화되도록 유지. 이슈 7812 참고.
-
updateCallback 동안 렌더링 억제. 이슈 7784 참고.
-
새 문서의 요소 크기/위치 변경시 새로운 UA 애니메이션 keyframe 생성. 이슈 7813 참고.
-
@keyframes를 -ua- 프리픽스로 UA 스타일시트에 스코프. 이슈 7560 참고.
-
의사 요소 이름을 view-transition*으로 변경. 이슈 7960 참고.
-
의사 요소 셀렉터 문법 업데이트. 이슈 7788 참고.
-
보안/개인정보 보호 고려사항 섹션 추가.