こんにちはかみむらです。もしReactベースのフレームワークで、スタイルを構成する場合はCSS in JSライブラリを検討する思います。特に人気なのが、styled-componentsです。最近では採用しているプロダクトが増えてきています。
自分もstyled-componentsを利用する一人ですが、Next.jsで導入する場合少し癖があったので備忘録として残しておきます。
ドキュメント
styled-components: Documentation
styled-componentsのインストール
まずは、ライブラリをインストールします。
$ yarn add styled-components
そして、TypeScriptsに対応する必要があるので、別途インストールが必要です。
$ yarn add -D @types/styled-components
styled-componentsの設定
_documentファイルは通常htmlとbodyを拡張するために使われます。ここではstyled-componentsで出力されるファイルを、Headタグで読み込む設定をしています。これを設定しないと、初期表示でスタイルが読み込まれるのが若干遅れます(Netlifyで観測)。
_documentファイルのドキュメントはこちらです。
Advanced Features: Custom `Document` | Next.js
_document.tsx
import Document, {Html, Head, Main, NextScript} from 'next/document'; import {ServerStyleSheet} from 'styled-components'; type Props = { styleTags: any; }; export default class MyDocument extends Document<Props> { static getInitialProps({renderPage}) { const sheet = new ServerStyleSheet(); const page = renderPage(App => props => sheet.collectStyles(<App {...props} />), ); const styleTags = sheet.getStyleElement(); return {...page, styleTags}; } render() { return ( <Html lang="ja"> <Head> <meta charSet="utf-8" /> {this.props.styleTags} </Head> <body> <Main /> <NextScript /> </body> </Html> ); } }
_document.tsxの書き方はこちらの記事を参考にしました。
Next.js + Styled Components The Really Simple Guide ▲ + 💅 - DEV
babel-plugin-styled-components
そして、styled-componentsのbabelプラグインをインストールします。
$ yarn add -D babel-plugin-styled-components
.babelrcファイルを作成して、下記の設定をして下さい。
.babelrc
{ "presets": [ "next/babel" ], "plugins": [ [ "styled-components", { "ssr": true, "displayName": false, "preprocess": false } ] ] }
displayNameをfalseにしていると、classの命名がランダムな文字列で出力されます。ただ、これはデバッグがしづらいため、もし開発環境で使う場合はtrueにすることをお勧めします。
//displayNameをtrueにした場合 <div class="sc-AykKC itxLzi">test</div> //displayNameをfalseにした場合 <div class="pages__H1-sc-AykKC itxLzi">test</div>
ThemeProviderの利用
styled-componentsにはThemeProviderというAPIがあります。これはContext APIを使って、子のコンポーネントに、propsでスタイルを渡すことができます。これで、スタイルを共通化することができます。ThemeProviderは、_app.jsで使用します。
components/_app.tsx
import { AppProps } from 'next/app'; import { ThemeProvider } from 'styled-components'; import { theme } from '@/styles/theme'; function MyApp({ Component, pageProps }: AppProps) { return ( <ThemeProvider theme={theme}> <Component {...pageProps} /> </ThemeProvider> ); } export default MyApp;
そして、Layout.tsxをインポートします。これでThemeProviderが使えるようになります。
pages/index.tsx
import Layout from '../components/Layout'; const Home = () => { return ( <> <H1>Home</H1> </> ) } const H1 = styled.h1` //propsで、themeのmainにある"red"を渡している color: ${props => props.theme.main} `