11. スタイルコンポーネント

スタイルコンポーネント

styled

スタイルコンポーネント名を変数にして設定します。CSSスタイルの設定は `(バッククォーテーション)で囲み、行末は ;(セミコロン) とします。

const スタイルコンポーネント名 = styled `
  CSSスタイル設定
`;

styled()

アイコンなどを設定する styled() も用意されています。

const スタイルコンポーネント名 = styled(値) `
  CSSスタイル設定
`;

コンポーネントを定義

「styled-components」と「material-ui」でコンポーネントを作成します。

styled-components のインポート

「import styled」で「styled-components」をインポート構文が自動入力できます。

SideMenu.js
import styled from "styled-components"

スタイルコンポーネント作成

「SideMenu.js」のメインコンポーネントの外にスタイルコンポーネントを作成します。

「Container」コンポーネント

コンポーネント「Container」を定義し、「div」のスタイルを空欄で設定します。

...

export default SideMenu

const Container = styled.div ``;

「Header」「Icons」コンポーネント

同様に「Header」「Icons」コンポーネントも定義します。

SideMenu.js
const Container = styled.div ``;
const Header = styled.div ``;
const Icons = styled.div``;

アイコン

styled(Avataer)を入力するとアバターアイコンが設定できます。同時に「material-ui」も自動インポートしてくれます。

//自動で挿入される
import { Avatar } from "@material-ui/core"

...

//styled(Avatar)を定義
const UserAvatar = styled(Avatar) ``;

アバターアイコンの追加

UserAvatarにAvatarを定義し、スタイルも設定しておきます。

SideMenu.js
import { Avatar } from "@material-ui/core"
import styled from "styled-components"

function SideMenu() {
    return (
        <div>
            <h2>Side Menu</h2>
        </div>
    )
}

export default SideMenu

const Container = styled.div ``;
const Header = styled.div ``;

const UserAvatar = styled(Avatar) `
    cursor: pointer;
    :hover {
        opacity: 0.8;
    }
`;

コンポーネントの利用

「SideMenu」コンポーネントからdivタグを削除し、「Container」「Header」「UserAvatar」などのコンポーネントを追加します。

SideMenu.js
...
function SideMenu() {
    return (
        <Container>
            <Header>
                <UserAvatar />
				<Icons>
                </Icons>
            </Header>
        </Container>
    )
}
...

アバターアイコンの確認

ブラウザでアバターアイコンを確認してみましょう。

アイコンの表示

「material-icons」のいくつかのアイコンを表示してみます。

ChatIcon

モジュールインポート

「import」を入力します。

importが入力できました。

SildeMenu.js
import moduleName from 'module'

アイコンの設定

続けて「@material-icons/icons/Chat」をインポートします。

モジュール名は「ChatIcon」とします。

SildeMenu.js
import ChatIcon from '@material-ui/icons/Chat';

MoreVertIcon

同様に「MoreVertIcon」アイコンもインポートしておきます。

SildeMenu.js
import MoreVertIcon from '@material-ui/icons/MoreVert'

アイコンボタンのインポート

「material-ui/core」のインポートで「IconButton」を追記します。

SildeMenu.js
import { Avatar, IconButton } from "@material-ui/core"

アイコンコンポーネントの追加

「Icons」タグに「IconButton」「MoreVertIcon」などのアイコンコンポーネントを追加します。

function SideMenu() {
    return (
        <Container>
            <Header>
                <UserAvatar />
                <Icons>
                    <IconButton>
                        <ChatIcon />
                    </IconButton>
                    <MoreVertIcon />
                </Icons>
            </Header>
        </Container>
    )
}

Header コンポーネントのスタイル修正

「Header」コンポーネントのスタイルを修正します。

const Header = styled.div`
    display: flex;
    position: sticky;
    top: 0;
    background: white;
    z-index: 1;
    justify-content: space-between;
    padding: 15px;
    height: 80px;
    border-bottom: 1px solid whitesmoke;
`;

アイコンの確認

「ChatIcon」や「MoreVertIcon」などのアイコンが表示されるか確認してみましょう。

リロードでスタイルが反映されない場合

「styled-components」がリロードで反映されないことがあるので「pages/_document.js」に以下のように追記します。「pages/_document.js」がない場合は新規作成します。

pages/_document.js
import Document, { DocumentContext } 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();
        }
    }
}

_documet.jsとは

「_documet.js」はデフォルトのHTML表示処理を拡張するための機能です。htmlタグやbodyタグをカスタマイズすることができます。

import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

SSRの設定

スタイルコンポーネントをSSR(サーバーサイドレンダリング)するとエラーになることがあります。

Warning: Prop `className` did not match. when using styled components with semantic-ui-react

.babelrcの設定

「.babelrc」ファイルを追加し、「styled-components」のSSRを「true」にします。

{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true }]]
}

Next.jsで作るチャットアプリ