본문 바로가기

개발일지

Firefox에서 Grid 영역에 Fixed 불가능한 크로스 브라우징 이슈 해결

웹 개발을 하다 보면 브라우저마다 CSS 속성의 동작 방식이 미묘하게 다를 수 있습니다. 이번에 제가 발견한 이슈는 Firefox에서 position: fixeddisplay: grid와 함께 사용될 때, 예상과 다르게 동작하는 문제입니다. 검색해보아도 관련 자료를 찾기 어려웠기 때문에, 해결 과정을 공유하고자 합니다.

배경 지식

일반적으로 position: fixed는 뷰포트를 기준으로 설정된 top, bottom, left, right 위치에 고정됩니다. 그러나 위치 설정이 없다면 top, bottom, left, rightauto가 되어, 브라우저가 자동으로 계산한 문서 흐름 상 원래 있어야 했을 위치에 고정됩니다.

position: fixed;
top: auto;
bottom: auto;
left: auto;
right: auto;

상황 설명

저는 위 사실을 바탕으로 display: gridposition: fixed를 함께 사용하면서, 부모 요소에 grid-template을 설정하고, 위치 설정 없이 fixedgrid-column: 1/2; grid-row: 2/3;처럼 위치를 지정하면 문서 흐름 상 원래 있어야 했을 위치인 해당 grid 위치에 고정된다는 사실을 발견해 유용하게 사용하고 있었습니다. 아래는 제가 사용한 코드와 웹 이미지입니다:

position: fixed;
padding: 10px;

@media ${media.expanded} {
  grid-column: 1/2;
  grid-row: 2/3;
}

Chrome 화면: fixed인 좌측 메뉴와 우측 앵커가 grid 요소의 위치에 있는 걸 확인 가능하다.

Firefox에서 발생한 문제

firefox: 전체 레이아웃 요소의 좌상단에 고정되어 있다.

Chrome, Safari, Opera, Edge 등 다른 브라우저에서는 위 코드가 정상적으로 동작하지만, Firefox에서는 요소가 문서 흐름 상 원래 있어야 했을 위치인 grid 영역을 무시하고, 전체 영역의 좌상단에 고정됩니다.

해결 방법

Firefox에서 발생하는 이 문제를 해결하기 위해, position: sticky로 대체하는 방법을 사용했습니다. position: sticky는 부모 요소의 grid 영역에 영향을 받으며 특정 스크롤 위치에서 요소를 고정시킬 수 있어, Firefox에서 발생하는 문제를 해결하는 데 적합했습니다.

@supports (-moz-appearance: none) {
  position: sticky;
  top: 90px;
  height: calc(100vh - 90px);
}

위 코드에서 @supports (-moz-appearance: none)는 Firefox에서만 적용되도록 하는 조건문입니다. position: sticky를 사용하여 요소를 고정 위치에 두면서, 상단에서 90px 떨어진 위치에 고정시킵니다.

왜 전부 sticky로 대체하지 않았는가?

좌: sticky / 우: fixed

모든 브라우저에서 position: sticky를 사용하는 대신, 일부만 사용하는 이유는 UX 때문입니다. 노트북 등 트랙패드나 태블릿 터치 드래그로 스크롤할 때, 오버스크롤 시 고정된 메뉴가 상하단 임계점에 닿으면 튕기는 듯한 움직임이 발생할 수 있습니다. 이는 사용자 경험을 저해할 수 있기 때문에, 최대한 position: fixed를 유지하고 필요한 부분에만 position: sticky를 사용했습니다.

결론

이번 문제는 display: gridtop: auto(bottom, left, right)의 크로스 브라우징 문제로, Firefox에서 발생하는 이슈였습니다. 이를 해결하기 위해 position: sticky를 사용하여 문제를 해결했습니다. 웹 개발 시 브라우저별 호환성을 고려하여 다양한 방법을 시도해보는 것이 중요합니다. 이 글이 비슷한 문제를 겪는 다른 개발자들에게 도움이 되길 바랍니다.

 


추가수정

function Left({ children }: LayoutProps) {
  return (
    <Expanded>
      <RelativeLeft>
        <LeftContainer>{children}</LeftContainer>
      </RelativeLeft>
    </Expanded>
  );
}

const LeftContainer = styled.aside`
  position: fixed;

  width: 280px;
  padding: 10px;
`;


const RelativeLeft = styled.div`
  position: relative;

  width: 100%;
  height: 100%;

  @media ${media.expanded} {
    grid-column: 1/2;
    grid-row: 2/3;
  }
`;

 

position: relative인 부모 요소를 grid에 맞게 배치한 후, 내부에 fixed를 사용하여 문제를 완전히 해결하였습니다.