1. 소개
오늘날 웹 사용자들은 뷰포트 외부에서 발생하는 변화로 인해 콘텐츠가 움직이면서 자주 방해를 받습니다. 예를 들어, 스크립트가 광고가 들어있는 iframe을 삽입하거나, 크기가 지정되지 않은 이미지가 느린 네트워크에서 로드될 때 등이 있습니다.
역사적으로 브라우저의 기본 동작은 이러한 변화가 발생할 때 절대적인 스크롤 위치를 유지하는 것이었습니다. 즉, 콘텐츠 이동을 방지하기 위해 웹페이지는 나중에 로드될 항목을 위해 페이지에 공간을 미리 예약할 수 있습니다. 실제로는 대부분의 웹사이트가 이를 일관되게 수행하지 않습니다.
스크롤 앵커링은 예기치 않은 콘텐츠 이동을 최소화하는 것을 목표로 합니다. 뷰포트 외부의 변화에 맞춰 스크롤 위치를 조정하여 이를 달성합니다.
설명서 문서는 스크롤 앵커링에 대한 비공식적인 개요를 제공합니다.
1.1. 값 정의
이 명세는 CSS 속성 정의 규약을 [CSS2]에서 따르며, 값 정의 문법을 [CSS-VALUES-3]에서 사용합니다. 이 명세에서 정의되지 않은 값 타입은 CSS Values & Units [CSS-VALUES-3]에서 정의됩니다. 다른 CSS 모듈과의 결합으로 이러한 값 타입의 정의가 확장될 수 있습니다.
속성별 값 정의에 나열된 값 외에도, 이 명세에서 정의된 모든 속성은 CSS-전체 키워드를 속성 값으로 허용합니다. 가독성을 위해 명시적으로 반복하지 않았습니다.
2. 설명
스크롤 앵커링은 레이아웃 변화에도 사용자가 문서를 보는 뷰를 안정적으로 유지하려고 시도합니다. 이는 DOM 노드( 앵커 노드 )를 선택해서 그 움직임을 기준으로 스크롤 위치 조정을 결정하는 방식으로 동작합니다.
그러나 스크롤 컨테이너가 현재 스냅된 요소에 맞춰져 있으면, ( [CSS-SCROLL-SNAP-1] 참조 ) 스크롤 앵커링은 재스냅에 의해 허용되는 조정으로 제한됩니다.
2.1. 앵커 노드 선택
각 스크롤 박스는 DOM 구조상 깊은 곳에 있고 중요한 DOM 노드로 우선시되거나, 최적 시야 영역의 블록 시작 가장자리와 가까운 앵커 노드를 선택하려고 합니다.
참고: 사용자 에이전트가 scroll-padding 속성을 지원하지 않는 경우, 스크롤 박스의 최적 시야 영역은 콘텐츠 영역과 동일합니다.
앵커 노드는 박스 중에서, 비-atomic inline 박스를 제외한 어떤 것이든 될 수 있습니다. 앵커 노드는 항상 후손이어야 하며, 스크롤 박스의 후손입니다. 경우에 따라 스크롤 박스가 앵커 노드를 선택하지 않을 수도 있습니다.
요소 C는 스크롤 박스 S의 스크롤 앵커 후보가 될 유효 후보입니다. 다음 조건을 모두 만족하면:
-
C는 비-atomic inline 요소가 아닙니다.
-
C는 S의 후손입니다
-
C는 제외된 서브트리에 속하지 않습니다
-
C의 S까지의 조상 중 어느 것도 제외된 서브트리에 속하지 않습니다
일부 요소는 앵커 선택 시 우선 후보로 간주됩니다:
-
DOM 앵커 ( 문서의 포커스 영역의).
-
find-in-page 사용자 에이전트 알고리즘의 현재 활성 선택 매치를 포함하는 요소. 매치가 여러 요소에 걸쳐 있으면, 첫 번째 해당 요소만 고려합니다.
우선 후보가 비-atomic inline 요소인 경우, 대신 가장 가까운 비-atomic inline 조상 요소를 우선 후보로 간주합니다.
-
S가 overflow-anchor 속성의 계산값이 none인 요소와 연결된 경우, S에 대해 앵커 노드를 선택하지 않습니다.
-
그 외의 경우, 지정된 순서대로 각 우선 후보 PC에 대해, PC가 유효 후보인지 S에서 확인합니다. 그렇다면 앵커 노드로 선택하고 종료합니다.
-
그 외의 경우, S와 연결된 요소 또는 문서의 각 DOM 자식 N에 대해, 후보 검사 알고리즘을 N에 대해 S에서 수행하고, 앵커 노드를 선택하면 종료합니다.
-
N이 제외된 서브트리이거나, N이 완전히 잘림 상태라면 (S에서), 아무것도 하지 않습니다 (N 및 그 후손은 건너뜁니다).
-
N이 완전히 보임 상태라면 (S에서), N을 앵커 노드로 선택합니다.
-
N이 부분적으로 보임 상태라면:
-
N의 각 DOM 자식 C에 대해, 후보 검사 알고리즘을 C에 대해 S에서 수행하고, 앵커 노드를 선택하면 종료합니다.
-
N이 컨테이닝 블록인, DOM 부모가 N이 아닌 절대 위치 요소 A 각각에 대해, 후보 검사 알고리즘을 A에 대해 S에서 수행하고, 앵커 노드를 선택하면 종료합니다.
-
N을 앵커 노드로 선택합니다. (이 단계에 도달하면, N의 후손 중에 적합한 앵커 노드가 없었던 것입니다.)
참고: 더 깊은 노드를 우선시하면, 뷰포트 외부에서 앵커 노드 내부의 콘텐츠가 변경되어 스크롤 앵커링 조정 없이 가시 콘텐츠가 이동하는 가능성을 줄일 수 있습니다.
-
개념적으로, 모든 스크롤 박스의 스크롤 위치가 변경될 때마다 새로운 앵커 노드가 계산됩니다. (성능 최적화를 위해, 구현에서는 앵커 노드가 필요할 때까지 계산을 지연할 수 있습니다.)
2.2. 스크롤 조정
앵커 노드가 선택된 경우,
앵커 노드가 이동할 때,
브라우저는 앵커 노드의 스크롤 앵커링 바운딩 rect의 블록 시작 가장자리의 이전 오프셋 y0
와
현재 오프셋 y1
를
계산합니다.
이 오프셋은 스크롤러의 블록 흐름 방향에서 스크롤 콘텐츠의 블록 시작 가장자리 기준입니다.
그 후 y1 - y0
만큼의 스크롤 위치 조정이
블록 흐름 방향으로 큐에 쌓이고,
억제 윈도우가 끝날 때 수행됩니다.
스크롤 조정은 [CSSOM-VIEW]에서 정의된 [[cssom-view-1#scrolling-events#scrolling]]의 한 종류이며, 거기서 설명된 방식대로 scroll 이벤트를 생성합니다.
2.2.1. 억제 윈도우
앵커 노드의 모든 이동은 억제 윈도우라 불리는 시간창 내에서 발생하며, 다음과 같이 정의됩니다:
-
억제 윈도우는 현재 HTML 처리 모델 이벤트 루프의 시작, 또는 최근에 완료된 억제 윈도우의 끝 중 더 최신 시점에서 시작합니다.
-
억제 윈도우는 현재 HTML 처리 모델 이벤트 루프의 끝, 또는 스크롤 위치 변화로 인해 결과나 부작용이 달라질 다음 작업(예:
getBoundingClientRect()
호출) 직전 중 더 이른 시점에 끝납니다.
참고: 억제 윈도우의 경계는 스크롤 앵커링 API가 안정화되면 HTML 표준에 통합되어야 합니다.
하나의 억제 윈도우 내에서 여러 번의 앵커 노드 이동이 발생할 수 있습니다.
억제 윈도우 끝에서, 사용자 에이전트는 윈도우 동안 큐에 쌓였지만 억제 트리거로 억제되지 않은 모든 스크롤 조정을 수행합니다.
2.2.2. 억제 트리거
억제 트리거는 앵커 노드 이동에 대해, 해당 이동의 억제 윈도우 내에서 발생하면 스크롤 앵커링 조정을 억제하는 동작입니다. 트리거는 다음과 같습니다:
-
아래 속성들 중 하나라도 계산값이 변경되는 경우, 앵커 노드에서 스크롤 가능한 요소(또는 문서)까지 경로 상의 모든 요소(양쪽 포함)에서 적용됩니다:
-
스크롤 가능한 요소(또는 문서) 내의 어떤 요소든 position 속성 계산값이 변경되어, 해당 요소가 절대 위치가 되거나 절대 위치가 아니게 되는 경우. 이 트리거는 수정된 요소가 앵커 노드에서 스크롤 가능한 요소까지 경로에 있든 아니든 상관없이 적용됩니다.
-
스크롤 가능한 요소의 스크롤 오프셋이 0인 경우.
참고: 억제 트리거는 스크롤 이벤트 핸들러에서 콘텐츠 이동으로 인해 스크롤 앵커링과 부정적 상호작용이 있는 기존 웹 콘텐츠와의 호환성을 위해 존재합니다.
3. 제외 API
스크롤 앵커링은 출시 시 기본 동작 모드가 되는 것을 목표로 하며, 사용자가 레거시 콘텐츠에서도 혜택을 받을 수 있도록 합니다. overflow-anchor는 웹페이지의 일부 또는 전체에서 스크롤 앵커링을 비활성화(옵트아웃)하거나, 앵커 노드 선택 알고리즘에서 DOM의 일부를 제외할 수 있습니다.
Name: | overflow-anchor |
---|---|
Value: | auto | none |
Initial: | auto |
Applies to: | 모든 요소 |
Inherited: | 아님 |
Percentages: | 해당 없음 |
Computed value: | 지정된 키워드 |
Canonical order: | 문법에 따라 |
Animation type: | 불연속적(discrete) |
값의 정의는 다음과 같습니다:
- auto
-
이 요소가 자신이나 조상이 생성한 모든 스크롤 박스의 앵커 노드 선택 알고리즘에 참여할 자격이 있음을 선언합니다.
- none
-
이 요소와 그 후손(다른 스크롤 요소에 중첩되어 있지 않은)은 자신이나 조상이 생성한 모든 스크롤 박스의 앵커 노드 선택 알고리즘에 참여 자격이 없음을 선언합니다.
참고: overflow-anchor: none 요소의 후손에 대해 스크롤 앵커링을 "다시 켜는" 것은 불가능합니다. 그러나 후손 스크롤 컨테이너는 (자신의 스크롤 박스에 대해) 자동으로 "다시 켜집니다" 단, 명시적으로 overflow-anchor: none이 설정된 경우는 제외입니다.
참고: overflow-anchor
속성은 (다른 값으로) CSS Sticky Scrollbars에도 제안된 바 있으며,
이는 현재 대체됨 상태입니다.
4. 개인정보 및 보안 고려사항
이 명세는 스크롤 위치 계산 방식만 조정할 뿐, 새로운 개인정보 또는 보안 고려사항을 도입하지 않습니다.