yarn add styled-components
yarn add @types/styled-components -D
로 설치한다. @types/styled-components를 설치해야 타입스크립트에서 스타일드 컴포넌츠를 자동완성 할 수 있다.
스타일드 컴포넌트를 ssr에 적용하면 새로고침할 때에 스타일이 적용되지 않는 문제가 발생할 수 있다. _document.tsx를 확장하여 문제를 해결할 수 있다.
pages/_document.tsx는 아래와 같은 형태를 가진다.
import { Html, Head, Main, NextScript } from "next/document";
export default function Document() {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
next js 공식문서 예제와 블로그 글를 참조하여 아래와 같이 수정한다.
import Document from "next/document";
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
}
yarn add babel-plugin-styled-components
를 통해 babel 플러그인을 설치해주자.
루트 폴더에 .babelrc를 아래와 같이 추가해준다
{
"presets": ["next/babel"],
"plugins": [
[
"babel-plugin-styled-components",
{
"ssr": true,
"displayName": true //개발 모드일 때에 stled-components 클래스명 확인할 수 있도록
}
]
]
}
components폴더에 GlobalStyle.ts 파일을 만들었다.
그리고 아래와 같이 스타일드 컴포넌트의 GlobalStyle을 만들어서 적용하였다.
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
`;
export default GlobalStyle;
CSS스타일은 에릭 메이어의 reset css 2.0 버전이다.
pages/_app.tsx
를 만들어 아래와 같이 글로벌 스타일을 정의한다.
CRA로 했을 때의 코드
import '@/styles/globals.css'
import type { AppProps } from 'next/app'
export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
직접 정의한 코드 (자동완성이 되지 않아 vscode 확장에서 npm Intellisense를 설치하였음.)
import App, { AppProps } from "next/app";
import GlobalStyle from "../styles/GlobalStyle";
const app = ({ Component, pageProps }: AppProps) => {
return (
<>
<GlobalStyle />
<Component {...pageProps} />
</>
);
};
나눔 스퀘어를 적용해보도록 하자.
먼저 pages/_document.tsx에서 render()를 추가해주어야 한다.
import Document, { Html, Main, NextScript } from "next/document";
import Head from "next/head";
import { ServerStyleSheet } from "styled-components";
export default class MyDocument extends Document {...;
} finally {
sheet.seal();
}
}
render() {
return (
<Html>
<Head>
<link
rel="stylesheet"
type="text/css"
href="https://cdn.jsdelivr.net/gh/moonspam/NanumSquare@2.0/nanumsquare.css"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
이후 GlobalFontFamily.ts라는 새로운 스타일을 만들자.
import { css } from "styled-components";
const GlobalFontFamily = css`
body {
font-family: "NanumSquare", sans-serif;
}
.font-weight-400 {
font-weight: 400;
}
.font-weight-700 {
font-weight: 700;
}
.font-weight-800 {
font-weight: 800;
}
.font-weight-300 {
font-weight: 300;
}
`;
export default GlobalFontFamily;
기존에 있던 css reset 부분도 GlobalResetStyle이라는 새로운 ts파일로 분리하자.
import { css } from "styled-components";
const GlobalResetStyle = css`
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
`;
export default GlobalResetStyle;
이후 아래와 같이 resetStyle를 먼저 넣어주고, fontFamily를 나중에 넣어주면 된다.
import { createGlobalStyle } from "styled-components";
import GlobalFontFamily from "./GlobalFontFamily";
import GlobalResetStyle from "./GlobalResetStyle";
const GlobalStyle = createGlobalStyle`
${GlobalResetStyle}
${GlobalFontFamily}
`;
export default GlobalStyle;
``