HTML과 CSS 작업을 하다 보면, 원하는 디자인처럼 잘 되지 않을 때가 정말 많다.
혼자서 화면 퍼블리싱과 이벤트 작동 코드를 개발하던 중, fixed 속성을 사용하면서 그 익숙한 좌절감이 다시 찾아왔다.
알고 보니, 제가 fixed 속성에 대해 잘못 이해하고 있었던 게 문제였다. fixed는 position 속성 중 하나다.

position이란?
요소의 위치를 지정하는 방법을 정의하며, 다른 요소나 부모, 뷰포트와의 관계를 설정한다.
position 속성의 종류
1. static(기본값)
- 요소가 문서 흐름에 따라 배치된다.
- 부모 요소나 다른 요소에 종속되지 않으며, 위치 조정 속성(top, left 등)을 사용할 수 없다.
2. relative
- 요소가 문서 흐름 내에서 본래 위치를 유지하면서 top, right, bottom, left를 사용해 상대적인 위치를 조정할 수 있습니다.
- 요소의 원래 공간은 그대로 유지된다.
3. absolute
- 요소를 문서 흐름에서 제거하고, 가장 가까운 relative, absolute, fixed 부모를 기준으로 위치를 지정한다.
- 만약 부모 중 위치 지정된 요소가 없다면 전체 문서(body)를 기준으로 배치된다.
4. fixed
- 요소를 뷰포트를 기준으로 고정한다.
- 스크롤해도 요소는 항상 동일한 위치에 표시된다.
- 부모 요소와 관계없이 뷰포트를 기준으로 배치
5. sticky
- 요소가 스크롤 위치에 따라 동적으로 동작한다.
- 스크롤할 때 지정된 임계점에 도달하기 전까지는 문서 흐름에 따라 배치되고, 이후에는 지정된 부모 요소를 기준으로 고정됩니다.
- top, left, bottom, right 값을 설정해야 작동한다.
팀원이 해놓은 화면 디자인은 이랬다.
여행 일정을 수정하는 페이지 제일 하단에 클릭할 수 있는 바를 배치해야 하는 것이다.
그리고 바를 클릭하면 이렇게 검색해서 새로 추가할 수 있는 모달이 뜰 수 있도록 해야했다.
클릭했을때 모달이 열리고 닫히는 이벤트는 잘 됐지만 저 검은색 바가 문제였다.....
디자인 해둔 팀원이 스크롤을 다 내렸을떄 보여야 하는게 아니라 고정시켜놓고 따라 다녀야 한다는거였다.
그래서 나는 fixed를 적용했는데 자꾸 width가 뷰포트만큼 넓어져버리는 상황이 발생했다.
그래서 calc(100% - 465px)를 적용했는데 이러면 또 화면 너비마다 그게 적용이 안되는 2차 문제가 발생했다.
.open_modal_cotanier {
position: fixed;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: calc(100% - 465px);
margin: 0;
}
이유를 찾아보니 내가 css를 엉망으로 하거나 충돌이 나서 그런것이 아니라 원래 fixed 속성은 뷰포트를 기준으로 잡는다는거였다....
화면 퍼블리싱할때 내가 했던 페이지는 fixed를 써본적이 없어서 몰랐다..ㅠㅠ
그래서 할 수 없이 자바스크립트로 해결하는걸로 결정했다.
해결 방법
먼저 modalWidth라는 상태를 통해, containerRef로 참조된 부모 요소의 너비를 추적하고, 해당 너비에 맞춰 모달 너비를 동적으로 설정하기 위해서 코드를 추가했다.
const containerRef = useRef<HTMLDivElement>(null);
const [modalWidth, setModalWidth] = useState<string>("100%");
부모 컨테이너의 너비가 변경될 때마다 모달의 너비를 동적으로 업데이트하기 위해 useEffect와 리사이즈 이벤트를 활용했습니다. 초기 렌더링 시와 윈도우 크기 변경 시 containerRef를 통해 부모 요소의 너비를 계산하여 modalWidth 상태를 업데이트하도록 했다.
useEffect(() => {
const handleResize = () => {
if (containerRef.current) {
setModalWidth(`${containerRef.current.offsetWidth}px`);
}
};
// 초기 너비 설정
handleResize();
// 윈도우 리사이즈 이벤트 추가
window.addEventListener("resize", handleResize);
// 리사이즈 이벤트 제거
return () => {
window.removeEventListener("resize", handleResize);
};
}, []);
마지막으로 부모 div에 요소를 참조하기 위해 ref 속성에 containerRef를 설정하고 css에는 작성해두었던 width 설정을 지웠다.
<div ref={containerRef} className={styles.travel_plan_list_container}>
완성한 화면은 이렇다.(하단 부분만 캡쳐)
'React' 카테고리의 다른 글
[React] react-icons v5.5.0 오류 해결: lucide-react로 전환 (0) | 2025.02.26 |
---|---|
[React] React에서 Drag & Drop 구현 – react-beautiful-dnd 사용 (0) | 2025.02.08 |
[React] REST, REST API, RESTful API의 개념과 특징, 장단점, 사용 방법 및 예시 (0) | 2025.01.21 |
[React] React에서 Css module 적용하기 (0) | 2025.01.21 |
[React] 프로젝트 폴더 구조 정리부터 퍼블리싱까지(작업 기록) (0) | 2025.01.18 |