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어 쿼리들을 가끔씩 재사용을 할 것입니다. 다음 섹션에서는 상태가 관리가 필요한 컴포넌트를 작업해보도록 하겠습니다.

results matching ""

    No results matching ""