【TailwindCSS v3.4】ドキュメントを隅から隅まで読んでみた

## はじめに
記事作成し始めた当初はドキュメントを読んで確認した内容全てを1記事にまとめる予定でしたが、ストックしてもらった時に読み返ししやすいように一部は切り出して別記事にしております。

本記事はそのハブとなる記事です。
分割した記事一覧です。読みたいセクションがあれば下記から遷移してください。

- [Utility-First Fundamentals](https://qiita.com/tanimoto-hikari/private/32360141504f773aeeac)

:::note
TailwindCSSのドキュメントを読めばわかることは記載せず、要点に絞ってお届けできればと考えています。詳細を確認したい場合は公式ドキュメントのリンクから確認いただけますと幸いです！
:::

## なぜドキュメントを読み直したのか？
TailwindCSSを利用していますが、まだまだ知識不足は否めないです…。
恥ずかしながら端から端まで読んでなかったので全て目を通してみることにしました！

:::note warn
記事はめちゃくちゃ長くなっているので時間の許す方のみご一読いただけるようお願いします。
読みたい！と思ってくださった方は一旦ストックに入れておくことをオススメします。
:::

## Tailwind CSS ドキュメントバージョン
今回読み進めるドキュメントのバージョンは3.4です。
インストールの方法など、一部は本記事には記載せず省きたいと思います。

:::note
改めて抜き出す必要がないと判断したものはタイトルの横に「省略」と記載します。
気になる方はリンクからドキュメントを確認してください！
:::

## 目次
1. Getting Started
1. Core Concepts
1. Customization
1. Base Styles
1. Layout
1. Flexbox & Grid
1. Spacing
1. Sizing
1. Typography
1. Backgrounds
1. Borders
1. Effects
1. Filters
1. Tables
1. Transitions & Animation
1. Transforms
1. Interactivity
1. SVG
1. Accessibility
1. Official Plugins

## Getting Started
環境設定がメインのセクションです。

1. [Installation](https://tailwindcss.com/docs/installation)　（省略）
1. Editor Setup
1. [Using with Preprocessors](https://tailwindcss.com/docs/using-with-preprocessors)（省略）
1. [Optimizing for Production](https://tailwindcss.com/docs/optimizing-for-production)（省略）
1. [Browser Support](https://tailwindcss.com/docs/browser-support)（省略）
1. Upgrade Guide

### [Editor Setup](https://tailwindcss.com/docs/editor-setup)
vscodeを利用する場合は必ず[Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)を入れましょう！
あるのとないのとで開発効率が全く違います！

[Prettier](https://github.com/tailwindlabs/prettier-plugin-tailwindcss)を入れると推奨される順番にクラスを並び変えてくれるのでインストールするのがオススメ。

### [Upgrade Guide](https://tailwindcss.com/docs/upgrade-guide)
TailwindCSSv2からv3へアップグレードする際のガイドです。
TailwindCSSをアップグレードする際は確認してみてください！

## Core Concepts

1. Utility-First Fundamentals
1. Handling Hover, Focus, and Other States
1. Responsive Design
1. Dark Mode
1. Reusing Styles
1. Adding Custom Styles
1. Functions & Directives

### [Utility-First Fundamentals](https://tailwindcss.com/docs/utility-first)
ご存知の通り、ユーティリティファーストなのがTailwindCSSです。
カスタムCSSを1行も記述せずにユーティリティのセットから実装できます！

利点は以下の通り。
- クラス名を考案する必要がない
- CSSのファイルが大きくなるのを防ぐ
- グローバルスコープをローカルスコープに

:::note
TailwindCSSを使い始める前はピンときませんでしたが、ドキュメントで挙げられている利点は非常に大きいと思っています。
これまで膨大な時間をクラス名を考えるのに消費していましたし、グローバルに定義されるCSSの影響を確認するために多くの時間をビジュアルの確認に使ってました。
:::

時間が節約できたことによって、**コンポーネントの設計など本質的な部分に時間を使うことができる**ようになりました！

#### [Why not just use inline styles?](https://tailwindcss.com/docs/utility-first#why-not-just-use-inline-styles)

TailwindCSSとインラインスタイルとは異なる点やTailwindCSSを利用することの利点が述べられています！

- 一貫性あるUIの構築が簡単
- レスポンシブユーティリティーが使える
- ホバー、フォーカスなどの表現が可能

:::note warn
インラインスタイルはマジックナンバー[^1]であると表現されますが、確かにそうだと思いました。インラインスタイルは書いた人にしか理解しづらい側面があります。
:::

TailwindCSSはレスポンシブユーティリティが用意されているので**従来より簡単にレスポンシブ対応が可能**です！

インラインスタイルでは**ホバーやフォーカスなどの状態をスタイリングできませんがTailwindCSSなら可能**です！

#### [Maintainability concerns](https://tailwindcss.com/docs/utility-first#maintainability-concerns)

TailwindCSSはユーティリティが繰り返されることで保守性に対する懸念が語られます。

- コンポーネントの部分抽出
- エディターの機能

を使うことで解決できると書かれています！
いくつか参考例も提示してくれているので気になる人は確認してください！

- [By The Numbers: A Year and a Half with Atomic CSS](https://medium.com/@johnpolacek/by-the-numbers-a-year-and-half-with-atomic-css-39d75b1263b4)
- [No, Utility Classes Aren’t the Same As Inline Styles](https://frontstuff.io/no-utility-classes-arent-the-same-as-inline-styles)
- [Diana Mounter on using utility classes at GitHub](http://www.fullstackradio.com/75)
- [The Case for Atomic/Utility-First CSS](https://johnpolacek.github.io/the-case-for-atomic-css/)

:::note
TailwindCSSは定義が長くなり冗長的に見えます…。
ただ、ライブラリやユーティリティ関数を利用することでも読みやすさを上げることが可能だと思います!
:::

#### Tailwind Variantsの利用

https://www.tailwind-variants.org/

TailwindCSSを宣言的な書き方をするためのライブラリです。
HTML部分に記述していたclassをまとめられるのでコードを見やすくできます！

過去に記事を書いてますのでよろしければご覧ください！

https://qiita.com/tanimoto-hikari/items/3b2ccc23afd7ab9cd264

#### `tailwind-merge`を利用する

https://www.npmjs.com/package/tailwind-merge

classNameのコンフリクトを処理してくれるライブラリです！
`tailwind-merge`を使うと下記のようにコードを書けます！

```javascript
// tailwind-merge利用前
<button class="bg-blue-500 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 active:bg-blue-800 text-white font-bold py-2 px-4 rounded-full transition duration-150 ease-in-out">
  Click me
</button>

// tailwind-mergeを利用した時のコード
import { twMerge } from 'tailwind-merge'

<button
  className={twMerge(
    'bg-blue-500 text-white font-bold py-2 px-4 rounded-full',
    'hover:bg-blue-700',
    'focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500',
    'active:bg-blue-800',
    'transition duration-150 ease-in-out'
  )}
>
  Click me
</button>
```

`tailwind-merge`を利用することで行を分割できるので可読性を改善することは可能だと思います！


### [Handling Hover, Focus, and Other States](https://tailwindcss.com/docs/hover-focus-and-other-states)

かなり長い章です…。
ざっと確認したい場合は[Quick reference](https://tailwindcss.com/docs/hover-focus-and-other-states#quick-reference)や[Pseudo-class reference](https://tailwindcss.com/docs/hover-focus-and-other-states#pseudo-class-reference)を確認するのが良いと思います！
それ以外のところは別記事にまとめました！

#### 擬似クラス・擬似要素
https://qiita.com/tanimoto-hikari/items/63254290be3631884e9d

#### 属性セレクタ・カスタム修飾子
https://qiita.com/tanimoto-hikari/items/ed75ba724cddf360510d

### [Responsive Design](https://tailwindcss.com/docs/responsive-design)
TailwindCSSでは簡単にレスポンシブインターフェイスを表現できます。
メタタグは忘れず`head`に記載していることを確認してください。

```html
<meta name="viewport" content="width=device-width, initial-scale=1.0">
```

あとは利用するユーティリティクラスの前に`ブレークポイント名:`を付与するだけです！

```html
<div class="w-16 md:w-32 lg:w-48">
```

Tailwwindには5つのブレイクポイントが用意されています。

|プレフィックス|最小幅|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) {}|

#### [モバイルファースト](https://tailwindcss.com/docs/responsive-design#working-mobile-first)

プレフィックス付きのユーティリティクラスは指定されたブレイクポイント以降でのみ有効になります！

:::note warn
プレフィックスのないユーティリティでモバイルのスタイルを定義し、より大きいデバイスはプレフィックスを使用したユーティリティでオーバライドするようにスタイリングすることに注意していください…

[targeting-mobile-screens](https://tailwindcss.com/docs/responsive-design#targeting-mobile-screens
)
:::

#### ブレークポイントの範囲の設定

ブレークポイントのプレフィックスを利用して下記のような記述が可能です。

```html
<div className="md:max-xl:bg-red-500 w-10 h-10">
```

`flex`の適用を特定の範囲に制限する手法です。
先ほどの例だと`md`は768px、`max-xl`は1280pxなのでこの間は背景色が赤色になります。

ブレークポイントは`tailwind.config`に記述することでカスタマイズできます！

```jsx
module.exports = {
  theme: {
    screens: {
      'tablet': '640px',
      'laptop': '1024px',
      'desktop': '1280px',
    },
  }
}
```

ブレイクポイントの設定はTailwindCSSSが用意してくれている通りの`sm`や`md`も良いのですが、上記の例のようにセマンティックな命名でブレイクポイントを設定した方が、利用用途が明瞭になり良いと感じています！

もちろん任意の値を設定することも可能です。

```jsx
<div className="min-[320px]:text-center">
```

### [Dark Mode](https://tailwindcss.com/docs/dark-mode)

TailwindCSSSではダークモードでのスタイル設定を`dark:`を利用することで対応できます。

```html
<div className="bg-white dark:bg-slate-800">
```

ダークモードは、手動で切り替えることが設定の変更で可能です。

```jsx:tailwind.config
module.exports = {
  darkMode: 'selector',
}
```

クラスはに基づいて適用されるのではなく、クラスが HTML ツリーの前の部分に存在するprefers-color-scheme場合はいつでも適用されるようになります。

```html
<!-- Dark mode not enabled -->
<html>
<body>
  <div className="bg-white dark:bg-black"></div>
</body>
</html>

<!-- Dark mode enabled -->
<html className="dark">
<body>
  <div className="bg-white dark:bg-black"></div>
</body>
</html>
```

一部のフレームワークにはダークモード設定時に独自のクラスを付与することがあります。
その場合はTailwindCSSの設定でダークモードのセレクターをカスタムします！

```jsx
module.exports = {
  darkMode: ['selector', '[data-mode="dark"]'],
}
```
TailwindCSSは、カスタムダークモードセレクターを:where()疑似クラスで自動的にラップし、詳細度が高くならないように対応してくれます。

:::note
window.matchMedia()APIを使用することで手動選択したモードとシステム設定の両方をサポートできます。
:::

細かい設定についてはこちらの記事がわかりやすいかったです。

https://zenn.dev/azukiazusa/articles/bee71756d66679

#### ダークモードバリアントを独自で定義

`tailwind.config`で`darkMode`を`variant`を設定することでバリアントを独自で定義し直せます。

```jsx
module.exports = {
  darkMode: ['variant', '&:not(.light *)'],
}
```

:::note alert
TailwindCSSは提供されたセレクターを一切変更しないため、`:where()`で詳細度の調整が行われないため他のclassと同じ詳細度を確保するように考慮していください。
:::

複数設定したい場合はセレクターの部分を配列にして指定します。
​
```jsx
darkMode: ['variant', [
  '@media (prefers-color-scheme: dark) { &:not(.light *) }',
  '&:is(.dark *)',
]],
```

### [Reusing Styles](https://tailwindcss.com/docs/reusing-styles)

TailwindCSSには繰り返し利用されるスタイルを再利用する方法がいくつか提案されています。

```html:繰り返し同じスタイルが定義されている例
<div class="mt-3 flex -space-x-2 overflow-hidden">
  <img className="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
  <img className="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
  <img className="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2.25&w=256&h=256&q=80" alt=""/>
  <img className="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
  <img className="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
</div>
```

上記を効率よく編集するためのプラクティス
- エディタの機能を使ったマルチカーソル編集
- ループさせる
- コンポーネントと部分抽出

#### Extracting classes with @apply

`@apply`を利用して繰り返し使用されるユーティリティをカスタムクラスとして抽出できます。

```html:カスタムクラスを作る前
<button className="py-2 px-5 bg-violet-500 text-white font-semibold rounded-full shadow-md hover:bg-violet-700 focus:outline-none focus:ring focus:ring-violet-400 focus:ring-opacity-75">
  Save changes
</button>
```

```css:カスタムクラスの定義
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  .btn-primary {
    @apply py-2 px-5 bg-violet-500 text-white font-semibold rounded-full shadow-md hover:bg-violet-700 focus:outline-none focus:ring focus:ring-violet-400 focus:ring-opacity-75;
  }
}
```

```html:カスタムクラスを利用したclassの指定
<button className="btn-primary">
  Save changes
</button>
```

ただ、`@apply`を見た目を綺麗にするため利用してはいけません。
理由は…

- クラス名は常に考えなければならない
- 変更を加えるには複数のファイルを行き来する必要がある
- スタイルはグローバルなので影響範囲が広く、変更後の確認が難しい
- CSSのバンドルが大きくなる

カスタムクラスを定義することは**TailwindCSSが提供する利点を全て捨てる**ことにつながることを意識して導入の検討には細心の注意を払ってください。

### [Adding Custom Styles](https://tailwindcss.com/docs/adding-custom-styles)
TailwindCSSで独自のカスタムクラスを追加する時のプラクティスが示されています。

この章のサマリーは以下の通りです。
- デザイン トークンのカスタマイズ
- 必要に応じて制約を解除する方法、独自のカスタムCSSの追加
- プラグインによるフレームワークの拡張

#### テーマのカスタマイズ
カラーパレット、間隔スケール、タイポグラフィスケール、ブレークポイントなどを変更する場合は、ファイルthemeのセクションに追加します。

```jsx:tailwind.config.js
module.exports = {
  theme: {
    screens: {
      sm: '480px',
      md: '768px',
      lg: '976px',
      xl: '1440px',
    },
  }
}
```

#### 任意の値を利用する
任意の値を指定することが可能です。
別の章で詳しく説明がありましたが、任意で値を指定するには下記のように書けます。

```html
<div className="top-[117px]">
<div className="top-[117px] lg:top-[344px]">
<div className="bg-[#bada55] text-[22px] before:content-['Festivus']">
```

`tailwind.config`に定義したデザイントークンを利用する場合は下記のように記述できます。

```html
<div className="grid grid-cols-[fit-content(theme(spacing.32))]">
```

また、CSS変数は`var()`を使う必要はありません。

```html
<div className="bg-[--my-color]">
```

TailwindCSSで定義されていないユーティリティを使いたい場合には下記のようにします。

```html
<div className="[mask-type:luminance]">
```

#### 任意のバリアント
こちらは[別の章](https://tailwindcss.com/docs/hover-focus-and-other-states)で詳しく説明されているので割愛します。
記事も別でまとめておりますのでそちらをご一読ください。

https://qiita.com/tanimoto-hikari/items/63254290be3631884e9d

https://qiita.com/tanimoto-hikari/items/ed75ba724cddf360510d

#### 空白の処理
_（アンダースコア）を使用すると、TailwindCSSはスペースへ変換します。

```html
<div className="grid grid-cols-[1fr_500px_2fr]">
```

下記のようなURLの場合はアンダースコアを保持します。
```html
<div className="bg-[url('/what_a_rush.png')]">
```

_（アンダースコア）が必要になる場合にはバックスラッシュでエスケープしてください。

```html
<div className="before:content-['hello\_world']">
```

バックスラッシュが JavaScript エスケープ文字として扱われないようにするには`String.raw()`を利用します。

```html
<div className={String.raw`before:content-['hello\_world']`}>
```

#### 曖昧さの解決
TailwindCSSのユーティリティは共通の名前空間を共有しています。
`text-lg`と`text-black`両方ともtext-名前空間を共有していますが、一方はfont-size、もう一方はcolorです。

```html
<div className="text-lg">
<div className="text-block">
```

TailwindCSSは、渡された値に基づいてこの曖昧さを自動的に処理します！
それは任意で定義された値も同様です。

```html
<div className="text-[22px]">
<div className="text-[#bada55]">
```

ただ、CSS変数を利用した場合曖昧さが解決されません。
値の前にCSSデータ型を追加することで回避できます！

```diff_html
- <div className="text-[var(--my-var)]">
+ <div className="text-[color:var(--my-var)]">
```

#### CSSと@layerの使用
TailwindCSSではレイヤーが3つ存在しています。

```css
@tailwind base;
@tailwind components;
@tailwind utilities;
```

それぞれの役割は、下記の通り
|レイヤー名|役割|
|--|--|
|base|リセットルールやプレーンHTML要素に適用されるデフォルトスタイル|
|components|ユーティリティでオーバーライドできるようにしたいクラスベースのスタイル用|
|utilities|他のスタイルよりも常に優先される、小さな単一目的のクラス用|

この@layerディレクティブは、対応するディレクティブに自動的に再配置することで宣言の順序を制御し@tailwind、独自のカスタムCSSに対して修飾子やツリー シェイキングなどの機能も有効にします。

:::note
2つのclassの詳細度が同じ場合、スタイルシート内の順序によってどちらが優先されるか決定します。
それを管理するための3つのレイヤーがあります。
これは[ITCSS](https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/#what-is-itcss)の概念とのことです。
:::

ユーティリティクラスをオーバーライドしたい場合は`@layer components`を利用します。
また、使用しているサードパーティコンポーネントのカスタムスタイルを配置するのにも適しています。

```jsx
@layer components {
  .card {
    background-color: theme('colors.white');
    border-radius: theme('borderRadius.lg');
    padding: theme('spacing.6');
    box-shadow: theme('boxShadow.xl');
  }
}
```

`@layer utilities`には独自のユーティリティクラスを追加する場合に利用します。

```css
@layer utilities {
  .content-auto {
    content-visibility: auto;
  }
}
```

`utilities`レイヤーに定義することでTailwindCSSの他のユーティリティクラスと同じように修飾子構文を自動でサポートしてくれます！

```jsx
<div class="lg:dark:content-auto">
```

レイヤーに追加したカスタムスタイルはTailwindCSSの機能により使用されている場合にのみコンパイルされるツリーシェイキングの機能が有効になります！

:::note
ツリーシェイキングの機能を有効にしたくない場合は、`@layer`ディレクティブを利用しないで定義します。
:::

#### レイヤーとコンポーネントごとのCSS
@layerコンポーネントスタイルでは使用しないでください。

```jsx:after
<style>
  @layer components {
    div {
      background-color: theme('colors.white');
      border-radius: theme('borderRadius.lg');
      padding: theme('spacing.6');
      box-shadow: theme('boxShadow.xl');
    }
  }
</style>
```

上記はエラーになります。
回避するためには`@layer`を使わないことです。

```jsx
<style>
  div {
    background-color: theme('colors.white');
    border-radius: theme('borderRadius.lg');
    padding: theme('spacing.6');
    box-shadow: theme('boxShadow.xl');
  }
</style>
```

ただ、これの対応は避けるべきです。

TailwindCSSはスタイルシート内で直接的なスタイル定義を行うのではなく、`@tailwindディレクティブ`[^1]を使用してプリファビケーションされたクラスを生成します。

このプロセスは、ビルド時に一度だけ実行されるべきですがフレームワークが各styleブロックを個別に扱うことで、このプロセスを複数回実行する可能性があります。

:::note alert
TailwindCSSは`<style>`タグが書かれてコンポーネントの数だけ生成しようとします。各styleブロック間でのスタイルの整合性が保証されないため、最終的な出力CSSが期待通りのレイヤー構造を得られない可能性があります。
:::

TailwindCSSのプラグインを使用してカスタムCSSを追加できます。

```jsx:tailwind.config
module.exports = {
  plugins: [
    plugin(function ({ addBase, addComponents, addUtilities, theme }) {
      addBase({
        'h1': {
          fontSize: theme('fontSize.2xl'),
        },
        'h2': {
          fontSize: theme('fontSize.xl'),
        },
      })
      addComponents({
        '.card': {
          backgroundColor: theme('colors.white'),
          borderRadius: theme('borderRadius.lg'),
          padding: theme('spacing.6'),
          boxShadow: theme('boxShadow.xl'),
        }
      })
      addUtilities({
        '.content-auto': {
          contentVisibility: 'auto',
        }
      })
    })
  ]
}
```

### [Functions & Directives](https://tailwindcss.com/docs/functions-and-directives)
TailwindCSSが公開するカスタム関数とディレクティブについて紹介されています。

TailwindCSSによって提供されるディレクティブは以下の4つです。

- `@tailwind`
    - base、components、utilities、variantsのレイヤーに追加します
- `@layer`
    - カスタムスタイルのセット先を指定します
- `@apply`
    - 独自のカスタムスタイルを定義するために利用します
- `@config`
    - CSSファイルをコンパイルするときにTailwindCSSが使用する構成ファイルを指定します

```jsx:@configの利用方法
@config "./tailwind.site.config.js";

@tailwind base;
@tailwind components;
@tailwind utilities;
```

`@config`は`@import`の宣言前に利用はできません。

```jsx:ダメな例
@config "./tailwind.admin.config.js";
@import "tailwindcss/base";
```

#### TailwindCSSのカスタム関数

TailwindCSSでは固有の値にアクセスするためのカスタム関数があります。
関数はビルド時に評価され、最終的なCSSで静的な値に置き換えられます。

- `theme()`
    - `tailwind.config`のthemeで定義した値にアクセスできます
- `screen()`
    - ブレークポイントを参照するメディアクエリを作成できます

##### `theme()`の使い方
基本はドット記法を用いてアクセスし、ドットを含む値の場合`[]（ブラケット）`を利用します。
色の不透明度を指定することも可能ですが、ダッシュ構文は利用できません。

```jsx
.content-area {
  height: calc(100vh - theme(spacing.12));
  height: calc(100vh - theme(spacing[2.5]));
  background-color: theme(colors.blue-500);　 /* これは利用できない */
  background-color: theme(colors.blue.500 / 75%);
}
```

##### `screen()`の使い方
`@media`の後に関数を続けて利用します。

```jsx
@media screen(sm) {}
@media (min-width: 640px) {} /* ビルドされた後 */
```

## [Customization](https://tailwindcss.com/docs/configuration)
1. Configuration
1. Content
1. Theme
1. Screens
1. Colors
1. Spacing
1. Plugins
1. Presets

`tailwind.config.js`の設定について書かれています。
`tailwind.config.js`への定義はオプションであるため変更したい部分だけ記載します。
不足している箇所はデフォルトの設定が反映されます！


### [Configuration](https://tailwindcss.com/docs/configuration)
TailwindCSSをカスタマイズするためには、`tailwind.config.js`に追記していく必要があります。

全てを設定する必要はなく、不足しているセクションはデフォルトの設定が反映されます！
変更を加えたい箇所のみを指定するだけでOKです。

```tsx
module.exports = {
  content: ['./src/**/*.{html,js}'],
  theme: {
    colors: {
      'blue': '#1fb6ff',
    },
    extend: {
      spacing: {
        '8xl': '96rem',
        '9xl': '128rem',
      },
      borderRadius: {
        '4xl': '2rem',
      }
    }
  },
}
```

設定ファイルを作成するには`npx tailwindcss init`を実行すると下記の内容のファイルがプロジェクトルートに作成されます。

```js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [],
  theme: {
    extend: {},
  },
  plugins: [],
}
```

:::note info
`init`の後に拡張しを含めたファイル名を指定することで任意のファイル名で作成できます！
:::

カスタムのファイル名を使う場合はCSSをコンパイルしているツールの設定ファイルにパスを追加してやる必要があるので注意が必要です…。

https://tailwindcss.com/docs/configuration#using-a-different-file-name

contentにはTailwindCSSが含まれるファイルのパスを指定します。

```js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './pages/**/*.{html,js}',
    './components/**/*.{html,js}',
  ],
}
```

themaでは元々存在するtailwindのスタイルを上書きしたり、追加できます。

```js
/** @type {import('tailwindcss').Config} */
module.exports = {
  // ...
  theme: {
    colors: {},
    fontFamily: {},
    extend: {
      spacing: {},
      borderRadius: {}
    }
  }
}
```

presetsには、独自のカスタム基本構成を指定することができます。

```js
/** @type {import('tailwindcss').Config} */
module.exports = {
  presets: [
    require('@acmecorp/base-tailwind-config')
  ],
  theme: {},
}
```

prefixオプションを使用すると、Tailwindが生成したすべてのユーティリティクラスにカスタムプレフィックスを追加できます。

```js
/** @type {import('tailwindcss').Config} */
module.exports = {
  prefix: 'tw-',
}
```

:::note info
名前の競合が発生する可能性のある既存のCSSの上にTailwindCSSを重ねる場合に非常に便利です。
:::

```css:出力されるcss
.tw-text-left {
  text-align: left;
}

.tw-text-center {
  text-align: center;
}
```

バリアント修飾子の場合は修飾子の後に追加されます。
負の値のダッシュ修飾子の場合は`-tw-mt-8`のようになります。

:::note alert
独自のカスタムクラスにはプレフィックスは付与されないことに注意してください…
:::

独自のクラスにプレフィックスを付与したい場合は定義する時にプレフィックスを追加しないといけません。

`important`が付与されたTailwindCCSのクラスを生成したい場合は`config`に下記の設定を追加することで可能です。

```js
/** @type {import('tailwindcss').Config} */
module.exports = {
  important: true,
}
```

サードパティーのJSライブラリを利用する場合`important`オプションを設定しているとJSによってインラインで付与されたスタイルが無効になり、意図したデザインが崩れる可能性もあります。

```diff_javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
-  important: true,
+  important: '#app', 
}
```

`!`を先頭につけることで`important`を設定することが可能です。

```jsx
<p class="!font-medium">
<div class="sm:hover:!tw-font-bold">
```

修飾子とユーティリティクラスのセパレーターをカスタムすることが可能です。

```js
/** @type {import('tailwindcss').Config} */
module.exports = {
  separator: '_',
}
```

:::note info
ユースケースとしては、class名に特殊記法をサポートしていないテンプレート言語を利用する場合などが想定されます！
:::

`corePlugins`ではプロジェクトには必要がないクラスを無効にできます。
無効にする場合はオブジェクトを提供します。
セーフリストにする場合は配列、全てを無効にする場合は空配列を指定します。

```js
/** @type {import('tailwindcss').Config} */
module.exports = {
  corePlugins: {
    float: false,
    objectFit: false,
    objectPosition: false,
  }
}

// セーフリストを追加したい場合
module.exports = {
  corePlugins: [
    'margin',
    'padding',
    'backgroundColor',
  ]
}

// TailwindCSSを無効にする
module.exports = {
  corePlugins: []
}
```

コアプラグインの一覧はドキュメントの[コアプラグイン](https://tailwindcss.com/docs/configuration#core-plugins)のセクションにありますので必要があれば確認してみてください。

TailwindCSSは`@config`ディレクティブを利用してCSSのエントリポイントに使用する構成ファイルを指定することが可能です。

```js
@config "./tailwind.site.config.js";

@tailwind base;
@tailwind components;
@tailwind utilities;
```

定義した`tailwind.config`にアクセスするには下記のように記述すると可能です！

```javascript
import resolveConfig from 'tailwindcss/resolveConfig'
import tailwindConfig from './tailwind.config.js'

const fullConfig = resolveConfig(tailwindConfig)

fullConfig.theme.width[4]
```

TypeScript型を手動で構成するには、構成オブジェクトの上に型注釈を追加するだけです。

```typescript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
```

### [Content](https://tailwindcss.com/docs/content-configuration)
TailwindCSSは、すべてのファイルをスキャンしてクラス名を検索し、それらのスタイルに対応するすべての CSSを生成します。

プロジェクト内のTailwindクラス名を含むすべてのファイルについて認識させるためにcontent構成ファイルのセクションで、ファイルへのパスを記述します。

```typescript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './pages/**/*.{html,js}',
    './components/**/*.{html,js}'
  ],
}
```

ファイルパターンは下記の記号が使えます。

|記号|意味|
|--|--|
|*|スラッシュと隠しファイル以外の文字に一致させる|
|**|0個以上のディレクトリに一致させる|
|{}|オプションのリストと一致させるには、値をカンマで区切って使用|

パスはファイルではなくプロジェクトのルートを基準とするため、プロジェクトのルートを基準としたパスを記述する必要があります。

:::note info
Tailwindは内部で`fast-glob`ライブラリが使用されているので上記の表以外にもサポートされているので詳細を知りたい方は[github](https://github.com/mrmlnc/fast-glob)を確認してください！
:::

#### 避けるべきパスの設定方法

パフォーマンスの観点から広い範囲指定は避けましょう。

```typescript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './**/*.{html,js}',
  ],
}
```

CSSファイルはスキャンさせないように設定します。

```typescript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './src/**/*.css',
  ],
}
```

また実装する時にクラス名を動的に作成してしまうとTailwindはクラスを検知できないので注意が必要です。

```typescript:クラス名が検知されない例
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
<button className={`bg-${color}-600 hover:bg-${color}-500 ...`}>
```

#### 相対パスの利用
`relative`プロパティを`true`に設定します。
`tailwind.config`ファイルの対して相対的なパスで指定できます。

```javascript
module.exports = {
  content: {
    relative: true,
    files: [
      './pages/**/*.{html,js}',
      './components/**/*.{html,js}',
    ],
  },
}
```

:::note
非絶対的なコンテンツパスを使用することで、`tailwind.config`ファイルが配置されている場所に関係なく、同じパス構造を持つ他のプロジェクトでも同じ設定を再利用できます。これは、開発者がプロジェクト間でコードを共有したり、異なる環境（開発、本番など）で同じ設定を適用したい場合に便利です。
:::

> This will likely become the default behavior in the next major version of the framework.

こちらの設定は次のメジャーバージョンでは相対的なパスで指定する設定がデフォルトの動作になる可能性があるとのことです。

#### 生コンテンツのスキャンとセーフリスト＆ブラックリスト
ファイルではなくコンテンツをスキャンしないといけない場合は`raw`を設定すれば可能です。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    { raw: '<div class="font-bold">', extension: 'html' },
  ],
}
```

ただ、`raw`を利用することに有効な例は少ないようで、`safelist`を利用するのが一般的だそうです。
正規表現で指定することも可能です。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [],
  safelist: [
    'bg-red-500',
    'text-3xl',
    'lg:text-4xl',
    {
      pattern: /bg-(red|green|blue)-(100|200|300)/,
    },
  ]
}
```

`safelist`は、サイトがユーザー生成コンテンツを表示していて、サイトのソースに存在しない可能性のあるTailwindクラスのセットをユーザーがコンテンツ内で使用できるようにしたい場合利用します。

`blocklist`を利用するとコンテンツ内で検出された特定のクラスを無視するように指示できます。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [],
  blocklist: [
    'container',
    'collapse',
  ],
}
```

ファイル形式がマークダウンの場合は、スキャンする前にHTMLへ変換されることが望ましいです。
その場合は`transform`を利用します。

```javascript
const remark = require('remark')

module.exports = {
  content: {
    files: ['./src/**/*.{html,md}'],
    transform: {
      md: (content) => {
        return remark().process(content)
      }
    }
  },
}
```

### [Theme](https://tailwindcss.com/docs/theme)

`tailwind.config`に`theme`を定義するとカラー、タイプスケール、フォント、ブレークポイント、境界線の半径の値などを定義できます。

定義できるthemeの一覧は[ページ下部に表示](https://tailwindcss.com/docs/theme#configuration-reference)されています。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    screens: {
      sm: '480px',
    },
    colors: {
      'blue': '#1fb6ff',
    },
  }
}
```

#### `DEFAULT`のキーの利用
`DEFAULT`を使用すると、サフィックス（接尾辞）のないクラスが作成されます。

#### `extend`の利用

`extend`を利用すると新しいクラスとして定義できます。
theme直下に定義するとデフォルトのthemeが上書きされるので注意しましょう。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    // デフォルトテーマをオーバーライド
    opacity: {
      '0': '0',
      '20': '0.2',
      '40': '0.4',
    },
    // デフォルトテーマに追加
    extend: {
      fontFamily: {
        display: 'Oswald, ui-serif',
      }
    }
  }
}
```

指定されなかったキーはデフォルトのThemeが適用されます。
逆にデフォルトのキーの値を全てオーバーライドしたい場合は全てのキーをtheme直下で指定します。

#### themeの他の値を参照したい場合

テーマ内の他の値を参照したい場合は`thema()`を使います。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    backgroundSize: ({ theme }) => ({
      contain: 'contain',
      ...theme('spacing')
    })
  }
}
```

この方法はトップレベルの`theme`のキーのみで利用でき、
ここの値では利用できません。

```diff_javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
-    fill: {
-      // ここでは使えない
-      gray: ({ theme }) => theme('colors.gray')
-    }
+    // themeのトップレベルキーでのみ利用できる
+    fill: ({ theme }) => ({
+      gray: theme('colors.gray')
+    })
  }
}
```

#### 特定のコアプラグインのクラスを生成したくない場合

コアプラグイン名をキーにして`false`を設定します。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  corePlugins: {
    opacity: false,
  }
}
```

下記のようにthemeの中でキーに対して空のオブジェクトを設定する方法は推奨されていません。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    opacity: {},
  }
}
```

### [Customizing Screens](https://tailwindcss.com/docs/screens)
Tailwindのブレイクポイントは`mim-width`で設定されます。
デフォルトのブレイクポイント完全に置き換えるときは`tailwind.config`の`theme`直下に記述します。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    screens: {
      'sm': '640px',
      // => @media (min-width: 640px) { ... }
      'md': '768px',
      // => @media (min-width: 768px) { ... }
    }
  }
}
```
定義されたキー以外は利用できなくなるので注意してください、

一部だけ上書きしたい場合には`extend`の直下に`screens`を定義して記述を追記します。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      screens: {
        'lg': '992px',
        // => @media (min-width: 992px) { ... }
      },
    },
  },
}
```

#### 小さいブレイクポイントを追加するときは注意が必要
大きいブレイクポイントを追加する場合は`extend`の直下に`screens`を定義することで可能です。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      screens: {
        '3xl': '1600px',
      },
    },
  },
}
```

ただ、小さいブレイクポイントを`extend`で追加しても動作しません。
それは`extend`が、ブレークポイントリストの最後に追加するためです。

なので小さいブレイクポイントを追加する場合は小さいものから順番に並べる必要があるため`theme`直下に上書きする形式で記述します。

```javascript
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    screens: {
      'xs': '475px',
      ...defaultTheme.screens,
    },
  },
}
```

#### スクリーン名のカスタム

`xs`などではなく独自でカスタム名を設定できます。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    screens: {
      'tablet': '640px',
      // => @media (min-width: 640px) { ... }
      'desktop': '1280px',
      // => @media (min-width: 1280px) { ... }
    },
  }
}
```

#### 最大幅のブレイクポイントを設定する
TailwindCSSのブレイクポイントは`min-width`を設定されます。
`max-width`でブレイクポイントを設定することもできます。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    screens: {
      '2xl': {'max': '1535px'},
      // => @media (max-width: 1535px) { ... }
       'xl': {'max': '1279px'},
      // => @media (max-width: 1279px) { ... }
  }
}
```

最大幅を定義するときは降順で定義する必要があります。
`min-width`と`max-width`両方指定する場合には、`min`も合わせて定義します。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    screens: {
      'sm': {'min': '640px', 'max': '767px'},
      // => @media (min-width: 640px and max-width: 767px) { ... }
      'md': {'min': '768px', 'max': '1023px'},
      // => @media (min-width: 768px and max-width: 1023px) { ... }
    },
  }
}
```

