position: fixed 가 작동을 하지 않는다면?

가누·2022년 12월 21일
1
post-thumbnail

우리가 보통 스크롤에 관계 없이 메뉴바, 헤더 등을 화면에 고정시키고 싶을 때 css의 position 속성을 사용한다.

position: fixed;

그런데 이 속성에는 재미있는 조건이 있다.

단, 요소의 조상 중 하나가 transform, perspective, filter 속성 중 어느 하나라도 none이 아니라면 (CSS Transforms 명세 참조) 뷰포트 대신 그 조상을 컨테이닝 블록으로 삼습니다. -MDN Web Docs

즉, 부모 요소 중 보통은 transform, perspective, filter 속성 중 하나를 가지고 있다면 원래 의도와 달리 화면에 고정이 안된다는 것이다. 설마 이런 조건이 나한테 해당되겠어? 라는 생각이 들지만, 개발하다 보면 해당되는 경우가 꽤 발생한다.

해결방법은 간단하다. 부모 요소 중 저 셋 속성을 가지고 있는 부분을 제거하면 된다. 하지만, 나의 경우 부모 요소 중 하나가 필수적으로 transform 속성을 가질 수 밖이 없었는데, 그것은 바로 scale 때문이다.

부모의 transform 속성을 포기할 수 없었던 이유

웨이브온에서 유저가 직접 생성한 요소는 대부분 position: absolute 속성을 가진다. 덕분에, 유저는 원하는 곳에 자유롭게 요소를 위치시킬 수 있지만, 한 가지 치명적인 문제를 갖는다. 다양한 사이즈의 디바이스를 대응하기 어렵다는 것이다.

이러한 문제를 해결하기 위해 모바일 디바이스의 width에 맞게 scale을 적용한다. 예를 들어, 디바이스의 width가 180px 이고 기준이 되는 width가 360px 이라면, transform: scale(0.5)를 해준다. 최상위 부모 요소가 transform 속성을 가지면서, 자식 요소는 position: fixed 가 되야하니 참으로 난감한 상황이다.

본론으로

이를 해결하기 위한 방법은 의외로 간단하다. fixed 속성을 가져야하는 요소를 transform 속성을 가지고 있는 최상위 부모 밖으로 빼내는 것이다.

// 기존 HTML 구조
<div id="부모 엘리먼트" style="transform: scale(0.5);">
    <div id="자식 엘리먼트 1" style="position: fixed;">
    </div>
</div>
// 수정 후
<div id="부모 엘리먼트" style="transform: scale(0.5);">
</div>
<div id="자식 엘리먼트 1" style="position: fixed;">
</div>

이제 부모 밖으로 빼낸 position: fixed를 가진 자식 요소 또한, scale을 시켜주면 된다. (혼자서만 엉뚱한 사이즈를 보여줄 수는 없으니까!) 하지만, 높은 확률로 엉뚱한 곳에 가있을 확률이 높다. 그 이유는 scale의 기준이 되는 포인트를 명시하지 않았기 때문이다. 이는 css의 transform-origin 속성으로 조정하면 된다. transform-origin에 대한 설명은 이 링크를 참조하면 쉽게 이해 할 수 있다. 이 속성의 기본 값은 center 이기 때문에 아무것도 설정하지 않으면 현재 요소의 중심점을 기준으로 scale이 적용된다.

다음 포스트에는 Vue에서 template을 이용하지 않고 렌더링을 하는 방법에 대해 다루고자 한다.

profile
가누입니다.

0개의 댓글