1. 개요
Drawer는 화면 측면에서 마치 서랍처럼 슬라이드로 나왔다 들어가는 패널을 말한다.
보통 이 기능은 Drawer의 open상태를 state로 관리하는식으로 구현한다.
하지만 CSS를 이용하면 Javascript없이도 Drawer를 구현할 수 있지 않을까 하는 생각이 들었다.
그래서 이번에는 CSS만 활용해 Drawer를 구현하는것을 도전해보았다.
2. 방법
Drawer는 결국 on/off toggle형태로 동작한다. 그렇기에 HTML중 toggle요소를 이용한다면 Drawer를 구현할 수 있을 것이다.
이런 요소들은 여러가지가 있을 수 있겠지만 나는 <input type={"checkbox"} />를 이용하기로 했다.
checkbox는 체크를 on/off로 관리하므로 이를 이용한다면 drawer를 구현할 수 있을 것이다.
3. 구현
// index.jsx
<>
<input
type={"checkbox"}
id={"navInput"}
readOnly
/>
<label htmlFor="navInput">
<div className={styles.navInput}>
{/* drawer open 버튼 */}
</div>
</label>
{/* Drawer 배경 */}
<label htmlFor="navInput" className={styles.drawerBackground} />
<div className={styles.drawerContainer}>
<label htmlFor="navInput">
{/* Drawer 컴포넌트 */}
</label>
</div>
</>
// index.module.css
.drawerBackground {
display: none;
position: absolute;
z-index: 8999;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(115, 120, 128, 0.4);
}
.navInput {
display: none;
}
.navInput:checked ~ .drawerContainer {
transform: translateX(-260px);
}
.navInput:checked ~ .drawerBackground {
display: inline;
}
먼저 <input type={"checkbox"} />를 이용해 Drawer의 on/off를 관리한다.
이후 체크박스가 체크되었을 때 Drawer가 나타나고 사라지는 방식은 CSS의 인접 형제 선택자(~)와 상태 선택자(:checked)를 활용하여 구현했다.
<input type={"checkbox"} />는 사용자에게 보이지 않게 display: none; 처리하고, 체크박스와 연결된 label 요소는 htmlFor="navInput" 속성을 사용해, 사용자가 클릭했을 때 체크박스의 상태가 변경되도록 했다.
.navInput:checked ~ .drawerContainer와 같은 CSS 선택자를 활용해, 체크박스가 체크되었을 때 Drawer가 나타나도록 스타일을 지정했고, .navInput:checked ~ .drawerBackground를 이용해 배경 오버레이가 나타나도록 한다.
마지막으로 input태그에 readOnly속성을 부여해 모바일에서 접근시 키보드가 나타나는것을 막았다.
4. 이 방법은 좋은 방법일까?
이렇게 CSS만으로 Drawer를 구현해 보았다. 하지만 이 방법이 과연 좋은 방법일지 고민해볼 필요도 있다.
앞서 언급했던 React의 useState를 이용한 방법과 비교해보았다.
CSS 방식이 적합한 경우:
아주 간단한 UI에서, 상태 관리가 필요하지 않고 순수하게 CSS로 해결할 수 있을 때.
퍼포먼스가 극도로 중요한 환경에서, JS 실행을 최소화하고 싶을 때.
정적인 페이지에서 간단한 토글만 필요할 때.
React useState 방식이 적합한 경우:
Drawer와 상태가 다른 컴포넌트와 연동될 때.
Drawer 내부에서 복잡한 동작(비동기 데이터 로딩 등)이 필요할 때.
접근성(ARIA 속성, 포커스 이동 등)을 신경 써야 할 때.
개인적으로는 useState가 더 직관적이고, 확장성면에서도 유리하기 때문에 useState를 이용한 방법을 권장하고 싶다.
하지만 이번 방법을 통해 CSS만으로도 Drawer를 구현할 수 있다는것을 알게 되었다.
동일한 기능을 구현할 때 한가지 방법론에만 엮이지 않고 여러 가지 방법으로 구현해보며 사고가 확장될 수 있다는 점에서 의미 있는 경험이었던것 같다.
앞으로도 이런 도전적인, 다양한 기능 구현을 종종 시도해봐야겠다.
'프론트엔드' 카테고리의 다른 글
[React Native] React Native 0.78 주요 업데이트 2가지 (0) | 2025.03.22 |
---|---|
[React Native] numeric타입 키보드에서 onSubmitEditing함수가 동작하지 않음 (1) | 2025.01.15 |
[Frontend] DNS를 알아보자 (1) | 2024.11.27 |
[React] 드래그 앤 드랍 라이브러리(react-dropzone) (0) | 2024.11.26 |
[TIP] 더미 이미지 URL이 필요할 때 (0) | 2024.11.25 |