소개
KUIT 교내 개발 동아리에서 WEB 파트장을 맡아 운영 중이다. WEB 파트 부원들에게 준 2주차 미션이 당근마켓 화면 HTML, CSS로 클론코딩하기였다.
미션 결과물 코드리뷰를 하다 좋은 질문들이 많이 나와 공부가 많이 되었는데, 그 중에 fixed menu, 메뉴 바 상단 고정 구현 할 때 menu bar 아래 content에 margin-top을 주면 위험할수도 있겠다는 생각이 들었고, 그 이유에 대해서도 많이 찾아보게 되어서 글을 써보았다.
질문
코드와 함께 보는 것이 편할 수도 있을 것 같아 추가한 github discussion 주소이다.
만들고자 하는 화면은 아래 이미지처럼 당근마켓의 한 화면을 구현하되, 스크롤을 내려도 맨 상단 바가 항상 위에 고정되도록 하는 것이었다. 일반적인 블로그나 사이트에서도 많이 쓰이는 fixed menu 구현이다.
질문은
.main__header 에 top 0px 속성을 주니 content 요소에서 margin,padding 속성으로 위치 조정이 가능한 반면, top 0px 속성을 주지 않았을 때 content 요소에서 margin-top 속성을 주니 fixed를 준 main__header 요소가 밑으로 함께 내려오는 이유를 알 수 있을까요? 였다.
유명 개발자 분이 fixed menu를 구현한 블로그에서도 당연한 듯이 margin이 아닌 padding-top을 사용하시길래 그 이유가 정말 궁금해졌다. 생각보다 이유를 정리한 글을 찾기 힘들었다.
해결
결론부터 말하자면 margin-collapsing 이 발생해 body element에 영향을 주었기 때문이다.
먼저, absolute position은 veiwport (브라우저에서 보이는 화면 기준)으로 positioning 된다. 그리고 브라우저에 렌더링 될 때 다음 단계를 거친다.
- item-list와 부모 요소 body tag가 margin collapsing이 발생해서 body의 viewport 상 시작 위치가 상단 52px부터가 된다.
- main__header에 absolute 속성을 붙이더라도 offset(top, left, bottom, right)을 지정하지 않거나 auto로 두면 position이 static일 때의 위치와 일치하도록 offset이 자동 지정된다.
- static의 기준점은 body 기준이므로, body element의 시작 위치부터 지정되게 된다. 따라서 따로 top:0 속성을 주지 않으면 body와 함께 밀린 상태로 있게 된다.
- 문제는 main__header에 top: 0을 줘도 사실상 body에는 margin-collapsing이 일어난 상태가 유지된다!!!!!!!
새로운 문제 발생
제목에서 적은 Fixed Menu, 메뉴 바 상단 고정 구현 시 content에 margin-top을 주면 위험한 이유는 바로 위 4번 과정에서처럼 body가 margin-collapsing이 발생해 밀려나기에, header는 따로 top: 0을 주어 맞춘다 하더라도 다른 body 기준으로 배치되는 element들이 이상해질 가능성이 높기 때문이다!!!
그럼 이를 해결하기 위해 어떻게 해야 할까?
처음에는 그렇다면 body에 추가 속성을 줘서 margin-collapsing을 방지하거나, item-list에 margin-top이 아닌, padding-top을 주는 것이 추후 오류 예방을 위해 훨씬 좋을 수도 있을 것이라 답변했다.
padding-top 으로 해결하거나, 헤더 동일 크기의 빈 element를 두어 해결
다른 사이트들을 찾아보니 네이버와 카카오는 padding-top으로 해결하는 것을 볼 수 있었다.
그런데 토스의 구현을 보니까 헤더 크기만큼 빈 요소를 두는 것을 발견했다.
굳이 padding 대신 빈 요소를 두는 이유가 이해가 안 되어 현직자 친구의 정말 깔끔한! 답변을 받았다.
padding 대신 동일 크기 빈 요소를 두는 이유는
"본래 목적에 맞지 않는 영역에 관여하는 것을 방지" 하고,
"padding으로 content에서 top menu까지 신경쓰기보다, 상단메뉴에서 구현할 때 아예 자기 자신의 높이만큼 차지하는 빈요소를 두는 것이 관심사 분리에 더 적합" 하기 때문이라 한다.
내 경험으로도 화면 구현할 때 여러 단계 아래 있는 content에서 padding을 일일히 계산하느라 애먹은 적이 있었고, 특히 반응형을 나중에 마이그레이션 할 때도 어느 padding들이 합쳐진 건지 이전 개발자 분이 적어둔 주석을 보고 겨우 찾아냈던 기억이 떠올랐다. 이를 생각해보면 토스가 관심사 분리 측면에서 정말 좋은 접근법을 고안한 것이라 느꼈다.
진짜 좋은 질문이었고 이 덕분에 생각지도 않고 쓰던 것을 한 번 더 돌아보며 자세히 파고들 기회였다.
<참고링크>
'프로그래밍 > Frontend (React, Javascript, Typescript)' 카테고리의 다른 글
전역 상태(zustand)에서 배열 concat의 side effect, 해결 방안 (feat. React Strict Mode) (0) | 2024.12.15 |
---|---|
Vite Proxy with Base URL & CORS 해결 (2) | 2024.11.28 |
10분 만에 웹사이트에 PWA 적용해서 웹앱 만들기! (2) | 2024.11.14 |
React Component와 객체지향의 차이에 관하여 (2) | 2024.09.29 |
[JavaScript, Node.js] 프론트엔드(JavaScript Runtime)에서의 Race Condition (0) | 2024.04.11 |