position:fixed 요소에 변경사항 스태킹

Tom Wiltzius
Tom Wiltzius

Chrome 22에서 position:fixed 요소의 레이아웃 동작이 이전 버전과 약간 다릅니다. 이제 모든 position:fixed 요소가 새로운 스택 컨텍스트를 형성합니다. 이렇게 하면 일부 페이지의 스태킹 순서가 변경되어 페이지 레이아웃이 손상될 수 있습니다. 새 동작은 휴대기기 (iOS Safari 및 Android용 Chrome)의 WebKit 브라우저 동작과 일치합니다.

무엇을 쌓을 것인가?

페이지에서 요소의 깊이 순서를 결정하는 데 z-index를 사용하는 것은 누구나 잘 알고 있습니다. 그러나 모든 Z-색인이 동일하게 생성되는 것은 아닙니다. 요소의 z-index는 동일한 스태킹 컨텍스트의 다른 요소와 관련된 순서만 결정합니다. 페이지의 대부분의 요소는 단일 루트 스택 컨텍스트에 있지만, 자동이 아닌 z-index 값을 갖는 절대적 또는 상대적으로 배치된 요소는 자체 스택 컨텍스트를 형성합니다. 즉, 모든 하위 요소가 상위 요소 내에서 z 순서로 지정되고 상위 요소 외부의 콘텐츠와 인터리브되지 않습니다. Chrome 22부터 position:fixed 요소도 자체 스태킹 컨텍스트를 생성합니다.

컨텍스트 스태킹에 관한 일반적인 개요는 이 MDN 문서를 참고하세요.

position:fixed새 position:sticky 속성을 비교합니다. 참고로 position:sticky는 항상 새로운 스택 컨텍스트를 만듭니다.

동기

모바일 브라우저 (모바일 Safari, Android 브라우저, Qt 기반 브라우저)는 자체 스택 컨텍스트에 position:fixed 요소를 배치하고 특정 스크롤 최적화를 허용하므로 (예: iOS5, Android Gingerbread 등) 일정 시간 동안 유지되어 웹페이지가 터치에 훨씬 더 잘 반응합니다. 이 변경사항이 데스크톱에 도입되는 이유는 다음 세 가지입니다.

  1. '모바일' 브라우저와 '데스크톱' 브라우저에서 렌더링 동작이 다르다는 것은 웹 작성자에게 난관이 됩니다. CSS는 가능한 경우 어디서나 동일하게 작동해야 합니다.
  2. 태블릿에서는 컨텍스트 생성 알고리즘을 스태킹하는 '모바일'과 '데스크톱' 중 어느 것이 더 적절한지 명확하지 않습니다.
  3. 모바일에서 데스크톱으로 스크롤 성능을 최적화하면 사용자와 작성자 모두에게 도움이 됩니다.

변경사항의 세부 내용

다음 예는 다양한 레이아웃 동작을 보여줍니다. https://codepen.io/paulirish/pen/CgAof

이번 변경으로 두 버전 모두 오른쪽 버전처럼 렌더링됩니다.

이 예에서 녹색 상자에는 z-index: 1가 있고 분홍색 상자에는 z-index: 3가 있으며 주황색 상자에는 z-index: 2가 있습니다. 파란색 상자는 주황색 상자의 상위 항목이며 position:fixed가 있습니다.

파란색 상자에 자체 스택 컨텍스트를 가져오면 주황색 상자의 z-index는 파란색 상자의 스택 컨텍스트를 기준으로 계산됩니다. 파란색 상자의 z-indexauto이므로 루트 스택 컨텍스트에서 스택 수준이 0이므로 주황색 상자가 루트 컨텍스트에서 각각 1과 3 (각각)의 Z-색인을 갖는 녹색과 분홍색 상자 뒤에 있습니다.

파란색 상자에 자체 스택 컨텍스트가 없으면 주황색 상자의 z-index가 루트 스택 컨텍스트를 기준으로 계산되며 녹색 및 분홍색 상자도 함께 계산됩니다. 따라서 주황색 상자가 분홍색 및 녹색 상자와 인터리브 처리됩니다.

