HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🤎
프론트엔드 데브코스 5기 교육생
/
🐬
류찬규팀
/
프로젝트 페이지
프로젝트 페이지
/
트러블 슈팅 노트
트러블 슈팅 노트
/
🏷️
드롭다운이 부모 요소의 크기에 따라 위치가 달라지는 이슈에 대하여 - 김현주
🏷️

드롭다운이 부모 요소의 크기에 따라 위치가 달라지는 이슈에 대하여 - 김현주

1️⃣ 어쩌다 버그를 마주했는가

 
드롭다운 모바일 이슈와 이어집니다.
이전 드롭다운 모바일 이슈를 해결하기 위해 전체적인 구조를 개선하였고, 드롭다운의 위치를 커스텀 할 수 있는 direction 기능을 추가하게 되었습니다. 따라서 현재 드롭다운 v2.0.0 부터는 드롭다운이 부모 요소의 children으로 들어가도록 구조를 변경하게 되었습니다. 이는 relative, absolute 사용을 통해 위치를 컨트롤 하기 위함입니다.
notion image
notion image
direction 은 총 12방향을 지원하며, 실제 left-bottom 값을 주었을 때의 예시입니다.
현재 위 예시는 부모 요소(CircleButton)이 자식요소(Dropdown)보다 작기 때문에, 제가 예상한 설계대로 잘 동작하여 문제가 없다고 생각했습니다.
그러나 경빈님의 제보로 문제점을 발견하게 되었습니다.
notion image
현재 위 2개의 드롭다운은 전부 left-bottom을 적용한 상태입니다. 그러나 부모 요소를 드롭다운보다 큰 크기를 가진 쉐도우 박스로 설정한 경우, 마치 left-top이 적용된 것 처럼 보입니다.
원인을 찾아본 결과, absolute의 기준점이 부모 요소의 윗 단이 되었기 때문에 해당 이슈가 발생한 것을 알 수 있었습니다.
// 기존 코드 case 'left-bottom': return css` right: 100%; top: 0; `; case 'left-top': return css` right: 100%; bottom: 0; `;
notion image
 
부모 요소(CircleButton)가 자식 요소(Dropdown)보다 작은 경우, top: 0을 주었을 때 우리가 생각하는 left-bottom 위치에 올 수 있습니다.
그러나 부모 요소(ShadowBox)가 자식 요소(Dropdown)보다 큰 경우, top: 0을 그대로 준다면 맨 위에 붙어버리기 때문에, left-top 처럼 보이게 됩니다. 오히려 이 경우엔 left-top을 적용했을 때 left-bottom 처럼 보이는, 마치 반대로 적용되는 듯한 현상을 보였습니다.
따라서 해당 코드는 드롭다운보다 부모 요소가 더 큰 경우, 부모 요소가 더 작은 경우 이렇게 2가지 케이스로 나누어 각 상황에 맞도록 값을 보정해줘야 했습니다.

💦어떤 시도를 해보았나

 
일단 부모 요소의 크기를 알아내려고 했으나, css 내부에서 부모 요소의 크기를 직접적으로 알 수 있는 방법은 없었습니다. 그렇기 때문에 처음에는 기존의 top, bottom, left, right 속성만으로 조절을 해보려고 했으나, 어떻게 해도 2가지 케이스를 모두 만족시킬 수 있는 방법은 찾을 수 없었습니다. 해당 이슈를 해결하기 위해서는 무조건 부모 요소의 크기 정보를 알아야 했습니다.
직접적으로는 크기를 알아낼 방법이 없지만 곰곰히 생각해본 결과, % 단위를 사용하면 해당 부모 요소의 크기를 간접적으로 판단할 수 있었기 때문에, %단위로 비교를 해야겠다고 생각했습니다.
 
left-bottom의 케이스로 예시를 들겠습니다.
 
left-bottom의 경우, Y축 기준점이 부모가 작을 때는 top: 0이 되어야하고, 부모가 더 클때는 top: 100% 이 되야합니다. 이 때 부모 요소의 height는 100%를 통해 간접적으로 판단할 수 있고, 자식 요소의 height는 드롭다운 props로 넘겨받은 height값을 통해 직접적으로 정보를 알고 있습니다. 따라서 max() 함수를 통해 두 값을 비교하여, 더 큰 값으로 기준점을 잡습니다.
top: max(100%, ${height});
부모 요소가 더 큰 경우 top: 100%가 되고, 부모 요소가 더 작은 경우 top: ${height} 가 됩니다.
notion image
그 결과 두 케이스 모두 나름 left-bottom에 해당하는 곳에 위치하게 되었습니다. 그러나 드롭다운의 height만큼 위치를 더 벗어나게 되었습니다.
따라서 transform: translateY() 함수를 통해 한번 더 보정을 해줍니다.
transform: translateY(-${height});
notion image
드롭다운의 height만큼 추가적으로 위로 이동시켜주니 부모 요소의 크기와 상관없이 두 케이스 모두 left-bottom 위치를 잘 찾아간 것을 확인할 수 있습니다.

💼최종 해결 방법

case 'left-top': return css` right: 100%; bottom: max(100%, ${height}); transform: translateY(${height}); margin-right: 0.5rem; `; case 'left-bottom': return css` right: 100%; top: max(100%, ${height}); transform: translateY(-${height}); margin-right: 0.5rem; `;
case 'top-left': return css` bottom: 100%; right: max(100%, ${width}); transform: translateX(${width}); margin-bottom: 0.5rem; `; case 'top-right': return css` bottom: 100%; left: max(100%, ${width}); transform: translateX(-${width}); margin-bottom: 0.5rem; `;
left-top left-bottom right-top right-bottom의 경우 드롭다운의 height를 이용해 위치를 보정합니다.
top-left top-right bottom-left bottom-right의 경우 드롭다운의 width를 이용해 위치를 보정합니다.