【Next.js + Tailwind】これを押さえればOK 最新のフロントエンド開発

#目次
[1.この記事を書くきっかけ](#1-この記事を書くきっかけ)
[2.自己紹介](#2-自己紹介)
[3.この記事を見てほしい人](#3-この記事を見てほしい人)
[4.Reactについて](#4-reactについて)
[5.Next.js + Tailwind cssの導入方法](#5-nextjstailwind-cssの導入方法)
[6.Tailwind css](#6-tailwind-cssについて)
[7.スクロールアニメーション](#7-スクロールアニメーション)
[8.Next.jsのImageについて](#8-nextjsのimageについて)
[9.おわり](#9-おわり)
[10.おまけ](#10-おまけ)

#1. この記事を書くきっかけ
fwywdという会社の１次試験でQiitaに記事を投稿するという試験があり、書くことになりました。

初めて記事を書くので、ご不明な点等があるかもしれませんが、できるだけ詳しく書いていくので、どうぞよろしくお願いいたします。

#2. 自己紹介
私はhtml css を３カ月前に勉強し始めたばかりの学生です。

Tailwind css歴は２カ月程度ですが、こんな私でもfwywdの一次試験のサイト制作が合格したので、ぜひ参考にしていただければ幸いです。

#3. この記事を見てほしい人
- Reactを触ったことがある人(jsx記法、コンポーネント化)
- cssを触ったことがある人(hover、レスポンシブ対応)
- Tailwind cssを触ったことがない人
- fwywdの一次試験に応募したい人

#4. Reactについて
ReactはNext.jsのもとになるものですが、説明については割愛させていただきます。
こちらの動画で詳しく解説しています。

https://www.udemy.com/course/react_stepup/

https://www.udemy.com/course/modern_javascipt_react_beginner/

#5. Next.js+Tailwind cssの導入方法
##nodeについて

nodeは必須なので、入っていない方はこちらの記事を参考にしてください

https://qiita.com/sefoo0104/items/0653c935ea4a4db9dc2b

すでにnode、npmかyarnが入っている方

https://fwywd.com/tech/next-tailwind

https://tailwindcss.com/docs/guides/nextjs

##vscode
vscodeが入っていない方は、インストールすることを強くお勧めします。

https://www.javadrive.jp/vscode/install/index1.html

https://qiita.com/ucan-lab/items/e85931bf8276da43cc97

###個人的におすすめな拡張機能
####絶対に必要
- Japanese Language Pack ( 日本語になる )
- Tailwind CSS intelliSense ( 補完機能 )
- Error Lens ( エラーの内容が表示される )
- ESLint ( 構文エラーがわかる )

####あると便利
- Auto Rename Tag ( 開始タグ、終了タグの片方を自動補完 )
- Git History ( git使うときに便利 )
- indent-rainbow ( 空白に色がついて、まとまりがわかりやすい )
- HTML CSS Support ( 補完機能 )
- HTML Snippets ( 補完機能 )

#6. Tailwind cssについて
生のcssの説明については割愛させて頂きます。

##基本的な使い方
Tailwind css は、HTMLのタグにクラスを与えることで、スタイルが付加されます。

Bootstrapを触ったことがある人なら、すぐに慣れると思います。

cssのコード

```
h1{
font-size:30px;
color:#535353;
width:100%;
height:50%;
}
```

Tailwind cssのコード

```
<h1 className="text-[30px] text-[#535353] w-full h-[50%] ">Hello Tailwind</h1>
```
![S__22822919.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2263510/ece31962-ef52-39a5-2f77-d54a0c819398.jpeg)


このように、必要なスタイルに応じたクラスを、つけ足していきます。

下のサイトはTailwind cssを使う上で必須なサイトで、サイトの上部の ”Search” に当てたいcssを入力するとTailwindのクラスに直してくれます。


https://tailwindcomponents.com/cheatsheet/

例
background-color

結果
bg-red-50
bg-red-100
・
・
・


:::note alert
ファイルのtailwind.config の設定を mode:"jit"にしないと、[ ]を使った書き方はできません。
:::
##基本的なクラス

```
padding -> p
margin  -> m　
width   -> w
height  -> h

例
padding:10px;     -> p-[10px]
padding-left:10%; -> pl-[10%]
margin:10px;      -> m-[10px]
margin-left:10%;  -> ml-[10%]
width:100px       -> w-[100px]
width:100%        -> w-full か w-[100%]
height:2em        -> h-[2em]
height:100vh      -> h-[100vh]

font-size:100px;  -> text-[100px]
font-family:bold; -> font-bold

color:red;     -> text-red-500
color:#92400E; -> text-[#92400E]

background-color:red;    -> bg-red-500
background-color:#92400E -> bg-[#92400E]

border:2px solid black; -> border-2 border-black border-solid
border-radius:100px;    -> rounded-[100px]

text-align:center; -> text-center
text-align:left    -> text-left

float:left;  -> float-left
float:right; -> float-right

opacity:0.1; -> opacity-10
opacity:1;   -> opacity:100
opacity:0.54 -> opacity-[54%]

display:none;         -> hidden
display:block;        -> block
display:inline;       -> inline
display:inline-block; -> inline-block
display:flex;         -> flex
display:grid;         -> grid

position:relative; ->relative
position:absolute; -> absolute
position:fixed;    -> fixed
position:static;   -> static

```

基本的なcss はこのようなクラスを書くことで、同等のスタイルになります。

これを見て、「案外、複雑じゃないかも！」と思えたら、すぐにTailwind cssをマスターできるはずです。

##hover activeについて
次に、hoverやactiveについてです。

Tailwind cssではクラスの前に hover: とつけるだけで、hoverしたときのスタイルになります。
しかし、ひとつひとつにhover:をつける必要があるところがデメリットです。

試しにこちらのコードを読み込んでみてください。

```
<button className="py-[10px] px-[20px] border border-black duration-300 hover:text-white hover:bg-black hover:translate-y-[-10px] hover:rotate-[360deg] hover:scale-150">Hover me!</button>
```
通常
![S__22822921.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2263510/a5730575-879b-01f3-24e9-72db56c77ca8.jpeg)

hoverした時
![S__22822922.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2263510/f4ae92ce-fe50-0afe-039c-b15c3ed4884d.jpeg)


hoverしたときにボタンが動いたでしょうか？
ここに書いてある hover: で始まるクラスは、全てhoverしたときに発火します。

hover:p-10　hover:m-10　hover:text-black　hover:hidden　のように、ほとんどのクラスをhoverにあてることができます

activeについても同様で、先ほどのコードのhoverの部分をactiveに変えるだけで、クリックしている間だけ発火させることができます。

```
<button className="py-[10px] px-[20px] border border-black duration-300 active:text-white active:bg-black active:translate-y-[-10px] active:rotate-[360deg] active:scale-150">Click me!</button>
```

また、このクラスの中に duration-300とありますが、これはcssでいうtransition:0.3sと同じスタイルになるので、hoverやactiveを使うときには必ずつけましょう

###レスポンシブについて
レスポンシブデザインは、cssでは

```
@media (min-width: 600px) {
	/* 画面の横幅が600px以上で適用 */
}
@media (min-width: 1000px) {
	/* 画面の横幅が1000px以上で適用 */
}
```
のように書きます。

Tailwind cssの場合では、hover: active:と似た書き方になります。

```
<button className="py-[10px] px-[20px] border border-black block sm:hidden md:block lg:hidden xl:block 2xl:hidden"> responsive BTN </button>
```


![S__22822934.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2263510/b4b51738-896c-a4a0-15f2-bbac8cee407e.jpeg)


![S__22822936.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2263510/36b25f7f-824d-f119-9723-5248294b67f8.jpeg)

![S__22822937.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2263510/d7189171-f736-c3cf-d240-254c7c0dc157.jpeg)


![S__22822938.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2263510/68a12e9c-e1ed-78d6-6353-0b06d75a1e88.jpeg)


![S__22822939.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2263510/80d6c01a-46fd-bcdf-a85b-dc81e6c596c0.jpeg)


![S__22822940.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2263510/e333018d-5b3f-21ed-7ca1-546e3dbf98a5.jpeg)




画面の横幅を変えることで、このボタンは出たり消えたりします。

このsm:　のように書いたものはデフォルトで、以下のようになります。

| BreackPoint | min-width | CSS |
|:------------|----------:|:------------:|
| sm          | 640px     | @media (min-width: 640px) { ... }  |
| md          | 768px     | @media (min-width: 768px) { ... }  |
| lg          | 1024px    | @media (min-width: 1024px) { ... } |
| xl          | 1280px    | @media (min-width: 1280px) { ... } |
| 2xl         | 1536px    | @media (min-width: 1536px) { ... } |

```
<p className="text-[10px] sm:text-[100px]"> Big </p>
```
このコードの場合、sm(640px)になるまで text-[10px]の状態でいて、sm(640px)を超えた時に text-[100px]の状態になります。

#7. スクロールアニメーション
スクロールアニメーションをつけると、それだけでとても高度なサイトに見せることができます。

生のJavaScriptでやると、

```
        const els = document.querySelectorAll(".new-Animation");
        const cb = function (entries, observer) {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    entry.target.classList.add("fadeIn");
                    //observer.unobserve(entry.target);
                } else {
                    entry.target.classList.remove("fadeIn");
                }
            });
        }
        const options = {
            root: null,
            rootMargin: "0px 0px",
            threshold: 0
        };
        const io = new IntersectionObserver(cb, options);
        els.forEach(el => io.observe(el));
```

このような書き方になると思います。ですが、Next.jsはReactなのでdom操作は推奨されていません。

そこで、react-intersection-observerというライブラリを使うと、簡単に実装することができます。

以下のサイトでわかりやすく説明しています。

https://qiita.com/masaki632d/items/090e5f3e7ac70a816681

https://zenn.dev/himorishige/articles/e17b7d04fc7722

##スクロールアニメーションのコンポーネント化
また、スクロールアニメーションを導入する際におススメするのが、スクロールアニメーションの動作をコンポーネント化して、動作させたい要素ごとに呼び出す方法です。

その方法は、まず、react-intersection-observerをインストールします。

そして、プロジェクトの直下にcomponentsフォルダを作り、ここではFadeIn.jsxを作ります。

```
components
　FadeIn.jsx
pages
  api
  _app.js
  index.js
```

FadeIn.jsxに以下を書きます。

```
import { useInView } from 'react-intersection-observer';

export const FadeIn = ({ children }) => {
    const { ref, inView } = useInView({
        // オプション
        rootMargin: '-50px', // ref要素が現れてから50px過ぎたら
        triggerOnce: true, // 最初の一度だけ実行
    });

    return (
        <div
            ref={ref}
            className={`${inView ? "opacity-100" : "opacity-0 translate-y-[50%]"} duration-[1s]`}
        >
            {children}
        </div>
    )
}
```
そしたら、index.jsに以下を書くとスクロールアニメーションが実行できます。

```
import { FadeIn } from '../components/FadeIn';

export default function Home() {
  return (
    <div>
      <FadeIn>
        <h1 className="my-[300px] text-[100px]">fadein</h1>      
      </FadeIn>
      <FadeIn>
        <h1 className="my-[300px] text-[100px]">fadein</h1>      
      </FadeIn>
      <FadeIn>
        <h1 className="my-[300px] text-[100px]">fadein</h1>      
      </FadeIn>
    </div>
  )
}
```
このように＜FadeIn＞＜/FadeIn＞で囲った要素が、スクロールで画面に入った時にふわっと出現ます。

###右から出現

```
import { useInView } from 'react-intersection-observer';

export const SlideInRight = ({ children }) => {
    const { ref, inView } = useInView({
        // オプション
        rootMargin: '-100px', // ref要素が現れてから50px過ぎたら
        triggerOnce: true, // 最初の一度だけ実行
    });

    return (
        <div
            ref={ref}
            className={`${inView ? "opacity-100" : "opacity-0 translate-x-[50%]"} duration-[1s]`}
        >
            {children}
        </div>
    )
}
```

###左から出現
```
import { useInView } from 'react-intersection-observer';

export const SlideInLeft = ({ children }) => {
    const { ref, inView } = useInView({
        // オプション
        rootMargin: '-100px', // ref要素が現れてから50px過ぎたら
        triggerOnce: true, // 最初の一度だけ実行
    });

    return (
        <div
            ref={ref}
            className={`${inView ? "opacity-100" : "opacity-0 translate-x-[-50%]"} duration-[1s]`}
        >
            {children}
        </div>
    )
}
```
これをセクションや、ブロックごとに、このコンポーネントを使い分けることで、よりアップグレードしたサイトになります。

#8. next.jsのImageについて
Next.jsはそのまま使うだけでも、SEO効果がかなり高いです。
さらに、SEO効果を高めるためにimgタグではなく、Imageを使うことが推奨されています。

こちらのサイトで詳しく説明しています。

https://maku.blog/p/fw7gpx7/

https://tech.012grp.co.jp/entry/2021/01/28/111151

昔のNext.jsでは

```
<img src="/img.png" alt="img"/>
```
と、いう書き方でしたが

```
import img from "../public/img.png"
.
.
.
<Image src={img} alt="img"/>
```
今は、このような書き方が推奨されています。

:::note alert
元の画像のサイズを変えない場合の書き方です。
:::

```
<Image src={img} placeholder="blur" alt="img" />
```
また、このようなオプションをつけることをおススメします。
placeholder="blur"をつけることで、画像完全に読み込まれるまで、ぼやけて表示してくれるので、表示速度が上昇します。
（src={img}のような書き方以外は、placeholderは使えません）

画像のサイズを変える場合で、アスペクト比を保ちたい場合には以下のように書きます。

```
<Image src="/img.png" width={100} height={500} objectFit="contain"  alt="img"/>
```
widthとheightは、両方かかないとエラーになるので注意して下さい。
また、objectFit="contain"を追加すると、画像のアスペクト比が保たれます。

#9. おわり
お疲れ様でした。Next.js + Tailwind css はこの先のフロントエンドで主流になると思うので、ぜひこの機会に習得してみてください。

ここまで読んでいただき誠にありがとうございました。

#10. おまけ
固定されたヘッダーを、下スクロールしたときに消えて、上スクロールしたときに表示する方法

https://suzukalight.com/snippet/posts/2021-01-04-header-scroll-visible

https://github.com/n8tb1t/use-scroll-position

このgithubのサイトをスクロールしていくと、inistall の仕方が書いてあります。
コードはこちらです。

```
import { useState } from 'react';
import { useScrollPosition } from "@n8tb1t/use-scroll-position";

export default function Home() {

const [showHeader, setShowHeader] = useState(true);
  useScrollPosition(({ prevPos, currPos }) => {
    const visible = currPos.y > prevPos.y;
    setShowHeader(visible);
  }, []);

return(
  <div>
      <header className={`fixed top-0 z-10 bg-red-300 bg-opacity-75 w-full duration-300
        ${showHeader ? "" : "translate-y-[-100%]"}`}>
        HEADER
      </header>
      
      <div className="my-[1000px]">text</div>
  </div>
  )
}
```
header のクラス内に${showHeader ? "" : "translate-y-[-100%]"}とあります。

これは、showHeaderという変数に今現在上にスクロールしているか、下にスクロールかを判別しています。

また、この書き方は三項演算子といい、ここではshowHeaderがtrueの時に左、falseの時に右の""の中が実行されます。

ここでは、下にスクロールしているときはtrueが格納されるので${showHeader ? "" : "translate-y-[-100%]"}ここでいう　""がクラスにあてられます。

上にスクロールしているときはfalseが格納されるので"translate-y-[-100%]"、つまり上に100%動くのでヘッダーが上に隠れます。