컨텍스트 생성 스태킹 기준 (및 컨텍스트 스태킹의 일반적인 동작 방식)에 관한 자세한 내용은 이 MDN 문서를 다시 참고하세요. 이 예시에서 오른쪽 버전은 불투명도가 1보다 작기 때문에 항상 파란색 상자에 자체 스태킹 컨텍스트를 제공했습니다. 실질적으로 이루어지는 동작 변경은 별도의 스태킹 컨텍스트, 즉 position:fixed의 요소를 생성하기 위한 또 다른 기준을 추가합니다.

테스트와 미래

페이지가 변경될지 테스트하려면 Chrome의 about:flags로 이동하여 '고정 위치 요소가 스태킹 컨텍스트를 생성함'을 사용 설정 또는 중지하세요. 두 경우 모두 레이아웃이 동일하게 작동하면 완료된 것입니다. 그렇지 않은 경우 해당 플래그가 사용 설정된 상태로 나에게 적합한지 확인하세요. Chrome 22에서 기본값이 될 것입니다.

이번 변경으로 인해 위치:고정 하위 트리 내의 콘텐츠를 외부에서 스크롤되지 않는 콘텐츠와 인터리브하는 기능이라는 한 가지 기능이 삭제됩니다. 웹 개발자들이 의도적으로 이 작업을 하는 경우는 거의 없으며, DOM의 여러 부분에 여러 position:fixed 요소에 여러 개의 position:fixed 요소를 제공함으로써 동일한 효과를 일으킬 수 있습니다. 예를 들어 다음 두 가지 예를 살펴보겠습니다.

https://codepen.io/wiltzius/pen/gcjCk

이 페이지에서는 위치:고정 요소의 하위 div (overlayA 및 overlayB)를 가져와 별도의 콘텐츠 div 위에 하나, 동일한 별도의 콘텐츠 div 아래에 하나를 배치하려고 합니다. position:fixed 요소가 자체 스태킹 컨텍스트이고 이 요소는 (모든 하위 요소와 함께) 콘텐츠 div 전체 위 또는 아래에 있기 때문에 이렇게 할 수 없습니다. Chrome 2에서는 더 이상 이러한 예가 작동하지 않습니다. Chrome 2에서는 더 이상 작동하지 않습니다.

이 문제를 해결하기 위해 두 오버레이를 자체 위치(고정) 요소로 나눌 수 있습니다. 각각은 고유한 스택 컨텍스트로, 하나는 콘텐츠 div 위에 위치할 수 있고 하나는 콘텐츠 div 아래에 위치할 수 있습니다. Chrome 21 및 22에서 작동하는 수정된 예를 참고하세요.

https://codepen.io/wiltzius/pen/vhFzG

이 예의 기원에 대한 크레딧은 불가능한 hixie에 부여됩니다.

Chrome은 position:fixed 요소를 통해 자체 스택 컨텍스트를 생성하는 최초의 데스크톱 브라우저입니다. 관련 표준은 CSS Z-색인 사양입니다 (예: https://www.w3.org/TR/CSS21/zindex.html 참고). 여기에서 모바일과 데스크톱 브라우저의 차이에 대해 어떻게 해야 할지에 대한 합의가 아직 이루어지지 않았지만, 모바일과 데스크톱에서 두 가지 다른 동작이 있다는 혼란을 감안하여 Chrome은 당분간 두 플랫폼 모두에서 이러한 단일 동작으로 전환하기로 했습니다.

2012년 10월 1일 업데이트: 이 도움말의 원래 버전에서는 새로운 위치 동작인 고정 요소를 반영하도록 CSS z-index 사양이 이미 변경되었음을 제안했습니다. 이는 정확하지 않습니다. www 스타일 목록에서 논의되었지만 아직 사양에 변경사항이 적용되지 않았습니다.