複数の範囲のブレイクポーンとを設定したいときは下記のように設定します。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    screens: {
      'sm': '500px',
      'md': [
        {'min': '668px', 'max': '767px'},
        {'min': '868px'}
      ],
    }
  }
}
```

`767px`を超えて`868px`までの間は`sm`で設定したスタイルが適用されます。
その後`868px`になれば`md`で設定したスタイルが適用されるようになります。

`raw`を使って定義することでメディアクエリを独自に定義できます。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      screens: {
        'tall': { 'raw': '(min-height: 800px)' },
        // => @media (min-height: 800px) { ... }
      }
    }
  }
}
```

### [Customizing Colors](https://tailwindcss.com/docs/customizing-colors)

カラーの設定をカスタマイズする場合は、`theme`直下の`colors`キーで定義します！

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    colors: {
       'white': '#ffffff',
       'purple': '#3f3cbb',
    },
    extend: {
      colors: {
        brown: {
          50: '#fdf8f6',
          100: '#f2e8e5',
        },
      }
    },
  }
}
```

`theme.colors`に定義するとデフォルトのカラーパレットを置き換えられます。
デフォルトのカラーパレットに色を追加したい場合は`theme.extend`の直下に`colors`をキーとしてオブジェクトを定義します。
定義したカラーはテキスト、境界線、背景色で利用できます。

:::note
`white`の部分を`primary`などのセマンティックな命名を利用できます。
:::

同じパレットの中に色の種類がある場合はネストすることで実現できます。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    colors: {
      'tahiti': {
        light: '#67e8f9',
        DEFAULT: '#06b6d4',
        dark: '#0e7490',
        100: '#cffafe',
        200: '#a5f3fc',
        300: '#67e8f9',
      },
    },
  },
}
```

