LoginSignup
3
0

A bag of potato chips with 'Next.js with Tailwind CSS' written in pop fonts.jpeg

※この記事では、文章の生成や、コードスニペットの生成に ChatGPT や Github Copilot、Edge ブラウザに搭載の Copilot など、様々なAIを駆使して作成しております 🙏

はじめに

この記事は、Next.js 入門するにあたり、よく一緒に語られる Tailwind CSS について、勉強してまとめたものになります。

弊社は最近 Next.js の社内での普及に取り組んでおります↓ 💪

Tailwind CSS とは

Tailwind CSS の要約(Edge の Copilot)

  • ユーティリティファースト: Tailwind CSSは、flexpt-4text-centerなどのクラスを組み合わせてデザインを構築できるユーティリティファーストのアプローチを採用しています。 
  • カスタマイズ性: 大規模なチームでもスケールしやすく、デザインに適応しやすいため、カスタマイズが容易です。
  • パフォーマンス: 未使用のCSSを自動的に削除し、最終的なCSSバンドルを可能な限り小さくします。多くのプロジェクトでは、クライアントに送信されるCSSが10kB未満です。
  • レスポンシブデザイン: メディアクエリを使わずにHTML内でレスポンシブデザインを構築できます。任意のユーティリティクラスの前に画面サイズを指定するだけで、特定のブレークポイントで適用されます。

所感

ユーティリティファーストについては、公式のドキュメントの以下のページの説明が従来のCSSを利用するやり方と比較していて、わかりやすいです。

一言でいうと、CSS 書かなくて良くなったね!(CSS は量が増えると修正するのも大変)という感じですが、
結局 HTML タグでクラス指定が増えるので、どっちがいいんだろうかと・・・。
プラグインとか既成のソリューションがあるので、それを使って気軽に実装!みたいなことができるのは便利ですよね。

パフォーマンスに関しては、CSSバンドルを小さくしてくれる機能は素晴らしいですよね。Rich な見た目のウェブサイトでも、CSS のダウンロードが、10kb 未満で済むんですから。

以下は、弊社で運用しているウェブサイトのあるページでダウンロードされるCSSですが、結構でかい・・。
このCSSファイルを利用する画面が、表っぽい UI とか、情報量が多いので仕方がないのですが、将来 Tailwind CSS に置き換えることがあれば、かなり軽くなりそう

image.png

以下のスクショは、適当に作った WEB アプリに Tailwind CSS を使った場合です。

厳密な比較ではないですが、小さくなりそうな予感がしますね。

image.png

ということで、Next.js とは切っても切り離せない存在になりつつある Tailwind CSS をより使いこなすために、いろいろ Tips を調べたので、記事にまとめたいと思います。

始め方

Tailwind CSS を始める方法は色々ありますが、Next.js といっしょに使い始めるのが一番手っ取り早いでしょう!なので、ここの章では、Next.js アプリの雛形をとりあえず作って、Tailwind CSS を色々試すためのサンドボックスを用意するための手順をまとめます。

npx create-next-app

まず雛形を用意するため、npx create-next-app@latest <app name> のコマンドで Next.js のサンプルアプリを作成します。
作成時にオプションの指定を色々聞かれます。今回気にするのは、Tailwind を使うということだけですが、一応他の選択肢で何を選択したかを、"バッククォート" で示します。

ですが、Tailwind CSS さえ Yes と選択しておけば、とりあえず 使い始められるので、気軽に選択しましょう。

