この記事は複数に分かれています。
前回までの記事をご覧になっていない場合はそちらの記事を読んでいただいた方が流れがわかると思います。
Next.jsのプロジェクトでは様々なスタイルの適用方法があります。
今回はCSS in JSの中でも有名なStyled-componentsというものを使用します。
npm install --save styled-components
型定義ように以下もインストールしておきます
npm install --save-dev @types/styled-components
Styled-componentsはサーバーサイドでは動かないためサーバーサイドでも動くように設定をしていきます
npm install --save-dev babel-plugin-styled-components
.babelrcファイルをルートディレクトリ(package.jsonを同じ階層)に作成します。
中に以下を記述
.babelrc
{
"presets": ["next/babel"],
"plugins": [
[
"babel-plugin-styled-components",
{
"ssr": true,
"displayName": true
}
]
]
}
これでStyled-componentsの設定は以上です。
stylesディレクトリの下にGlobalStyles.jsを作成
src > styles > GlobalStyles.js
import { createGlobalStyle } from 'styled-components';
const GlobalStyles = createGlobalStyle`
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
:root{
--primary: #707070;
--subprimary: #DFDFDF;
--blue: #007ACC;
--white : #ffffff;
--black: #000000;
}
html{
font-size: 10px;
height: 100vh;
}
body{
background-color: var(--white);
font-family: 'Roboto Mono';
color: var(--black);
letter-spacing: 0.1em;
}
ul,li{
list-style: none;
}
a{
text-decoration: none;
color: var(--black);
}
img{
width: 100%;
height: 100%;
object-fit: cover;
}
button{
outline: none
}
`;
export default GlobalStyles;
共通のスタイルはここに書いておきます
使用する色はこのように管理しておきます。
:root{
--primary: #707070;
--subprimary: #DFDFDF;
--blue: #007ACC;
--white : #ffffff;
--black: #000000;
}
呼び出し方
color:var(--primary)
var()の中に:rootの内で管理している色を呼び出します
src以下にcomponensディレクトリを作成
componentsの中にLayoutディレクトリを作成
その下に全ページで共通して表示するものを入れていきます
Header.tsxをLayoutディレクトリの下に作成する
src > components > layout >Header.tsx
import Link from 'next/link';
import styled from 'styled-components';
// --------------- Function ---------------
export default function Header() {
return (
<HeaderStyles>
<Link href='/'>
<a>LOGO</a>
</Link>
</HeaderStyles>
)
}
// --------------- Styles ---------------
const HeaderStyles = styled.header`
width: 100%;
height: 60px;
display: flex;
align-items: center;
padding: 0 4rem;
`;
layoutディレクトリの下にFotter.tsxを作成
src > components > layout >Footer.tsx
import styled from 'styled-components';
// --------------- Function ---------------
export default function Footer() {
return (
<FooterStyles>
<p><small>©2021 TestBlog</small></p>
</FooterStyles>
)
}
// --------------- Styles ---------------
const FooterStyles = styled.footer`
width: 100%;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background-color: var(--primary);
color: var(--white);
`;
Layoutはどのページでも共通して表示するものです。
例えばheaderやfooter、お問い合わせのコンポーネントはどのページでも共通して表示してあることが多いと思います。
Layoutを使わない場合はpage以下にあるファイル全てにheaderコンポーネント等をインポートしなければなりせん。
layoutディレクトリ以下にLayout.tsxを作成
src > components > layout >Layout.tsx
import { PropsWithChildren } from 'react';
import GlobalStyles from '../../styles/GlobalStyles';
import Footer from './Footer';
import Header from './Header';
// --------------- Function ---------------
export default function Layout({ children }: PropsWithChildren<any>) {
return (
<>
<GlobalStyles />
<Header />
<main>{children}</main>
<Footer />
</>
);
}
Layoutコンポーネントのpropsをchildrenとして、mainタグの中で呼び出します。
こうすることでLayoutコンポーネントで囲んだ中身がchildrenとしてLayoutに渡されます。
GlobalStylesコンポーネントを呼び出しておくことでスタイルが適用されます。
_app.tsxは全ページに適用させたい処理などを書くときに使用されます
そのため、ここで使用されているコンポーネントをLayoutコンポーネントで囲むことで全ページに適用させます
pages > _app.tsx
import type { AppProps } from 'next/app';
import Layout from '../components/layouts/Layout';
function MyApp({ Component, pageProps }: AppProps) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}
export default MyApp;
トップページに当たるindex.tsxを編集します。
pages > index.tsx
export default function Home() {
return (
<div>
<h1>Hello</h1>
</div>
)
}
とりあえずHelloとだけ表示させておきましょう。
開発サーバーを立ち上げ、headerとfooter、スタイルが適応されていることを確認しましょう
npm run dev
HTMLではheadタグに当たるものがNext.jsにはありません。
そのためサイトタイトルやメタデータを記述するためにはHeadを読み込む必要があります
今回は全ページ共通のHeadを作成するため、Layoutに設置していきます。
src > components > layout >Layout.tsx
// 追加
import Head from 'next/head';
import { PropsWithChildren } from 'react';
import GlobalStyles from '../../styles/GlobalStyles';
import Footer from './Footer';
import Header from './Header';
// --------------- Function ---------------
export default function Layout({ children }: PropsWithChildren<any>) {
return (
<>
<Head>
<title>Next Blog</title>
<meta name='description' content='Generated by create next app' />
<link
rel='icon'
href='https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/apple/285/whale_1f40b.png'
/>
</Head>
// 省略
</>
);
}
Headコンポーネントの中にHTMLで書いているのと同じように記述することができます。
faviconはこちらのサイトを使用させていただいています。
画像のURLをコピーして貼り付けています。
今回から本格的に作成に入っていきました。
これから少し難しくなりますが、頑張りましょう。