3-3. 헤더와 레이아웃
복잡한것들을 시작하기전에, 매우 간단한것들을 먼저 시작하겠습니다. 이번 섹션에선 프로젝트의 헤더와 레이아웃을 잡아보겠습니다.
헤더 만들기
헤더는 이번 프로젝트에서는 기능상 중요한 역할을 하지 않습니다. 그냥 달려있을 뿐이죠.
src/components/Header.js
import React from 'react';
import styled from 'styled-components';
import oc from 'open-color';
const Wrapper = styled.div`
/* 레이아웃 */
display: flex;
position: fixed;
align-items: center;
justify-content: center;
height: 60px;
width: 100%;
top: 0px;
z-index: 5;
/* 색상 */
background: ${oc.indigo[6]};
color: white;
border-bottom: 1px solid ${oc.indigo[7]};
box-shadow: 0 3px 6px rgba(0,0,0,0.10), 0 3px 6px rgba(0,0,0,0.20);
/* 폰트 */
font-size: 2.5rem;
`;
const Header = () => (
<Wrapper>
memo
</Wrapper>
);
export default Header;
그 다음엔, App 컴포넌트에서 이를 렌더링하세요.
src/containers/App.js
import React, { Component } from 'react';
import Header from 'components/Header';
class App extends Component {
render() {
return (
<div>
<Header/>
</div>
);
}
}
export default App;
조금은 밋밋한가요? 그렇다면, 구글 폰트에서 좀 더 멋진 폰트를 골라서 설정해보겠습니다.
index.css 파일에서 웹폰트를 불러오세요.
이 과정에서, 다른 기본적인 스타일 설정도 해주겠습니다.
box-sizing
값을 border-box
로 설정하여 추후 사이즈 지정을 좀 더 용이하게 하고, 배경색도 설정해주겠습니다.
@import url('https://fonts.googleapis.com/css?family=Baloo');
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background: #e9ecef;
box-sizing: border-box;
}
* {
box-sizing: inherit;
}
이제, Header 의 스타일 설정에 다음 라인을 추가하세요.
src/components/Header.js
const Wrapper = styled.div`
(...)
font-family: 'Baloo', cursive
`;
헤더가 좀 더 개성있게 변했습니다!
레이아웃 구성하기
현재 헤더가 fixed
로 설정이 되어있으니, 헤더 하단에 텍스트를 입력하게 된다면 텍스트가 가려질 것입니다.
따라서, 레이아웃 컴포넌트를 만들어서 상단 여백을 헤더 크기만큼 설정하겠습니다.
src/components/Layout.js
import React from 'react';
import styled from 'styled-components';
const Wrapper = styled.div`
padding-top: 60px; /* 헤더 높이 */
`;
const Layout = ({children}) => (
<Wrapper>
{children}
</Wrapper>
);
export default Layout;
그 다음엔, 이를 App 에서 렌더링하겠습니다.
최상위 <div>
태그 대신에 이 레이아웃 컴포넌트를 렌더링하세요.
src/containers/App.js
import React, { Component } from 'react';
import Header from 'components/Header';
import Layout from 'components/Layout';
class App extends Component {
render() {
return (
<Layout>
<Header/>
hello
</Layout>
);
}
}
export default App;
텍스트가 헤더 바로 하단에 잘 나타나는지 확인하세요.
메인 레이아웃 구성하기
내용을 화면의 중앙에 정렬하고, 화면의 크기에 따라 사이즈가 조정되는 메인 레이아웃을 만들어보겠습니다.
우선, Layout
컴포넌트에 멤버변수를 만들어서 Main
컴포넌트를 만들어보세요.
src/components/Layout.js
import React from 'react';
import styled from 'styled-components';
const Wrapper = styled.div`
padding-top: 60px; /* 헤더 높이 */
`;
const Layout = ({children}) => (
<Wrapper>
{children}
</Wrapper>
);
Layout.Main = styled.div`
margin: 0 auto;
margin-top: 2rem;
width: 1200px;
position: relative;
background: gray;
`;
export default Layout;
현재 회색 배경은 크기가 제대로 설정되는지 확인하기 위하여 임시로 설정하였습니다. 이제 이 컴포넌트를 App 컴포넌트에서 렌더링해주겠습니다.
import React, { Component } from 'react';
import Header from 'components/Header';
import Layout from 'components/Layout';
class App extends Component {
render() {
return (
<Layout>
<Header/>
<Layout.Main>hello</Layout.Main>
</Layout>
);
}
}
export default App;
가운데에 잘 정렬이 되었지요? 하지만 브라우저 크기를 줄이면 크기가 잘립니다. 이를 미디어 쿼리를 통하여 개선을 해보도록 하겠습니다.
반응형 디자인을 위한 미디어쿼리 준비하기
미디어 쿼리에서 사용되는 코드를 모듈화 하여 src/lib/style-utils.js 에 저장하도록 해보겠습니다.
src/lib/style-utils.js
import { css } from 'styled-components';
export const media = ({
desktop: (...args) => css`
@media (max-width: 1200px) {
${ css(...args) }
}
`,
tablet: (...args) => css`
@media (max-width: 992px) {
${ css(...args) }
}
`,
mobile: (...args) => css`
@media (max-width: 600px) {
${ css(...args) }
}
`
});
우리는 디바이스 사이즈를 4종류로 나뉘었습니다. 기본적으로는 해상도가 1200px 이상인 디바이스로 작업을 하고, 그 다음에 1200px 미만은 desktop, 1024px 미만은 tablet, 600px 미만은 mobile 로 분류를 하여 작업을 해보도록 하겠습니다.
이제 메인 레이아웃에서 다음과 같이 사용을 해보세요.
반응형 디자인 적용하기
src/components/Layout.js
import React from 'react';
import styled from 'styled-components';
import { media } from 'lib/style-utils';
const Wrapper = styled.div`
padding-top: 60px; /* 헤더 높이 */
`;
const Layout = ({children}) => (
<Wrapper>
{children}
</Wrapper>
);
Layout.Main = styled.div`
margin: 0 auto;
margin-top: 2rem;
width: 1200px;
transition: all .3s;
position: relative;
background: gray;
${media.desktop`
width: 990px;
`}
${media.tablet`
margin-top: 1rem;
width: calc(100% - 2rem);
`}
${media.mobile`
margin-top: 0.5rem;
width: calc(100% - 1rem);
`}
`
export default Layout;
애니메이션 효과를 주기 위하여 transition
도 설정을 해주었습니다. 한번 제대로 작동하는지 확인해볼까요?
widescreen
desktop
tablet
mobile
잘 되는군요! 이제 앞으로 이 미디0어 쿼리들을 가끔씩 재사용을 할 것입니다. 다음 섹션에서는 상태가 관리가 필요한 컴포넌트를 작업해보도록 하겠습니다.