ターミナル
❯ npx create-next-app@latest tailwind-sample
Need to install the following packages:
create-next-app@14.1.4
Ok to proceed? (y) y
✔ Would you like to use TypeScript? … No / `Yes`
✔ Would you like to use ESLint? … No / `Yes`
✔ Would you like to use Tailwind CSS? … No / `Yes`
✔ Would you like to use `src/` directory? … `No` / Yes
✔ Would you like to use App Router? (recommended) … No / `Yes`
✔ Would you like to customize the default import alias (@/*)? … `No` / Yes
Creating a new Next.js app in /Users/s14103/code/private/tailwind-sample.

Using npm.

Initializing project with template: app-tw


Installing dependencies:
- react
- react-dom
- next

Installing devDependencies:
- typescript
- @types/node
- @types/react
- @types/react-dom
- autoprefixer
- postcss
- tailwindcss
- eslint
- eslint-config-next


added 369 packages, and audited 370 packages in 32s

136 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
Initialized a git repository.

Success! Created tailwind-sample at /Users/s14103/code/private/tailwind-sample

インストール後のファイル構成↓
※ node_modules と README.md は列挙の対象から除外しています!

ターミナル
❯ tree -I 'node_modules' -I 'README.md' -L 2
.
├── app
│   ├── favicon.ico
│   ├── globals.css
│   ├── layout.tsx
│   └── page.tsx
├── next-env.d.ts
├── next.config.mjs
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│   ├── next.svg
│   └── vercel.svg
├── tailwind.config.ts
└── tsconfig.json

3 directories, 13 files

不要なコードの削除(Tailwind CSS に集中する)

npx create-next-app@latest <app name> を実行すると、Next.js のデフォルトのページが入っています。Next.js でコンポーネントを使って、どんな感じでページを構築するのか参考にはなりますが、Tailwind CSS の機能を色々試すためには、むしろ不要です。
そのため、以下のファイルから不要なコードを削除します。

まずは、app/global.css。以下のように、@tailwind の記述だけ残して残りは消します。

@tailwind の記述は、Tailwind CSS の下記のインストール手順にも記載されているものです。
npx create-next-app... をやると、主要な CSS ファイルへの追記も自動でやってくれているようですね。

app/global.css
@tailwind base;
@tailwind components;
@tailwind utilities;

// 👆 のtailwind の記述だけ残して、👇 にある生の css は全部削除

続いて、app/page.tsx の Home コンポーネントから、JSXの要素をすべて、消して、div 要素だけ残します。(div の代わりにフラグメントを使ってもいいですね。フラグメント使うと色々性能に関する問題もありそうですが、Tailwind CSS試したいだけなので気にしません!)

app/page.tsx
// 何かしらコンポーネントの import もあれば、tailwind 使うだけなら不要なので、削除する
export default function Home() {
  return (
    <div>
        {/* 空のDIV要素をだけ残す */}
    <div/>
  );
}

開発用サーバー起動

最後に、↓のコマンドで Next.js のサーバーを起動すると、http://localhost:3000 で、真っ白なページが見えるかと思います。

ターミナル
npm run dev

簡単な Tailwind CSS 利用例

あとは、楽しく Tailwind CSS の各種機能を使ってみるだけです!
例えば、以下のように!

jsx:app/page.tsx
export default function Home() {
  return (
    <div className="flex gap-4 mx-4">
      <div className="w-1/2 flex flex-col gap-1">
        <div className="bg-green-400">Column Left Row 1</div>
        <div className="bg-green-400">Column Left Row 2</div>
        <div className="bg-green-400">Column Left Row 3</div>
      </div>
      <div className="w-1/2  flex flex-col gap-1">
        <div className="bg-blue-500">Column Right Row 1</div>
        <div className="bg-blue-500">Column Right Row 2</div>
        <div className="bg-blue-500">Column Right Row 3</div>
      </div>
    </div>
  );
}

上記は、flex box を利用して、要素を並べる例ですが、className に Tailwind CSS が用意している CSS のクラスを指定するだけで、そのスタイルができます。結果は↓の通り。

image.png

なお、VScode で Tailwind CSS を使う際は、↓の拡張機能必須です!

上記拡張機能使うと、以下のスクショのように、候補を出してくれるので、いちいちドキュメントを参照せずとも Tailwind CSS のクラスがかけるようになります。

image.png

さらにホバーすると、それが具体的にはどんな CSS になっているかも確認できます。

image.png

とりあえず、Tailwind を Next.js 使い始めるにはこんな感じで上記のようにすることでできますね!

ここからは具体的に、知っておくと便利そうな Tailwind CSS の機能をご紹介します!

1. divide-{x or y}, divide-{color} の組み合わせで、要素同士の区切りを簡単につける

まずは、↓のスクショを見ていただきたいのですが、
上下に2つのコンポーネントが並んでいますが、どちらもほとんど同じスタイルになっています。

image.png

