헤더 navbar에서 메뉴 버튼을 클릭하면 해당 위치로 이동하는 anchor link 기능을 구현했다.
아주 간단하다.
가장 먼저 html
태그에 scroll-behavior: smooth
라는 CSS 속성을 부여해야 한다.
/* styles/globals.css */
html {
scroll-behavior: smooth;
}
이 속성을 부여하면 유저가 직접 스크롤하는 경우가 아니라 navigation (e.g. a
태그) 또는 스크롤 API 호출로 인한 스크롤 동작이 부드러워진다.
a
태그로 링크를 걸었다면 문제 없이 동작하지만,
Next.js의 Link
컴포넌트를 사용했다면 scroll={false}
를 추가해야 한다.
// components/Header/HeaderButton.tsx
import Link from 'next/link';
interface Props {
name: string;
}
const HeaderButton = ({ name }: Props) => {
return (
<Link href={`#${name}`} scroll={false}>
<button className="px-4 capitalize">{name}</button>
</Link>
);
};
export default HeaderButton;
이렇게 해야 하는 이유는 Link
의 특성 때문이다.
페이지 이동 시 스크롤을 맨 위로 올리는 게 Link
컴포넌트의 default scroll behavior이기 때문에,
scroll={false}
를 통해 이 default scroll behavior를 override하겠다는 의사를 밝혀야 한다.
링크 버튼에 보여지는 이름은 text-transform: capitalize
속성을 통해 capitalize했다.
Link
와 목적지 div
를 연결해주는 값은 id
이다.
예를 들어, Link
의 href
속성에 #123
이라는 값을 넣어주면,
123
이라는 id
를 가진 div
와 해당 Link
가 연결된다.
현재 모든 섹션이 ContentWrapper
컴포넌트 단위로 나뉘어지기 때문에,
Props
에 id
를 추가해주고 섹션마다 id
값을 다르게 전달해주면 된다.
// components/Contents/ContentWrapper.tsx
interface Props {
id: string;
children: React.ReactNode;
style?: string;
}
const ContentWrapper = ({ id, children, style }: Props) => {
return (
<div id={id} className={`min-h-screen px-[200px] py-[200px] ${style}`}>
{children}
</div>
);
};
export default ContentWrapper;
// components/Contents/Main/Main.tsx
/* ... */
const Main = () => {
return (
<ContentWrapper id="main" style="flex items-center">
<div className="w-full">
<h3 className="mb-6 text-2xl font-light">안녕하세요.</h3>
<SlotMachine textData={textData} />
<h3 className="mt-4 text-4xl font-black">누구누구입니다.</h3>
</div>
</ContentWrapper>
);
};
export default Main;
사실 scroll-behavior: smooth
도, text-transform: capitalize
도 오늘 처음 알게 된 CSS 속성이다.
JS로 직접 어렵게 구현할 필요 없이 이런 꿀같은 CSS를 활용한다면 시간도 절약되고 성능 면에서도 더 좋을 거라고 생각한다. (내가 만든 기능 vs 전세계의 석학들이 모여 전세계 개발자들을 위해 만든 기능)
아무리 단순한 기능이라도, 이미 구현 방법을 알고 있는 기능이라도 몇 분만 더 투자해서 조금만 더 깊이 검색해본다면 더 좋은 방법, 각 방법의 장단점, 차이점 등 추가로 배울 점이 항상 있다고 생각한다.
다음은 다크 모드 기능을 구현할 것이다.