###### 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の併用
```