ですが、以下に示す通り、下段の DividedByParent コンポーネント は StyleEachElement コンポーネントよりもスタイル指定がシンプルです。

ちょっとだけ複雑な StyleEachElement コンポーネント:

app/page.tsx
const StyleEachElements = () => {
  return (
    <div className="flex mx-4 divide-x-8 divide-white">
      <div className="w-1/2 flex flex-col">
        <div className="bg-green-500 my-[1px]">Column Left Row 1</div>
        <div className="bg-green-500 my-[1px]">Column Left Row 2</div>
        <div className="bg-green-500 my-[1px]">Column Left Row 3</div>
      </div>
      <div className="w-1/2 flex flex-col">
        <div className="bg-blue-500 my-[1px]">Column Right Row 1</div>
        <div className="bg-blue-500 my-[1px]">Column Right Row 2</div>
        <div className="bg-blue-500 my-[1px]">Column Right Row 3</div>
      </div>
    </div>
  );
};

シンプルになった DividedByParent コンポーネント:

app/page.tsx
const DividedByParent = () => {
  return (
    <div className="flex mx-4 divide-x-8 divide-white">
      <div className="w-1/2 bg-green-500 flex flex-col divide-y divide-white">
        <div>Column Left Row 1</div>
        <div>Column Left Row 2</div>
        <div>Column Left Row 3</div>
      </div>
      <div className="w-1/2 bg-blue-500 flex flex-col divide-y divide-white">
        <div>Column Right Row 1</div>
        <div>Column Right Row 2</div>
        <div>Column Right Row 3</div>
      </div>
    </div>
  );
};

ポイントは、 divide-... で始まるCSSクラスを使っているところです。

要素間に隙間を入れたい・・と思ったら、とりあえず divide-... を使いましょう!縦方向に隙間を入れたいなら、divide-y 横方向なら、divide-x といった具合です!
隙間の色も指定可能で、divide-white などとすると、隙間が白くなり、
mergin や padding を使って、要素間に隙間を入れたようなスタイルが適用されます。

css クラスの書く量が減って、きっと保守性も上がりますね!

ドキュメント:

2. size-{n} で正方形のサイズ指定をする

これは、めちゃくちゃシンプルです。

以下のスクショのような正方形を作りたい場合、従来だと、width と height に同じ値を指定する必要がありましたが、Tailwind CSS では、size-{n} というクラスを使うことで、簡単に正方形を作ることができます。

image.png

コード例を示すと以下のようになります。

従来の正方形の作り方:

app/page.tsx
const NormalSquare = () => {
  return (
    <div className="w-20 h-20 bg-black mx-auto"></div>
  );
};

従来の方法だと、w-20h-20 というように、width と height に同じ値を指定する必要がありますが、

Tailwind CSS を使った正方形の作り方:

app/page.tsx
const SquareSize = () => {
  return (
    <div className="size-20 bg-black mx-auto"></div>
  );
};

size-20 というクラスを使うだけで、正方形が作れます!

ドキュメント:

3. group, group-hover で、特定の要素のマウスオーバー時のスタイルを適用する

以下のスクショを見ていただきたいのですが、
マウスオーバー時に、アニメーションが適用されているのがわかります。

「良い例見出し👍」のコンポーネントをホバーしたときと、
「悪い例見出し❌」のコンポーネントをホバーしたときで、アニメーションが違うのがわかります。

animegroup.mov.gif

具体的には、「悪い例見出し❌」のコンポーネントをホバーしたときに、以下の3つのアニメーションが同時に発動してしまっています。

  • 背景色の明度が上がるのアニメーション
  • 見出し文字の真下に表示される「今すぐチェック!」の文字列の表示アニメーション
  • 一番右側のアカウントアイコンの回転アニメーション

ホバーのアクションと、アニメーションを連動させるという意味で考えると、おそらく、最初の2つと、3つ目のアニメーションは分けてトリガーさせるほうが自然かなと思います。

「良い例見出し👍」では、アニメーションの動作が期待通り分かれています。

それを可能にするのが、groupgroup-hover という Tailwind CSS のクラスです。

以下に使用例のコードを示します。