`bg-tahiti-300`と記述することでカラーを指定できます。
また、`DEFAULT`で定義するとサフィックスのない`bg-tahiti`でカラーを指定できる値を定義できます。

#### デフォルトの色を使用する
`tailwindcss/colors`ファイルをインポートすることでtailwindがデフォルト定義されているカラーを利用できます。

```javascript
const colors = require('tailwindcss/colors')

module.exports = {
  theme: {
    colors: {
      black: colors.black,
      white: colors.white,
    },
  },
}
```

#### CSS変数を使用する
CSS変数を利用してカラーを定義する場合、不透明度修飾子`text-blue-600/80`のように`/80`で不透明度を設定するためには下記のように実装します。

```diff_javascript
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
-    --color-primary: rgb(255 115 179);
+    --color-primary: 255 115 179;
  }
}
```
次に`tailwind.config`の設定を変えます。

```diff_javascript
module.exports = {
  theme: {
    extend: {
      colors: {
-        primary: 'var(--color-primary)',
+        primary: 'rgb(var(--color-primary) / <alpha-value>)', 
      }
    },
  },
}
```

### [Customizing Spacing](https://tailwindcss.com/docs/customizing-spacing)

Spacingは`theme`直下に`spacing`をキーとしてオブジェクトを定義します。
`theme`直下に定義するとデフォルトのSpacingが上書きされます。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    spacing: {
      '1': '8px',
      '2': '12px',
    }
  }
}
```

拡張するときは`extend`の直下に`spacinng`をキーとしてオブジェクトを定義します。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      spacing: {
        '13': '3.25rem',
        '15': '3.75rem',
      }
    }
  }
}
```

