FRONTEND/React
[React + styled-components ] 반응형 네비게이터(헤더 메뉴) 적용하기
JUNGY00N
2023. 12. 25. 05:03
결과물 미리보기
모바일 버전에서는 모든 메뉴를 나열하기에 너비가 부족하므로 메뉴 버튼을 클릭했을 때만 메뉴가 보이고, 닫을 수 있도록 반응형으로 구현하고자 한다.
반응형 너비 기준
반응형 너비 나누는 기준은 아래와 같이 적용했다.
테블릿 버전일경우 달라지는 것은 폰트 사이즈 변경뿐이기에 자세한 설명들은 생략하고 모바일 버전일 때를 주로 다루겠다.
/* 노트북 & PC (해상도 1024px)*/
@media screen and (min-width:1024px) {
스타일 입력
}
/* 테블릿 가로, 테블릿 세로 (해상도 768px ~ 1023px)*/
@media screen and (min-width:768px) and (max-width:1023px) {
스타일 입력
}
/* 모바일 가로, 모바일 세로 (해상도 480px ~ 767px)*/
@media screen and (max-width:767px) {
스타일 입력
}
구현 코드
const Header = () => {
(...)
const [hideSideMenu, setHideSideMenu] = useState(true); // 모바일 버전에서 메뉴 숨김 유무
const toggleSideMenu = () => {
setHideSideMenu(!hideSideMenu);
};
(...)
return (
<Container>
<Navbar>
<Logo ... />
/* 모바일 버전이면서 hideSideMenu값이 true면 메뉴 버튼 보이기 */
{hideSideMenu && (
<MenuButton>
<TbMenu2 size={'30px'} onClick={toggleSideMenu} />
</MenuButton>
)}
/* 일반 네비게이터와 사이드 메뉴를 구분하기 위해 hideSideMenu값이 false일 때만 클래스명 side 추가 */
<NavitemContainer className={!hideSideMenu ? 'side' : ''}>
/* hideSideMenu 값이 false 일 때만 메뉴버튼 보이게 하기 */
{hideSideMenu || (
/* 사이드 메뉴 안에서의 메뉴 버튼임을 구분하기 위해 클래스명 side 설정 */
<MenuButton className="side">
<TbMenu2 size={'30px'} onClick={toggleSideMenu} />
</MenuButton>
)}
<Navitem ... > 홈 </Navitem>
)}
(...)
</NavitemContainer>
</Navbar>
</Container>
);
};
export default Header;
export const MenuButton = styled.button`
display: none;
/* 모바일 버전에서만 보이도록 */
@media screen and (max-width: 767px) {
display: flex;
width: 100%;
background-color: transparent;
justify-content: end;
padding: 0;
/* 여백 조절을 위해 클래스이름으로 패딩값을 다르게 함 */
&.side {
padding: 20px 5vw;
}
}
`;
(...)
export const NavitemContainer = styled.div`
display: flex;
width: 80%;
@media screen and (min-width: 768px) and (max-width: 1023px) {
width: 70%;
}
/* 모바일 버전일 때는 숨김 */
@media screen and (max-width: 767px) {
display: none;
/* 사이드 메뉴 열었을 때 */
&.side {
margin: 0 auto;
background-color: var(--main-yellow-color);
box-shadow: 3px 3px 10px 0px lightgray;
display: block;
width: 100vw;
position: absolute;
z-index: 12;
right: 0;
top: 0;
}
}
`;
주요 코드만 작성했다.
- hidesidemenu : true면 사이드메뉴가 숨겨진 상태, false면 보이는 상태
- 첫번째 MenuButton은 style 코드에서 모바일 버전이 속할 때만 보이도록 설정
- 두번째 MenuButton은 sidemenu 안에 있는 메뉴 닫기 버튼으로서 모바일 버전이면서, hidesidemenu 값이 false일 때만 보이도록 함
- 네비게이터 메뉴가 모바일이 아닐 때는 display 속성을 flex로, 모바일일때는 block으로 주기 위해 클래스명 side로 구분함
- 기존 헤더의 z-index 값이 10이었는데, 그보다 큰 12로 주어 항상 최상에 위치하게 함
- right와 top 값을 0으로 하여, 오른쪽 위부터 시작되도록 함
- width 를 100% 로하여 화면에 빈틈없이 채워지도록 함
반응형 웹은 해본 적이 많이 없어서 아직 어렵게 느껴진다.
어쩌면 저 코드들이 매우 비효율적일 수도 있으나 현재 상태에선 최선인 것 같다.
코드 : https://github.com/elice-final-team6/MongMongVillage-FE/tree/main/src/components/Header