TailwindCSSで実装する時に知っておくべきポイント18選

TailwdindCSSの実装時に知っておけると良いと思うポイントをまとめました！
参考にいただけると幸いです！

## Summary
- [hoverでのスタイル定義について](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#hover%E3%81%A7%E3%81%AE%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E5%AE%9A%E7%BE%A9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
- [peerを利用する際の注意点](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#peer%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E9%9A%9B%E3%81%AE%E6%B3%A8%E6%84%8F%E7%82%B9)
- [`*`を利用してスタイルを適用させた場合の注意点](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%A6%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%82%92%E9%81%A9%E7%94%A8%E3%81%95%E3%81%9B%E3%81%9F%E5%A0%B4%E5%90%88%E3%81%AE%E6%B3%A8%E6%84%8F%E7%82%B9)
- [`content:`を利用する場合](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#content%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E5%A0%B4%E5%90%88)
- [preflightがリセットしていないもの](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#preflight%E3%81%8C%E3%83%AA%E3%82%BB%E3%83%83%E3%83%88%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%82%82%E3%81%AE)
- [`marker`のスタイリングについて](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#marker%E3%81%AE%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AA%E3%83%B3%E3%82%B0%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
- [任意の修飾子を複数回利用したい場合](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#%E4%BB%BB%E6%84%8F%E3%81%AE%E4%BF%AE%E9%A3%BE%E5%AD%90%E3%82%92%E8%A4%87%E6%95%B0%E5%9B%9E%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88)
- [Tailwindの親および兄弟の状態修飾子では自動的には機能しない](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#tailwind%E3%81%AE%E8%A6%AA%E3%81%8A%E3%82%88%E3%81%B3%E5%85%84%E5%BC%9F%E3%81%AE%E7%8A%B6%E6%85%8B%E4%BF%AE%E9%A3%BE%E5%AD%90%E3%81%A7%E3%81%AF%E8%87%AA%E5%8B%95%E7%9A%84%E3%81%AB%E3%81%AF%E6%A9%9F%E8%83%BD%E3%81%97%E3%81%AA%E3%81%84)
- [ブレイクポイントについての重要事実](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#%E3%83%96%E3%83%AC%E3%82%A4%E3%82%AF%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6%E3%81%AE%E9%87%8D%E8%A6%81%E4%BA%8B%E5%AE%9F)
- [ダークモードバリアントを上書きする時は注意](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#%E3%83%80%E3%83%BC%E3%82%AF%E3%83%A2%E3%83%BC%E3%83%89%E3%83%90%E3%83%AA%E3%82%A2%E3%83%B3%E3%83%88%E3%82%92%E4%B8%8A%E6%9B%B8%E3%81%8D%E3%81%99%E3%82%8B%E6%99%82%E3%81%AF%E6%B3%A8%E6%84%8F)
- [`@apply`を使わない](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#apply%E3%82%92%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84)
- [空白の処理](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#%E7%A9%BA%E7%99%BD%E3%81%AE%E5%87%A6%E7%90%86)
- [ユーティリティクラスとして定義されてないものをつかいたい時](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#%E3%83%A6%E3%83%BC%E3%83%86%E3%82%A3%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AF%E3%83%A9%E3%82%B9%E3%81%A8%E3%81%97%E3%81%A6%E5%AE%9A%E7%BE%A9%E3%81%95%E3%82%8C%E3%81%A6%E3%81%AA%E3%81%84%E3%82%82%E3%81%AE%E3%82%92%E3%81%A4%E3%81%8B%E3%81%84%E3%81%9F%E3%81%84%E6%99%82)
- [`@layer`ディレクティブは個別のコンポーネント内では利用しない](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#layer%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%86%E3%82%A3%E3%83%96%E3%81%AF%E5%80%8B%E5%88%A5%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E5%86%85%E3%81%A7%E3%81%AF%E5%88%A9%E7%94%A8%E3%81%97%E3%81%AA%E3%81%84)
- [`!import`を使いたい場合の注意点](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#import%E3%82%92%E4%BD%BF%E3%81%84%E3%81%9F%E3%81%84%E5%A0%B4%E5%90%88%E3%81%AE%E6%B3%A8%E6%84%8F%E7%82%B9)
- [`@config`利用時の注意](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#config%E5%88%A9%E7%94%A8%E6%99%82%E3%81%AE%E6%B3%A8%E6%84%8F)
- [tailwind.configへのアクセスについて](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#tailwindconfig%E3%81%B8%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)
- [動的class名](https://qiita.com/tanimoto-hikari/items/5c567533751605646df6#%E5%8B%95%E7%9A%84class%E5%90%8D)

## hoverでのスタイル定義について

TailwindCSSでは、既存のクラスにホバー状態を追加するのではなく、ホバー時のみ実行するクラス要素を追加されることを留意しなければなりません…

:::note
動作が想定通りではない…と思ったら、通常の`:hover`とは違うことを思い出せると良いでしょう！
:::

## peerを利用する際の注意点

`peer`は、`peer`の直後に`peer-*`を付与した要素を設置することで利用できます。
順番を前後させてしまうと動作しないことに注意してください。

```jsx
<p className="peer-invalid:visible">
  Please provide a valid email address.
</p>
<input type="email" className="peer"/>
```

## `*`を利用してスタイルを適用させた場合の注意点

親要素で`*`を利用して子要素に対してスタイルを適用させた場合、子要素でユーティリティclassを適用してのclassのオーバーライドは機能しません。

```jsx
<ul className="*:p-4">
  <li className="p-2">list item</li>
  <li className="pt-6">list item</li>
  <li>list item</li>
</ul>
```

## `content:`を利用する場合

TailwindCSSではデフォルトで`content: ''`が設定されています。
別の値が必要な場合の除いて指定する必要がありません！

:::note
`content: ''`がデフォルトで設定されているのは、TailwindCSSで用意されている[preflight](https://tailwindcss.com/docs/preflight)で設定されているからです。
もし、無効にしていた場合は`content-['']`を設定する必要があります。
:::

## preflightがリセットしていないもの

TailwindCSSのpreflightでファイル入力ボタンのborderはリセットされません…。
リセットや追加には明示的に指定する必要があります。

https://tailwindcss.com/docs/preflight

## `marker`のスタイリングについて

`marker`は継承可能な設計になっているため、`<li>`に直接指定できるだけでなく繰り返しを避けるために親の`ul`等で指定することもできます！

:::note alert
markerのデフォルトスタイルがpreflightではリセットされているためulタグからrole='list'が消えてしまっているため、ulに対してrole='list'をしておくことをオススメします。
:::

## 任意の修飾子を複数回利用したい場合
`tailwind.config`でプラグインを定義することで繰り返し利用することができます。

```jsx
let plugin = require('tailwindcss/pligin')

module.exports = {
  //...
  plugins = [
    plugin(function({ addVariant })) {
      addVariant('third', '&:nth-child(3)')
    }
  ]
}
```

https://tailwindcss.com/docs/plugins#adding-variants


## Tailwindの親および兄弟の状態修飾子では自動的には機能しない
カスタム修飾子は親要素や兄弟要素の状態修飾子を機能させるためには設定を追加する必要があります。

```jsx
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 ~ &')
    })
  ]
}
```

https://tailwindcss.com/docs/plugins#parent-and-sibling-states


## ブレイクポイントについての重要事実

TailwindCSSのブレイクポイントは下記のように指定します。

```html
<div class="text-center sm:text-left"></div>
```

>このアプローチで人々が最も驚かされるのは、モバイル用にスタイルを設定するには、ユーティリティのプレフィックス付きバージョンではなく、sm:プレフィックスなしバージョンを使用する必要があることです。「小さな画面で」という意味ではなくsm:、「小さなブレークポイントで」という意味で考えてください。

TailwindCSSは、プレフィックスのないユーティリティを使用してモバイルをターゲットにし、より大きなブレークポイントでそれらをオーバーライドすることでスタイルを適用させます！

https://tailwindcss.com/docs/responsive-design#targeting-mobile-screens
​
## ダークモードバリアントを上書きする時は注意

TailwindCSSで用意されているダークモードバリアントを置き換えたい場合は下記のようにします。

```jsx:tailwind.config
module.exports = {
  darkMode: ['variant', '&:not(.light *)'],
}
```
提供されたセレクターを一切変更しないため、セレクターの詳細度に注意し、自分で`:where()`疑似クラスを使用して他のユーティリティと同じ詳細度を確保するする必要があります。

## `@apply`を使わない
TailwindCSSの公式ドキュメントには`@apply`を利用する記述がいくつかあります。
ただ、`@apply`は利用することが推奨されていないことを意識しましょう。

> 見た目を「きれいに」するためだけに使用しないでください

と書かれているように`@apply`はTailwindCSSを利用することで得られるメリットを破壊してしまう可能性が高いためです…。

https://tailwindcss.com/docs/reusing-styles#avoiding-premature-abstraction

## 空白の処理

任意の値にスペースを含めるには_（アンダースコア）を使用します。
するとビルド時に自動的にスペースに変換します。

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

URLではアンダースコアが保持されます。
```html
<div class="bg-[url('/what_a_rush.png')]">
```

アンダースコアをバックスラッシュでエスケープすると、スペースに変換しません。
```html
<div class="before:content-['hello\_world']">
```

レンダリングされたHTMLからバックスラッシュが削除される場合は、`String.raw()`を使用するとバックスラッシュがJavaScriptエスケープ文字として扱われるようになります。
```html
<div className={String.raw`before:content-['hello\_world']`}>
```

## ユーティリティクラスとして定義されてないものをつかいたい時
TailwindCSSで使用できるユーティリティが含まれていないCSSプロパティを使用するには角括弧表記を使用して記述します。

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

https://tailwindcss.com/docs/adding-custom-styles#arbitrary-properties

## `@layer`ディレクティブは個別のコンポーネント内では利用しない

TailwindCSSは`<style>`タグが書かれてコンポーネントの数だけ生成しようとするため、最終的な出力CSSが予期せぬ形になる可能性があります。

各styleブロック間でのスタイルの整合性が保証されないため、期待通りのレイヤー構造を得られない可能性があります。

https://tailwindcss.com/docs/adding-custom-styles#layers-and-per-component-css


## `!import`を使いたい場合の注意点
@apply既存のクラスを にして にしたい場合は!important、!important宣言の最後に以下を追加するだけです。

```css
/* Input */
.btn {
  @apply font-bold py-2 px-4 rounded !important;
}

/* Output */
.btn {
  font-weight: 700 !important;
  padding-top: .5rem !important;
  padding-bottom: .5rem !important;
  padding-right: 1rem !important;
  padding-left: 1rem !important;
  border-radius: .25rem !important;
}
```

:::note alert
Sass/SCSSを使用している場合、Sassの補間機能を使用する必要があることに注意してください。

```css
.btn {
  @apply font-bold py-2 px-4 rounded #{!important};
}
```
:::

## `@config`利用時の注意

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

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

https://tailwindcss.com/docs/functions-and-directives#config

## tailwind.configへのアクセスについて

関数`theme()`を使用して、ドット表記を使用してアクセスします。

```css
.content-area {
  height: calc(100vh - theme(spacing.12));
}
```

ドットを含む値 (2.5間隔スケールの値など) にアクセスする必要がある場合は、角括弧表記を使用できます。

```css
.content-area {
  height: calc(100vh - theme(spacing[2.5]));
}
```

:::note alert
ネストされたカラー値にアクセスするときはダッシュ構文を使用しないでください

```css
.btn-blue {
  background-color: theme(colors.blue-500);
}
```
:::

ドット表記を使用してネストされたカラー値にアクセスする
```css
.btn-blue {
  background-color: theme(colors.blue.500);
}
```

不透明度を調整するにはスラッシュに続けて使用する不透明度の値を指定します。

```css
.btn-blue {
  background-color: theme(colors.blue.500 / 75%);
}
```

https://tailwindcss.com/docs/functions-and-directives#theme

## 動的class名

TailwindCSSは実際にはソースコードを評価せず、静的で途切れていないクラス文字列しか検出できません。

```html
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
```

コードでは常に完全なクラス名を使用するようにしてください。

```html
<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
```

https://tailwindcss.com/docs/content-configuration#dynamic-class-names

## まとめ
TailwindCSSは色々と通常とは異なるルールがあります。

:::note
把握しておくことで予期せぬ動作やTailwindCSSのメリットを壊しかねない実装を防ぐことになります！
:::

本記事がTailwindCSSを理解するための一助になれば幸いです！