### [Plugins](https://tailwindcss.com/docs/plugins)
プラグインを利用する場合は`tailewindcss/plugin`をimportして関数を呼び出して利用します。

```javascript
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities, addComponents, e, config }) {
      // Add your custom styles here
    }),
  ]
}
```

npm経由でインストールして利用できる公式のプラグインもあります。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  plugins: [
    require('@tailwindcss/typography'),
    require('@tailwindcss/forms'),
    require('@tailwindcss/aspect-ratio'),
    require('@tailwindcss/container-queries'),
  ]
}
```

- [@tailwindcss/typography](https://github.com/tailwindlabs/tailwindcss-typography)
- [@tailwindcss/forms](https://github.com/tailwindlabs/tailwindcss-forms)
- [@tailwindcss/aspect-ratio](https://github.com/tailwindlabs/tailwindcss-aspect-ratio)
- [@tailwindcss/container-queries
](https://github.com/tailwindlabs/tailwindcss-container-queries)

#### utilitiesレイヤーにクラスを追加する
`addUtilities`と`matchUtilities`を使うとTailwindのutilitiesレイヤーに新しいスタイルを登録できます。

```javascript
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities }) {
      addUtilities({
        '.content-auto': {
          'content-visibility': 'auto',
        },
      })
    })
  ]
}
```

`matchUtilities`を利用すると`theme`に定義した値をマップしてユーティリティクラスとして定義する時に利用します。

```javascript
const plugin = require('tailwindcss/plugin')

