###### tags: `Next.js` `linaria` # Next.js のcss ## 目次 * グローバルなcss * コンポーネントレベルのcss - CSS Modules - CSS-in-JS - Styled JSX (Next.jsデフォ対応) - Styled Components - emotion - Linaria (zero runtimeライブラリ) <br><br> # グローバルなcss `pages/_app.js` 内で CSS ファイルをimportする。scssはyarn add すれば使えるようになります。 ```javascript= import '../styles.css'; export default function MyApp({ Component, pageProps }) { return <Component {...pageProps} />; } ``` ### css内の変数、mixinなど jsで書き直したファイルをexport / import してやればOK. variables.ts ```typescript= export const black = '#000' export const red = '#f30' ``` global.ts ```typescript= import * as v from '@/s/m/variables' ``` ### 補足 パスのエイリアス定義 tsconfig.jsonでパスを定義できる ```diff= { "compilerOptions": { ~ + "paths": { + "@/p/*": ["src/pages/*"], + "@/s/*": ["src/styles/*"], + "@/s/m/*": ["src/styles/modules/*"], + "@/c/a/*": ["src/components/atoms/*"], + "@/c/m/*": ["src/components/molecules/*"], + "@/c/o/*": ["src/components/organisms/*"], + "@/c/l/*": ["src/components/layout/*"], + "@/img/*": ["public/images/*"], + "@/data/*": ["src/data/*"] + } }, ~ } ``` <br><br> # コンポーネントレベルのcss 代表的な手法の分類は以下で、下記のどの方法もスタイルがスコープ付けられる。 <br> - CSS Modules - CSS-in-JS - Styled JSX (Next.jsデフォ対応) - Styled Components - emotion - Linaria (zero runtimeライブラリ) <br> ## CSS Modules **コンポーネントファイルとcssファイルが別**。 `hoge.modules.css`と命名したcssファイルをコンポーネント側でimportする(scss可) **メリット** - 公式が推奨している - デフォルトのビルトインサポート対象になってい - パフォーマンス面で優れている - これまでのcssに近い形で記述できる - コンポーネントを跨ぐCSS共通化が難しい **デメリット** - 大規模になればなるほど(or コンポーネントを細分化すればするほど)、ファイル数が増大して管理ハードルが上がる - いずれは depcrecated にしたいってvercelの中の人がいってる? **src/index.jsx** ```jsx import Head from 'next/head' import classes from 'src/styles/Home.module.css' import { Footer } from "src/components/Footer" import { Main } from 'src/components/Main' import { Header } from 'src/components/Header' const Home: NextPage = () => { return ( <> <Head> <title>ワワワNext.jsデモサイト</title> </Head> <Header /> <Main /> <Footer /> </> ) } export default Home ``` <br> **src/components/Header/index.jsx** ```jsx import classes from 'src/components/Header/Header.module.css' export function Header() { return ( <header className={classes.header}> ヘッダー </header> ) } ``` <br> **src/components/Header/Header.module.css** ```css .header { width: 100%; height: 100px; border-bottom: 1px solid #eaeaea; } ``` サンプル https://github.com/naito-junya/study-next/tree/main/src/ <br><br> ## CSS-in-JS **1ファイルで1つのコンポーネントとして管理する**ことができる。 インラインスタイルを含む、js内にcssを記述する手法の総称。  例 - Styled JSX (デフォでサポート対象) - Styled Components - emotion **メリット** - 1ファイルで1つのコンポーネントが完結 - propsを用いて動的にスタイルの変更が可能 **デメリット** - パフォーマンス面で劣る ```スタイルに関係するCSSOM Treeを構築するステップの手前に、ロジックが混ざったjsのScriptingのステップを挟む必要が出てきてしまい、いわゆるブロッキング状態が起こらざるを得なくなってしまう点。``` ##### propを用いたスタイル変更 ```jsx export const Nav = () => { return ( <> <Title>タイトル</Title> <Title color='#ff3300'>あかいタイトル</Title> <Title color='blue'>あおいタイトル</Title> </> ) } const Title = styled.div` font-size: 16px; color: ${(props) => (props.color ? props.color : '#000')}; ``` <br><br> ### 1.styled-jsx (デフォルト) コンポーネント内に`<style jsx>{``}</style>` でラップしてstyleを記述する方法 - 可読性にかける ```javascript= export default function Home() { return ( <div className="container"> <h1 className="title">hoge</h1> <style jsx>{` .container { width: 100%; } @media (max-width: 600px) { .container { width: 85%; } } `}</style> <style jsx global>{` html, body { padding: 0; margin: 0; } * { box-sizing: border-box; } `}</style> </div> ); } ``` ### 2.styled-component (ライブラリ) ```jsx const Font = styled.p`  //・・・タグを指定(ここではpタグ) font-size: 16px; `; <Font>テキストテキストテキストテキストテキスト</Font> ``` 参考 https://zenn.dev/nbr41to/articles/c0c691653e3d55 ### 3.emotion (ライブラリ) ```jsx //<Emotionの記述例> const color = css` color: red; `; <p css={color}>テキストテキストテキストテキストテキスト</p> //・・・クラス名を付与する方法に近い ``` 参考 https://zenn.dev/iwakin999/articles/7a5e11e62ba668 ※@emotion/styledを使用するとstyled-componentsと同じ書き方でできる Emotionがタグやコンポーネントにcss propを使うため、JSX→JavaScriptのコンパイル設定を調整する必要がある `.babelrc` を作成して下記を設定 ``` { "presets": [ [ "next/babel", { "preset-react": { "runtime": "automatic", "importSource": "@emotion/react" } } ] ], "plugins": ["@emotion/babel-plugin"] } ``` <br> #### [参考] Next.jsデフォトップページをstyled-componsnt / emotionでそれぞれで書きかえてみた > https://github.com/satoshiiiiii/next-ts-styledcomponents/blob/main/pages/index.tsx > https://github.com/satoshiiiiii/next-ts-emotion/blob/main/pages/index.tsx <br> ### 個人的な所感 - 最初は慣れなかったけどstyled component がスッキリしてやりやすい - import したコンポーネントとstyled componentがパッと見だと区別がつかないが、コンポーネントの粒度の問題かと <br><br> ## Linaria (ライブラリ) Linaria とは > Write CSS in JS, but with zero runtime, CSS is extracted to CSS files during build >CSS in JS の形式で実装できるものの、ビルドした後は別ファイルの CSS ファイルとして書き出される **メリット** - ビルド時にcssファイルとして吐き出される - 抽出されたcss分だけjsが減る → ページ実行時のjs量が減る - そのためパフォーマンス面で優れている - styled(前述したstyled-componentsとほぼ同様の書き方)記法とcss(前述したemotionとほぼ同様の書き方)記法の2種類がある - トータルのファイルサイズが減るという説もある  **デメリット** - ファイル抽出をするためビルド時間が長くなる <br><br> <br><br> ``` - チームとしてはLinariaの利用で進める - tailwind.cssの併用 ```