app/page.tsx
const GroupedCard = () => {
  return (
    // ポイント
    // ・親で group クラスを指定すると、親クラスをホバーしたときに、group-hover:... というクラスが指定されている子要素のアニメーションが発動する。
    // ・group を分けて、ホバー時のアニメーションの挙動を分けることも可能。

    // group クラスを指定することで、h1 タグのに含まれる span 要素の hover が有効になる。
    <article className="group my-1 hover:bg-cyan-500 border-orange-600 mx-auto hover:cursor-pointer flex bg-cyan-600 text-white h-24 w-[30rem] justify-around items-center">
      <h1 className="relative">
        <a href="" className="text-xl">良い例見出し👍</a>
        {/* group-hover... のクラスに注目。親が group クラスを使っているので、親クラスが hover されると、この span 要素の hover が発動して、opacity が変化する  つまり、この要素そのものをホバーしなくても良くなるということ */}
        <span className="group-hover:opacity-100 opacity-0 transition absolute text-[0.6rem] text-yellow-300 bottom-[-50%] left-0 whitespace-nowrap">今すぐチェック!</span>
      </h1>
      <p className="text-xs max-w-[40%]">いろはにほへと ちりぬるを わかよたれそ つねならむ うゐのおくやま けふこえて あさきゆめみし...</p>
      <button className="border border-gray-300 p-2 rounded-xl bg-slate-400 hover:bg-yellow-300">
        <span>🦩</span>
      </button>
      {/* グループを分ける例: special-animation という適当な名前のグループをつけてみる */}
      <button className="group/special-animation">
        {/* 👇 の要素は、hover 効果が設定されているが、special-animation のグループとして発動する。つまり他のグループのホバーの影響を受けず、単体で作動できる。 */}
        <IoPersonCircle className="group-hover/special-animation:rotate-[360deg] transition size-14 rounded-[100%]" />
      </button>
    </article>
  );
};

上記では、group クラスを指定することで、親要素をホバーしたときに、group-hover:... というクラスが指定されている子要素のアニメーションが発動するようになります。

↓コンポーネント全体(親)をホバーして、子要素の span が表示されるアニメーションが発動している
hove.mov.gif

また、group を分けて、ホバー時のアニメーションの挙動を分けることも可能です。
上記のコードでは、group/special-animation というクラスを指定して、その要素の子要素のアイコンコンポーネントに対して、 group-hover/special-animation:rotate-[360deg] というクラスを指定しています。
これにより、アイコンの要素をホバーしたとき専用のアニメーションも実装できました。

icon.mov.gif
(※gifのフレーム数が少なくて、1回転している様子が伝わりづらい🥲)

ドキュメント:

4. prose クラスで、読みやすい文章のスタイルを適用する

SPAとかプログレッシブウェブアプリケーションなど、近年は、Webでできることの幅が広がってきていますよね!
でも、やっぱり基本は文章を読むことですよね!Hyper Text Markup Language ですから!(HTML)

ということで、読みやすい文章のスタイルを手軽に実現できる Tailwind CSS のクラス prose を使ってみましょう。

prose クラスは、tailwindcss/typography という Tailwind CSS のプラグインをインストールすることで使えるようになります。

インストールコマンド:

npm install -D @tailwindcss/typography

インストール後に、Next.js のプロジェクトルートにある、tailwind.config.js に以下のように記述すると、このプラグインのクラスが使えるようになります。

/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    // ...
  },
  plugins: [
    require('@tailwindcss/typography'),
    // ...
  ],
}

まずは、prose を使わない状態の文章のスタイルを見てみましょう。
次の NonProseSection コンポーネントは、prose クラスを使っていない文章のスタイルで、ほぼほぼ生のHTMLが書かれているだけです。

