JS' 공부흔적
[CSS] hover 시 숨겨진 메뉴 보이게 하기 (feat. styled-components) 본문
이 글을 통해서 아래 메뉴를 구현할 수 있다.
hover 시에는 컴포넌트가 보이도록, 벗어나면 다시 사라지도록 구현해야 한다.
우선 뼈대를 구성할 건데 styled-components를 사용하여 스타일링했다.
<div>
<MenuUl>
<li>
<span>일정</span>
<SubHeader tab="schedule" />
</li>
<li>
<span>커뮤니티</span>
<SubHeader tab="feed" />
</li>
</MenuUl>
</div>
const MenuUl = styled.ul`
list-style: none;
display: flex;
align-items: center;
gap: 48px;
position: relative;
& span {
cursor: pointer;
}
`;
ul의 기본 스타일을 없애고, 메뉴 사이에 gap을 줬다.
SubHeader는 각 메뉴에 마우스를 호버 하면 나타나는 서브 메뉴이다. 간단하게 아래와 같이 작성했다.
const SubHeader = ({ tab }) => {
const getListItems = () =>
tab === "schedule"
? ["개인일정", "공유일정"]
: ["홈", "알림", "마이페이지"];
return (
<SubHeaderDiv>
<SubTabUl>
{getListItems().map((name, idx) => (
<li key={idx}>{name}</li>
))}
</SubTabUl>
</SubHeaderDiv>
);
};
export const SubHeaderDiv = styled.div`
display: none;
position: absolute;
top: 100%;
`;
export const SubTabUl = styled.ul`
list-style: none;
display: flex;
align-items: center;
gap: 48px;
padding: 0;
margin-top: 40px;
& > li {
cursor: pointer;
}
`;
SubHeader는 기본적으로 보이지 않고, 마우스를 호버 했을 때만 보이므로 display: none;으로 설정했다.
위 코드에서 유의할 점은 메인 메뉴와 서브 메뉴 사이의 간격을 SubHeaderDiv와 SubTabUl 2개를 이용해서 설정했다는 것이다.
우리는 메인 메뉴의 li 태그에 마우스를 호버했을 때 서브 메뉴가 보이도록 할 예정이다. 만약 둘을 합쳐서 SubHeaderDiv에 top: calc(100% + 40px);를 설정하게 되면 메인 메뉴의 span과 SubHeader 사이에 li 태그에 포함되지 않는 40px의 영역이 생기게 된다. 그 이유는 SubHeaderDiv가 absolute position이기 때문이다.
따라서 top: 100%;로 설정함으로써 메인 메뉴와 붙어있는 선에서 최대한 아래로 내려주고, 추가적인 margin을 SubTabUl을 통해 부여하는 것이다.
이제 마우스를 호버했을 때 css를 설정해야 하는데, 메인 메뉴인 일정, 커뮤니티에 호버했을 때 적용해야 한다.
styled-components로 선언한 컴포넌트에도 적용할 수 있다는 걸 알게 되었는데, 아래와 같이 작성한다.
const MenuUl = styled.ul`
...
& > li:hover ${SubHeaderDiv} {
display: block;
}
`
사실 메인 메뉴가 아닌 서브 메뉴에 호버 중일 때도 서브 메뉴가 계속 보여야 하는데, 이에 대해 추가 설정을 할 필요가 없다. 왜냐하면 SubHeader가 메인 메뉴의 li 태그 내에 있기 때문이다.
즉, SubHeader가 보이게 되면 li 태그의 영역이 그만큼 늘어나므로 "SubHeader에 호버 == li 태그에 호버"가 된다.