[Study] 개발 공부/[React] 리액트 공부
[React] 모바일에서는 메뉴가 버튼으로 바뀌는 반응형 헤더 만들어보기
지공A
2024. 11. 4. 17:15
여태 반응형 웹 사이트를 제대로 구현해보지 못한게 아쉬워서, 포트폴리오에서는 반응형 웹 사이트를 만들어 보려고 한다!
웹에서는 기본적으로 헤더 메뉴가, 모바일에서는 메뉴 버튼을 누르면 메뉴가 보이도록 하고 디자인에도 차별점을 줘봤다.
1. isNavVisible 상태를 생성하고, toggleNav 함수를 햄버거 메뉴의 onClick에 연결한다.
const [isNavVisible, setIsNavVisible] = useState(false);
const toggleNav = () => {
setIsNavVisible(!isNavVisible);
};
2. 모바일의 햄버거 메뉴 컴포넌트 <NavMobile>을 모바일에서만 보이도록 미디어 쿼리를 설정해줬다.
- 햄버거 메뉴 컴포넌트인 NavMobile과, 모바일용 Nav 메뉴 css를 주석으로 달아놨다. (기본 Nav css 생략)
const NavMobile = styled.div<{ isNavVisible: boolean }>`
display: none;
width: 40px;
height: 40px;
cursor: pointer;
/* 모바일에서만 보이게 */
@media (max-width: 768px) {
display: block;
}
span {
display: block;
width: 40px;
height: 2px;
/* 메뉴가 열리면(isNavVisible) 흰색, 닫히면 검은색 */
background-color: ${(props) => (props.isNavVisible ? "#fff " : "#000")};
margin-top: 19px;
position: relative;
/* 햄버거 메뉴의 윗 줄 막대 */
&::before {
content: ""; // 가상 요소에 content 속성이 필수!
width: 40px;
height: 2px;
background-color: ${(props) => props.theme.colors.black000};
position: absolute;
right: 0;
top: 6px;
// 메뉴가 열리면, 막대 길이를 반으로 줄어드는데, 자연스럽게 애니메이션 효과 적용
transition: width 0.3s;
}
&::after {
content: "";
width: 40px;
height: 2px;
background-color: ${(props) => props.theme.colors.black000};
position: absolute;
left: 0;
bottom: 6px;
transition: width 0.3s;
}
}
`;
const Nav = styled.nav<{ isNavVisible: boolean }>`
@media (max-width: 768px) {
position: absolute;
top: 72px;
right: 0;
background-color: rgba(254, 168, 180);
backdrop-filter: blur(15px);
z-index: 10000;
min-width: 150px;
padding: 20px 0;
height: 100vh;
overflow-y: auto;
/* 활성화 시켰을 때, 왼쪽으로 나오는 효과 */
transform: translateX(${(props) => (props.isNavVisible ? "0" : "100%")});
opacity: ${(props) => (props.isNavVisible ? "1" : "0")};
transition: transform 0.3s ease, opacity 0.3s ease;
visibility: ${(props) => (props.isNavVisible ? "visible" : "hidden")};
ul {
list-style: none;
padding: 0;
margin: 0;
li {
display: block;
text-align: right;
a {
display: inline-block;
padding: 10px;
color: ${(props) => props.theme.colors.black000};
text-transform: uppercase;
font-size: 16px;
font-weight: 700;
position: relative;
&::before {
content: "";
width: calc(100% - 16px);
height: 1px;
background-color: ${(props) => props.theme.colors.white000};
position: absolute;
left: 8px;
bottom: 10px;
transform: scaleX(0);
transition: transform 0.3s ease;
}
&:hover {
color: ${(props) => props.theme.colors.white000};
&::before {
transform: scaleX(0.9);
}
}
}
}
}
/* isNavVisible이면 즉, 모바일메뉴가 열리면, show 클래스가 추가된다
show 클래스가 추가되면 NavMobile 햄버거 메뉴 막대의 width를 반으로 줄이고, 흰색으로 변경한다. */
&.show + ${NavMobile} span::before {
width: 20px;
background-color: ${(props) => props.theme.colors.white000};
}
&.show + ${NavMobile} span::after {
background-color: ${(props) => props.theme.colors.white000};
width: 20px;
}
}