module.exports = {
  theme: {
    tabSize: {
      1: '1',
      2: '2',
      4: '4',
      8: '8',
    }
  },
  plugins: [
    plugin(function({ matchUtilities, theme }) {
      matchUtilities(
        {
          tab: (value) => ({
            tabSize: value
          }),
        },
        { values: theme('tabSize') }
      )
    })
  ]
}
```

上記のように定義すると`tab-1`や`tab-4`をclassとして使えます。
この方法で定義すると`tab-[13]`のような任意の値もサポートされます。

#### `prefix`と`importanat`の利用

`tailwind.config`のに設定を追加すると自動で追加してくれます。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  prefix: 'tw-',
  important: true,
}
```

上記の設定でCSSは下記のようにスタイルを生成されます。

```css
.tw-content-auto {
  content-visibility: auto !important;
}
```

セレクター内のクラスにもプレフィックスが付与されます。

```javascript
const plugin = require('tailwindcss/plugin')

module.exports = {
  prefix: 'tw-',
  plugins: [
    plugin(function({ addComponents }) {
      const components = {
        '.navbar-inverse a.nav-link': {
            color: '#fff',
        }
      }

      addComponents(components)
    })
  ]
}
```
設定したプレフィックスは、`navi-link`にも付与されます。
```css
.tw-navbar-inverse a.tw-nav-link {
    color: #fff;
}
```

