콘텐츠를 작성하기에 앞서 폰트를 먼저 결정하려고 한다.
폰트가 웹 페이지의 인상을 크게 좌우한다고 생각하기 때문에 항상 고르는 데 시간이 걸린다.
포트폴리오 웹 페이지니까 깔끔한 폰트가 좋을 것 같아서 쭉 찾아보다 돌고 돌아 애플로 갔다.
폰트 파일을 다운받아 src/fonts/AppleSDGothicNeo
라는 폴더에 넣어줬다.
CSS를 수정해 웹 페이지의 기본 폰트로 설정해줬다.
/* styles/globals.css */
/* ... */
@font-face {
font-family: 'AppleSDGothicNeo';
src: url(../fonts/AppleSDGothicNeo/AppleSDGothicNeoH.ttf);
font-weight: 900;
}
@font-face {
font-family: 'AppleSDGothicNeo';
src: url(../fonts/AppleSDGothicNeo/AppleSDGothicNeoEB.ttf);
font-weight: 800;
}
/* ... */
html * {
font-family: 'AppleSDGothicNeo';
}
테스트를 위해 Main
이라는 콘텐츠 컴포넌트 하나를 먼저 만들었다.
// components/Main/Main.tsx
const Main = () => {
return (
<div>
<h3 className="text-9xl font-black">안녕하세요.</h3>
<h1 className="text-9xl font-thin">무슨무슨 개발자</h1>
<h3 className="text-lg">누구누구입니다.</h3>
</div>
);
};
export default About;
스타일은 나중에 손 보는걸로 하고, 일단 오늘은 메인 콘텐츠 구역을 잡아준 다음 헤더에 이펙트를 넣어줄 것이다.
우선 메인 콘텐츠들을 모두 같은 div로 감싸서 스타일을 통일시키면 좋을 것 같아 ContentWrapper
라는 공용 컴포넌트를 하나 만들어서 아까 만든 Main
컴포넌트를 감쌌다.
적어도 화면 만큼의 높이가 있어야 하니까 min-h-screen
을 적용했다.
// components/Contents/ContentWrapper.tsx
interface Props {
children: React.ReactNode;
style: string;
}
const ContentWrapper = ({ children, style }: Props) => {
return <div className={`min-h-screen p-[200px] ${style}`}>{children}</div>;
};
export default ContentWrapper;
포트폴리오 페이지에 들어오면 가장 먼저 보게 될 화면이다.
인사말, 키워드, 이름을 배치할 것이고,
추후에 TypeIt이나 슬롯머신 이펙트 같은 효과를 넣어 다양한 키워드를 번갈아가며 보여주려고 한다.
// components/Contents/Main/Main.tsx
import ContentWrapper from '../ContentWrapper';
const Main = () => {
return (
<ContentWrapper style="flex items-center">
<div>
<h3 className="mb-6 text-2xl font-light">안녕하세요.</h3>
<h1 className="mb-4 text-9xl font-thin">무슨무슨 개발자</h1>
<h3 className="text-4xl font-black">누구누구입니다.</h3>
</div>
</ContentWrapper>
);
};
export default Main;
스크롤을 내리면 헤더가 위로 사라지고 올리면 헤더가 다시 나타나는 이펙트를 구현했다.
transition duration-500 ease-in-out
을 통해 이펙트를 부드럽게 만들어줬다.
추가로 z-10
을 통해 헤더가 다른 콘텐츠보다 앞으로 오게 했고, backdrop-blur
를 적용해 헤더가 덮는 콘텐츠들을 blurry하게 보이게 만들었다.
// components/Header/Header.tsx
import { useEffect, useState } from 'react';
import HeaderButton from './HeaderButton';
const Header = () => {
const [scrollY, setScrollY] = useState(0);
const [show, setShow] = useState(false);
useEffect(() => {
function handleScroll() {
setShow(window.scrollY < scrollY);
setScrollY(window.scrollY);
}
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, [scrollY]);
return (
<div
className={`fixed z-10 flex w-full justify-between border-2 border-dashed border-gray-400 px-16 py-8 backdrop-blur transition duration-500 ease-in-out ${
show ? '' : 'transparent'
}`}
>
<div>LOGO</div>
<div>
<HeaderButton text="menu 1" />
<HeaderButton text="menu 2" />
<HeaderButton text="menu 3" />
</div>
</div>
);
};
export default Header;
/* styles/globals.css
/* ... */
.transparent {
transform: translateY(-100%);
}
※ 테스트를 위해 Main
컴포넌트를 여러 개 배치했다.
내일은 다른 콘텐츠들의 레이아웃을 잡아줘야겠다.