app/page.tsx
const NonProseSection = () => {
  return (
    <>
      <div className="mx-auto">
        <h1>Prose が効いていないので、このブログはあったら読みたくない</h1>
        <h2>小見出しもこんな感じ・・・</h2>
        <p>
          この文章は、Tailwind CSS のデフォルトスタイルによって、めちゃくちゃシンプルにされてしまっている・・・流石にシンプル過ぎる!!!!!!!!!!!
        </p>
        <ul>
          <li>リストが・・・</li>
          <li>なぜか・・・・・</li>
          <li>箇条書きじゃないの!!!!!!!!!!!!!!!!!1</li>
        </ul>
        <p>『デューン』(Dune)は、アメリカの作家フランク・ハーバートによるSF小説のシリーズ。第1作『砂の惑星』が1965年に公開されると、その人気を受けて『砂漠の救世主』『砂丘の子供たち』『砂漠の神皇帝』『砂漠の異端者』『砂丘の大聖堂』と次々に続編が著された。</p>
        <p>出版直後から幾度も映像化が構想されたが、その壮大なドラマの製作は困難を極め、『エル・トポ』で知られるアレハンドロ・ホドロフスキーを始め多くの人が挫折。ようやく1984年に初めて映画化を成功させたのはディノ・デ・ラウレンティスであったが、監督したデイヴィッド・リンチ自身が認めているように、作品世界全体を描くには充分な内容に仕上がっていたとは言い難い。</p>
        <img src="https://www.wfla.com/wp-content/uploads/sites/71/2023/05/GettyImages-1389862392.jpg?w=2560&h=1440&crop=1" alt="cat" className="shadow-lg" />
        <h2>チャーチ博士</h2>
        <p>昭和二十四年七月六日に羽田を立って、三カ月の予定で、アラスカ、米本国、カナダを廻って、十月五日に、南方空路経由、羽田へ帰り着いた。その間、わずか九十日の間に、十年前ならば、一年以上もかかるくらいの旅行をして来た。
          そういうことが出来たのは、ほとんど全部飛行機を使ったからである。飛行機というものが、ほんとうに実用になったことがよく分った。現在では、東京からアメリカまでの距離が、東京札幌間の距離よりも近くなってしまったのである。
          初めはリノのネバダ大学に落着いて、そこで旅程を立てて貰って、二、三カ所廻って来るくらいの暢気のんきな気持で出かけた。ところが着いてみたら、私を招いてくれたチャーチ博士が、既に全米の各大学や研究所に打合せをしておいてくれたので、とんでもない大旅行になってしまった。
          地図で見られるように、ちょいちょいと次の大学へ寄るといっても、たいていは東京から札幌までくらいの距離である。しかしそれが現在の飛行機だと、二時間半くらいのものである。それで例えば、札幌の大学に夕方四時までいて、ホテルへ帰って夕食をすませ、六時に飛行場へ行くと、八時半にはもう東京に着いている。ホテルへ行って、風呂にはいって少し仕事をして寝ると、翌朝はもう八時から東京の大学へ顔を出すことが出来る。旅行の時間というものをほとんど旅程の中に入れなくてもいい。疲労の点も汽車と較べれば、全然問題にならない。</p>
        <img src="https://thumbor.forbes.com/thumbor/fit-in/1290x/https://www.forbes.com/advisor/wp-content/uploads/2023/09/how-much-does-a-cat-cost.jpeg.jpg" alt="cat" className="shadow-lg" />
      </div>
    </>
  );
};

そして、ブラウザでは次のように表示されます。

image.png

image.png

h1 タグや、 ul タグなどが、コンポーネントに含まれていますが、どれもスタイルの特徴がなくなっています。
これは、Tailwind CSS が、デフォルトの挙動として、ブラウザのスタイルをリセットしているためです。

この状態から、prose クラスを指定するだけで、以下のように、読みやすい文章のスタイルが適用されます。

以下に、prose クラスを指定したコンポーネントを示しますが、違いは、一番上位にある div 要素に prose クラスを指定しているだけです。

app/page.tsx
const ProseSection = () => {
  return (
    <>
      <div className="prose mx-auto">
        <h1>Prose効いていい感じ!</h1>

          {/* 以下、基本 NonProseSection と同じ内容なので省略 */}        

      </div>
    </>
  );
};

そして、それが、ブラウザでは次のように表示されます。

image.png

image.png

見出しや、箇条書きなどの、スタイルが良い感じで適用されているのがわかりますね!
画像のサイズも、適切に調整されているのがわかります。

ブログっぽいページを作りたいときは、この prose クラス使うだけで、きれいな見た目になるので、便利そうです。

(※サンプルの文章は、wikipedia や 青空文庫から引用しています。)

ドキュメント:

5. snap-x, snap-center で、スクロールスナップを実現する

画像のギャラリーだったり、ランディングページのカルーセルな要素だったり、スクロールするときに、
通常のスクロールだと、ちょっとだらしなく感じるときがあります。

そんなときに、スクロールスナップを使うと、スクロールにメリハリが出て、見栄えが良くなります。

Tailwind CSS では、snap-xsnap-center というクラスを使うことで、スクロールスナップを実現できます。

app/page.tsx
const ScrollSnap = () => {
  return (
    <>
      <h1 className="text-center">スナップスクロール</h1>
      <section className="border-4 border-black flex mx-auto max-w-[40%] h-full gap-8 overflow-x-scroll snap-x">
        {[...Array(10)].map((_, index) => {
          return (
            <div key={index} className="min-w-96 snap-center">
              <img className="" src="https://mychandlervet.com/wp-content/uploads/2019/04/Dog_mosquitoes.png" alt="dog" />
            </div>
          );
        })}
      </section>
    </>
  );
};

snap.mov.gif

ドキュメント:

6. animate-ping で、要素を点滅させる

アイコンなどにバッジをつけて、新着情報などを目立たせたいとき、バッジを点滅させたいときありますよね。
そういった場合は、その要素に対して、animate-ping という Tailwind CSS のクラスを指定するだけで、要素を点滅させることができます。

以下に、animate-ping を使った要素と、使わない要素を示します。

app/page.tsx
const BoxWithAnimatedBadge = () => {
  return (
    <div className="divide-x flex">
      <div className="bg-blue-500 w-40 h-40 mx-auto relative rounded-full">
        <span className="absolute top-0 right-0 bg-red-500 text-white text-xs">New!</span>
      </div>

      <div className="bg-blue-500 w-40 h-40 mx-auto relative rounded-full">
        <span className="absolute top-0 right-0 bg-red-500 text-white text-xs animate-ping">New!</span>
      </div>
    </div>
  );
};

ブラウザでは、以下のように表示されます。

ping.mov.gif

ドキュメント:

vercel にデプロイしてみる

最後に、上記でご紹介した Tailwind CSS の機能をサイトをサクッとデプロイしてみようと思います。

まずは vercel のコマンドをインストールします。

npm i -g vercel

そして、以下のコマンドでデプロイします。

vercel deploy

たったこれだけで、サイトがデプロイされます!
いろいろ質問されますが、まあ基本デフォルトで大丈夫でしょう。

github リポジトリとの連携があるので、途中で github のログインが求められるかと思います。
(自分がやったときは、すでにログイン、連携済みだったので、はじめてやるときどうなるか・・・記憶が曖昧)

Vercel CLI 33.7.0
? Set up and deploy “~/code/private/tailwind-sample”? yes
? Which scope do you want to deploy to? takaesujunya's projects
? Link to existing project? no
? What’s your project’s name? tailwind-sample
? In which directory is your code located? ./
Local settings detected in vercel.json:
Auto-detected Project Settings (Next.js):
- Build Command: next build
- Development Command: next dev --port $PORT
- Install Command: `yarn install`, `pnpm install`, `npm install`, or `bun install`
- Output Directory: Next.js default
? Want to modify these settings? no
🔗  Linked to takaesujunyas-projects/tailwind-sample (created .vercel)
🔍  Inspect: https://vercel.com/takaesujunyas-projects/tailwind-sample/YvqAU61mQA3YHQVG8RucnfqEzwqi [1s]
✅  Production: https://tailwind-sample-9gurqza9a-takaesujunyas-projects.vercel.app [1s]
📝  Deployed to production. Run `vercel --prod` to overwrite later (https://vercel.link/2F).
💡  To change the domain or build command, go to https://vercel.com/takaesujunyas-projects/tailwind-sample/settings

実際にデプロイされたサイトが以下です。

まとめ

Tailwind CSS は、CSS を書くのが面倒だと感じる人にとって、とても便利なツールです。
また、Tailwind CSS は、デザインシステムを構築するためのツールとしても使えるので、デザインシステムを構築する際にも、活用できると思います。
Next.js と組み合わせることで、より効率的に開発を進めることができるので、ぜひ使ってみてください!

参考

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0