#### コンポーネントの追加
`addComponents`を利用することで新しいスタイルを登録できます。

```javascript
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addComponents }) {
      addComponents({
        '.btn': {
          padding: '.5rem 1rem',
          borderRadius: '.25rem',
          fontWeight: '600',
        },
      })
    })
  ]
}
```

#### baseレイヤーに新しいクラスを追加する
`addBase`を利用して追加します。

```javascript
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addBase, theme }) {
      addBase({
        'h1': { fontSize: theme('fontSize.2xl') },
        'h2': { fontSize: theme('fontSize.xl') },
        'h3': { fontSize: theme('fontSize.lg') },
      })
    })
  ]
}
```

baseは`div`のようなセレクタをターゲットのすることを目的にしているため、`prefix`や`inportant`は付与されません。

#### バリエーションの追加
独自のカスタム修飾子を定義できます。

```javascript
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addVariant }) {
      addVariant('optional', '&:optional')
      addVariant('hocus', ['&:hover', '&:focus'])
      addVariant('inverted-colors', '@media (inverted-colors: inverted)')
    })
  ]
}
```

上記のように定義した場合下記のように利用できます。

```html
<form class="flex inverted-colors:outline">
  <input class="optional:border-gray-300" />
  <button class="bg-blue-500 hocus:bg-blue-600">...</button>
</form>
```



