프로젝트를 개발 중 메뉴 밑줄 슬라이딩을
자연스럽게 구현하고 싶어 정리해 보았습니다.
용어 설명
메뉴 밑줄 슬라이딩을 구현하고 싶은데 어떻게 만들어야 할지 막막하다면 여기서 정리한 내용만 차근차근 읽어보시면
어떻게 구현하고 어떤 방식으로 만들 수 있는지 이해하실 수 있습니다.
특정 메뉴로 이동하고 싶을 때 애니메이션을 적용하고 싶다면 offset 이라는 기능을 사용하시면 됩니다.
그림에서 보시는 바와 같이 검정색 화면이 브라우저 화면이라고 가정해 봅시다.
그럴 때 브라우저에서 내가 측정하고 싶은 요소와 브라우저 간의 거리를 확인하고 싶다면 offsetTop 을 이용하시면 됩니다.
이 기능을 이용해서 간편하게 구현하시면 됩니다.
아래의 코드는 React 를 이용해서 구현한 코드입니다.
아직은 tsx 로 넘어가지 않았으니 tsx 를 이용한 메뉴 슬라이드 애니메이션을 보고 싶다면 아래 코드는 넘어가시면 됩니다.
구현
css
.navbar {
display: flex;
margin-bottom: 40px;
}
.navbar p {
font-size: 30px;
margin: 10px;
}
.horizontal-underline {
position: absolute;
height: 4px;
background-color: pink;
transition: all 1s;
}
react
import { useRef } from 'react';
const Navbar = () => {
const underlineRef = useRef(null);
const horizontalIndicator = (e) => {
const target = e.target;
const current = underlineRef.current;
if (underlineRef.current && e.target) {
current.style.left = `${target.offsetLeft}px`;
current.style.width = `${target.offsetWidth}px`;
current.style.top = `${target.offsetHeight + target.offsetTop}px`;
}
};
return (
<div className="navbar">
<div className="horizontal-underline" ref={underlineRef}></div>
<p onClick={horizontalIndicator}>home</p>
<p onClick={horizontalIndicator}>about</p>
<p onClick={horizontalIndicator}>login</p>
</div>
);
};
export default Navbar;
React 에서는 이렇게 직접 event 라는 것을 통해 해당 요소의 target 으로 접근해 offset 기능을 이용하시면 됩니다.
또한 React 는 요소에 직접적으로 style 에 접근할 수 없기 때문에 useRef 라는 hook 을 통해서 접근하시면 손쉽게
메뉴 슬라이드 애니메이션을 구현하실 수 있습니다.
추가적으로 만약 tsx 로 작업하고 계신 중이시라면 아래 코드처럼 만들어 주시면 됩니다.
위에 코드와 달리 useEffect 를 추가한 이유는 페이지가 처음 렌더링 돼었을 때 home 이라는 p 태그에 바로 underline
을 추가하기 위해서 입니다.
import { useRef, useEffect } from 'react';
const Navbar: React.FC = () => {
const underlineRef = useRef<HTMLDivElement | null>(null);
const homeRef = useRef<HTMLParagraphElement | null>(null);
useEffect(() => {
const current = underlineRef.current;
const home = homeRef.current;
if (current && home) {
current.style.left = `${home.offsetLeft}px`;
current.style.width = `${home.offsetWidth}px`;
current.style.top = `${home.offsetHeight + home.offsetTop}px`;
}
}, []);
const horizontalIndicator = (e: React.MouseEvent<HTMLParagraphElement>) => {
const target = e.target as HTMLParagraphElement;
const current = underlineRef.current;
if (current && target) {
current.style.left = `${target.offsetLeft}px`;
current.style.width = `${target.offsetWidth}px`;
current.style.top = `${target.offsetHeight + target.offsetTop}px`;
}
};
return (
<div className="navbar">
<div className="horizontal-underline" ref={underlineRef}></div>
<p ref={homeRef} onClick={horizontalIndicator}>
home
</p>
<p onClick={horizontalIndicator}>about</p>
<p onClick={horizontalIndicator}>login</p>
</div>
);
};
export default Navbar;
'React' 카테고리의 다른 글
React 에러 핸들링 (0) | 2024.09.10 |
---|---|
React 에서 formData 다루기 (0) | 2024.08.21 |
useId (0) | 2024.08.19 |
useLayoutEffect (0) | 2024.08.13 |
React-throttle (0) | 2024.08.12 |