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

Tom Wiltzius
Tom Wiltzius

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

스태킹이란 무엇인가요?

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

스택 컨텍스트에 관한 일반적인 개요는 이 MDN 도움말을 참고하세요.

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

동기

모바일 브라우저 (Mobile 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이 됩니다. 즉, 주황색 상자는 루트 컨텍스트에서 z 인덱스가 각각 1과 3인 녹색 및 분홍색 상자 뒤에 표시됩니다.

파란색 상자가 자체 스택 컨텍스트를 가져오지 않으면 주황색 상자의 z-index는 녹색 및 분홍색 상자와 함께 루트 스택 컨텍스트를 기준으로 계산됩니다. 따라서 주황색 상자는 분홍색 상자와 녹색 상자 사이에 삽입됩니다.

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

테스트 및 미래

페이지가 변경되는지 테스트하려면 Chrome의 about:flags로 이동하여 '고정된 위치 요소가 스택 컨텍스트를 만듭니다'를 사용 설정/사용 중지합니다. 두 경우 모두 레이아웃이 동일하게 작동하면 설정이 완료된 것입니다. 그렇지 않다면 Chrome 22의 기본값이므로 이 플래그를 사용 설정했을 때 수락할 수 있는지 확인하세요.

이 변경사항으로 인해 position:fixed 하위 트리 내 콘텐츠를 외부의 스크롤되지 않는 콘텐츠와 교차로 배치하는 기능이 하나 삭제됩니다. 웹 개발자가 의도적으로 이렇게 할 가능성은 낮으며, 여러 position:fixed 요소에 DOM의 서로 다른 부분을 지정하여 동일한 효과를 얻을 수 있습니다. 예를 들어 다음 두 가지 예시를 살펴보세요.

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

이 페이지에서는 position:fixed 요소의 두 하위 div(overlayA 및 overlayB)를 가져와 하나는 별도의 콘텐츠 div 위에, 다른 하나는 동일한 별도의 콘텐츠 div 아래에 배치하려고 시도합니다. 이제는 불가능합니다. position:fixed 요소는 자체 스택 컨텍스트이며 모든 하위 요소와 함께 콘텐츠 div의 완전히 위에 있거나 완전히 아래에 있기 때문입니다. 이 예시는 Chrome 21 이하에서는 작동하지만 Chrome 22에서는 더 이상 작동하지 않습니다.

이 문제를 해결하려면 두 오버레이를 자체 위치:고정된 요소로 분할할 수 있습니다. 각각은 자체 스택 컨텍스트이며, 그중 하나는 콘텐츠 div 위에 올릴 수 있고 하나는 콘텐츠 div 아래에 올릴 수 있습니다. Chrome 21 및 22에서 작동하는 수정된 예를 참고하세요.

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

이 예시의 창시자는 비할 데 없는 hixie님입니다.

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

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