##### ダイナミックバリアント
`matchVariant`を利用して`data-*`や`aria-*`のような新しいバリアントを登録できます。

```jsx:tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ matchVariant }) {
      matchVariant(
        'nth',
        (value) => {
          return `&:nth-child(${value})`;
        },
        {
          values: {
            1: '1',
            2: '2',
            3: '3',
          }
        }
      );
    })
  ]
}
```

新しく追加したバリアントでは`[]`を利用した任意の値も指定できます！

```jsx
<div class="nth-[3n+1]:bg-blue-500">
```

#### 親と兄弟の状態

カスタム修飾子は、親と兄弟の状態修飾子で利用するには、個別のバリアントとして登録する必要があります。

```jsx:tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addVariant }) {
      addVariant('optional', '&:optional')
      addVariant('group-optional', ':merge(.group):optional &')
      addVariant('peer-optional', ':merge(.peer):optional ~ &')
    })
  ]
}
```

記述のルールとしてクラスの最終セレクターに1回だけ表示されるように記述する必要があるとのことです。

:::note
ちなみに`:merge`はTailwindCSSが用意しているカスタムディレクティブで、たくさんバリアントが重なった場合に`tailwind.config`でまとめられます。
:::

### [Presets](https://tailwindcss.com/docs/presets)
`presets`を利用して別で定義した構成をデフォルトの構成とマージして利用できます。
複数の別ブランドのTailwindプロジェクトを管理する場合に便利です。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  presets: [
    require('@acmecorp/tailwind-base')
  ],
  // ...
}
```

デフォルトを無効にするには`presets`を空にすることで可能です。
`tailwind.config`がマージされる時、以下の項目は置き換えられます。

- content
- darkMode
- prefix
- important
- variantOrder
- separator
- safelist

それ以外の項目に関しては、別の挙動になるので確認しておきましょう。

- [theme](https://tailwindcss.com/docs/presets#theme)
- [presets](https://tailwindcss.com/docs/presets#presets)
- [plugins](https://tailwindcss.com/docs/presets#plugins)
- [core-plugins](https://tailwindcss.com/docs/presets#core-plugins)

#### 複数のpresetsを利用する場合
`presets`で複数指定する場合注意が必要です。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  presets: [
    require('@acmecorp/configuration-a'),
    require('@acmecorp/configuration-b'),
  ]
}
```

上記のように複数設定した場合、それぞれでカラーパレットを提供されていたとき後に定義された方が有効になります。

## Preflight
Tailwindで定義されているいわゆるリセットCSSです。
`@tailwind base`を記述すれば自動的に設定されます。

Tailwindのpreflightが実行していることは下記の通りです。

- マージンの削除
- 見出しスタイルの無効化
- リストスタイルの無効化
- borderスタイルの無効化
- 画像には`display: block`、アスペクト比を保つための設定

:::note warn
リストはスタイルが無効化されている場合、VoiceOverによってリストとして認識されません。
アクセシビリティを考慮する場合は`role`属性を追加しましょう。

```html
<ul role="list">
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
</ul>
```
:::

preflightを反映したくない場合は、`tailwind.config`の設定で無効にできます。

```javascript
module.exports = {
  corePlugins: {
    preflight: false,
  }
}
```

設定や仕様のパートが終わり次からTailwindで利用できるクラスについてです。

## Tanilwindで利用できるクラス

Tailwindで利用できるクラスは下記のようにカテゴリで分けられています。
基本的にtailwindの命名規則について書かれているのであえてまとめることはしないでおこうと思います。

ただ、tailwind特有の作法のようが書かれていた場合、抜粋してまとめておこうと思います。

- Layout
- Flexbox & Grid
- Spacing
- Sizing
- Typography
- Backgrounds
- Border
- Effects
- Filters
- Tables
- Transitions & Animation
- Transforms
- Interactivity
- SVG
- Accessibility

### Container
コンテナをデフォルトでセンタリングしたい場合は下記のように設定すると実現できます。
```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    container: {
      center: true,
    },
  },
}
```

水平paddingを追加したい場合は、`padding`を利用します。
また、ブレイクポイントごとに`padding`を設定する場合は`DEFAULT`とブレイクポイントに対応したあたいを定義します。

```javascript
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    container: {
      padding: {
        DEFAULT: '1rem',
        sm: '2rem',
        lg: '4rem',
        xl: '5rem',
        '2xl': '6rem',
      },
    },
  },
};
```

### Overscroll Behavior

スクロールコンテンツがスクロールし終えると親のコンテンツがスクロールし始めます。
`overscroll-contain`を設定すると

![overscroll-contain.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146612/cdd61402-8126-07cd-de7c-6f571be47aaf.gif)

さらに、一番下までスクロールすると跳ね返るような動作を`overscroll-none`を設定すると動作を削除できます。

### Spacing

`space-*`ユーティリティは分割ユーティリティとはペアリングできない用に設計されているので利用時に注意が必要です。

### Transforms

`transform-gpu`を追加することでハードウェアアクセラレーション[^2]を強制できます。
ハードウェアアクセラレーションを強制することで、アニメーションがよりスムーズになり読み込み時間が短縮され、全体的なパフォーマンスの向上が見込めます。

## Official Plugins

- [tailwindcss-typography](https://github.com/tailwindlabs/tailwindcss-typography)
    - proseMarkdownからレンダリングされたHTMLやCMSから取得されたHTMLなど、制御できない通常のHTMLに美しいタイポグラフィのデフォルトを追加するために使用できるクラスのセットを提供
- [tailwindcss-forms](https://github.com/tailwindlabs/tailwindcss-forms)
    - フォームスタイルのリセットを提供。ユーティリティを使用してフォーム要素を簡単に上書きできるようにするプラグイン
- [tailwindcss-aspect-ratio](https://github.com/tailwindlabs/tailwindcss-aspect-ratio)
    - 要素に固定のアスペクト比を与えるための構成可能なAPIを提供するプラグイン
- [tailwindcss-container-queries](https://github.com/tailwindlabs/tailwindcss-container-queries)
    - コンテナクエリ用のユーティリティを提供するTailwindCSSv3.2+用のプラグイン


[^1]:`@tailwind`で定義されるbase、components、utilitiesの3つのレイヤーのこと
[^2]: GPUアクセラレーションとも呼ばれます。プロセッシングユニット(GPU)を使用して、アプリ内の視覚要素のレンダリングを高速化する機能です。