🌬

Tailwind CSS の一歩進んだ書き方

2022/05/23に公開

Changelog

2023.12.25
  • v3.3、v3.4 の機能を追加
  • theme() 関数の追加
  • 解説順の変更

以下差分:

-## CSS カスタムプロパティ
+## CSS カスタムプロパティの宣言

+## CSS カスタムプロパティの利用
+
+```html:html
+<h1 class="px-[--gutter]">
+  Hello world!
+</h1>
+```
+
+`px-[var(--gutter)]` のように記述することもできますが、`var()` は省略可能です。

-<h1 class="text-[length:var(--title-size)] text-[color:var(--title-color)]">
+<h1 class="text-[length:--title-size] text-[color:--title-color]">
+## フォントサイズと一緒に行の高さを指定するショートハンド
+
+```html:html
+<h1 class="text-5xl/tight">
+  Hello world!
+</h1>
+```
+
+もちろん `text-5xl leading-tight` のように別々でも記述できますが、`/` を使えば短く書けます。
+
+```html:html
+<h1 class="text-5xl/[4rem]">
+  Hello world!
+</h1>
+```
+
+任意値も使えます。
+## グラデーションの位置調整
+
+```html:html
+<h1 class="bg-gradient-to-r from-indigo-500 from-10% via-purple-500 via-[31.56%] to-pink-500 to-90%">
+  Hello world!
+</h1>
+```
+
+`from` `via` `to` でグラデーションの位置を調整できます。任意の値を使うことも可能。
+
 ## 子要素を一括指定

+```html:html
+<dl class="[&>dt]:font-bold">
+  <dt>Foo</dt>
+  <dd>Semper cursus dictumst.</dd>
+  <dt>Bar</dt>
+  <dd>Dapibus rhoncus nec.</dd>
+</dl>
+```
+
+上記は特定の子要素を指定する方法ですが、すべての子要素の場合は下記のように `*` を使って短く書けます。`li` などのスタイリングで便利です。

 ```html:html
-<ul class="[&>li]:border-b">
+<ul class="*:border-b">
   <li>1st</li>
   <li>2nd</li>
   <li>3rd</li>
 </ul>
 ```

+上記は `[&>*]:border-b` に相当します。
+## CSS ファイル内で Tailwind CSS で設定されている値を使う
+
+```css:css
+h1 {
+  font-size: min(5vw, theme(fontSize.7xl));
+}
+```
+
+CSS ファイル内での基本的なスタイリングは `@apply text-7xl;` のように記述できますが、関数などで値のみを利用したい場合は `theme()` 関数で実現できます。`theme()` 関数の引数は `tailwind.config.js` の `theme` や `extend` のプロパティに対応しています。
+
+## 任意値内で Tailwind CSS で設定されている値を使う
+
+```html:html
+<h1 class="text-[min(5vw,theme(fontSize.7xl))]">
+  Hello world!
+</h1>
+```
+
+CSS ファイル同様、任意値内でも `theme()` 関数を利用することで Tailwind CSS テーマの設定値を使うことができます。
+
+## `theme()` 関数での色の透明度も `/` で指定可能
+
+```css:css
+h1 {
+  background: theme(colors.red.500 / 25%);
+}
+```
+
+```html:html
+<h1 class="bg-[theme(colors.red.500/25%))]">
+  Hello world!
+</h1>
+```
+
+CSS ファイルでも任意値でも利用可能。
2023.02.24
  • v3.2 の機能を追加

以下差分:

+## `data` 属性
+
+```html:html
+<h1 class="text-2xl data-[size=large]:text-3xl">
+  Hello world!
+</h1>
+```
+
+通常は `text-2xl` ですが、`data-size="large"` がある場合は `text-3xl` になります。
+## ネストされた祖先要素の状態によるスタイリング
+
+```html:html
+<div class="group">
+  <a href="https://example.com/">Hello world!</a>
+  <div class="invisible group-hover:visible group/child">
+    <a href="https://example.com/child/">Child</a>
+    <div class="invisible group-hover/child:visible">
+      <a href="https://example.com/child/grandchild/">Grandchild</a>
+    </div>
+  </div>
+</div>
+```
+
+たとえば、マウスホバーしたときに下層メニューを表示するようなネストされたナビゲーションでは、`group` だけだと最下層のメニューまで表示されてしまいます。`group/*` のようにそれぞれのグループに名前をつけることでこの問題を解決できます。スタイリングしたい要素には `group-hover/*` のようなバリアントをつけます。
-
-:::message alert
-以下 v3.1 で実装される予定の variant にも任意値ですが、`tailwindcss@insiders` をインストールすることでテスト可能です。
-:::
-
+```html:html
+<body class="group home">
+  <h1 class="text-black group-[.home]:text-red-500">
+    Hello world!
+  </h1>
+</body>
+```
+
+v3.2 で追加されたダイナミック `group-*` でも書けます。
+## メディアクエリの `max-width`
+
+```html:html
+<h2 class="sr-only lg:not-sr-only">
+  Menu
+</h2>
+```
+
+Tailwind CSS では通常メディアクエリは `min-width` を使ったモバイルファーストになっているので、上記のようにモバイルでは非表示にしたい場合、デスクトップでスタイルを戻す必要がありました。
+
+```html:html
+<h2 class="max-lg:sr-only">
+  Menu
+</h2>
+```
+
+`max-*` バリアントを使えば元に戻すという手間が不要になります。プロパティが複数ある場合はかなりわかりやすく書けるようになります。
+
+## ダイナミックブレークポイント
+
+```html:html
+<h1 class="text-7xl min-[1440px]:text-[5vw]">
+  Hello world!
+</h1>
+```
+
+特殊なブレークポイントのために、いちいち `screens` に設定を追加する必要がなくなります。

はじめに

Tailwind CSS とは何か」については理解している前提で進めます。

html
<h1 class="text-3xl font-bold underline">
  Hello world!
</h1>

簡単な例として、上記 HTML を記述すると、以下のようにスタイリングされます。

スタイリングされた Hello world! のスクリーンショット

Just-in-Time 改め arbitrary values

上記例にある text-3xl などのスタイルは予め Tailwind CSS が用意しているものですが、tailwind.config.js を編集することで簡単に変更・追加できます。ただし、1 回しか使わないスタイルでもいちいち tailwind.config.js に登録しないといけないので、その不便さを解消する機能として v2.1 から Just-in-Time (JIT) モードが導入されました。

v3.0 からは JIT がデフォルトになりましたので、わざわざ「JIT モード」ということもなくなり、ドキュメントではその機能を単に arbitrary values (任意値) と記述しています。

html
<h1 class="text-[10vw] font-bold underline">
  Hello world!
</h1>

text-[10vw] のように記述することで、登録されていないスタイルでも以下の CSS が自動的に生成されます。

css
.text-\[10vw\] {
  font-size: 10vw;
}

スタイリングされた Hello world! のスクリーンショット

一歩進んだ記述方法まとめ

しかし、自由度が増したことで記述方法が複雑になってきましたので、それらをまとめていきます。

シンプルな任意値

html
<h1 class="text-[10vw]">
  Hello world!
</h1>

マイナス値は角括弧内で

html
<h1 class="ml-[-1em]">
  Hello world!
</h1>

通常では -ml-1 のように先頭に - をつけますが、任意値は [] の中に記述します。

値に calc() clamp() などを使う場合はスペースをつめる

html
<h1 class="text-[clamp(32px,2.5vw+24px,48px)]">
  Hello world!
</h1>

スペースが必要な値は代わりに _ を使う

html
<h1 class="drop-shadow-[0_0_1em_#0ff]">
  Hello world!
</h1>

CSS カスタムプロパティの宣言

html
<h1 class="[--viewport-from:320] [--viewport-to:960] [--min-font-size:32] [--max-font-size:48]">
  Hello world!
</h1>

以前投稿した「CSS カスタムプロパティによる流動的フォントサイズ」のように、要素に CSS カスタムプロパティを設定することでスタイリングするようなケースで重宝されます。

CSS カスタムプロパティの利用

html
<h1 class="px-[--gutter]">
  Hello world!
</h1>

px-[var(--gutter)] のように記述することもできますが、var() は省略可能です。

データ型の明示

html
<h1 class="text-[length:--title-size] text-[color:--title-color]">
  Hello world!
</h1>

text- のように、色やサイズの複数プロパティが一つの名前を共有しているケースがあります。text-[22px] text-[#bada55] を記述すると、サイズなのか色なのかは、値から自動的に判別されます。しかし、CSS カスタムプロパティなど、値から判別できない場合があります。このようなときは length:color: などで明示することができます。CSS カスタムプロパティ以外でも、たとえば background-sizebg-[length:200px_100px] のようにデータ型を明示する必要があったりします。

任意のプロパティ

html
<h1 class="animate-bounce [animation-delay:3s]">
  Hello world!
</h1>

用意されていないプロパティは上記の [animation-delay:3s] のように書けます。アニメーションの細かい調整も可能になります。

フォントサイズと一緒に行の高さを指定するショートハンド

html
<h1 class="text-5xl/tight">
  Hello world!
</h1>

もちろん text-5xl leading-tight のように別々でも記述できますが、/ を使えば短く書けます。

html
<h1 class="text-5xl/[4rem]">
  Hello world!
</h1>

任意値も使えます。

::before ::after などの疑似要素・擬似クラス

html
<h1 class="after:content-['👋🏼']">
  Hello world!
</h1>

::before ::after 以外にもさまざまな疑似要素・擬似クラスが用意されています。こちらの一覧表をご覧ください。

data 属性

html
<h1 class="text-2xl data-[size=large]:text-3xl">
  Hello world!
</h1>

通常は text-2xl ですが、data-size="large" がある場合は text-3xl になります。

祖先要素の状態によるスタイリング

html
<a href="https://example.com" class="group">
  <h2 class="group-hover:underline">Hello world!</h2>
  <p>Etiam facilisi eu dolor per leo ante…</p>
</a>

祖先要素に group をつけて、子孫要素に group-* でスタイリングすることができます。マウスホバーでよく使うと思いますが、ほかにも group-odd などほとんどの擬似クラスと組み合わせられます。

ネストされた祖先要素の状態によるスタイリング

html
<div class="group">
  <a href="https://example.com/">Hello world!</a>
  <div class="invisible group-hover:visible group/child">
    <a href="https://example.com/child/">Child</a>
    <div class="invisible group-hover/child:visible">
      <a href="https://example.com/child/grandchild/">Grandchild</a>
    </div>
  </div>
</div>

たとえば、マウスホバーしたときに下層メニューを表示するようなネストされたナビゲーションでは、group だけだと最下層のメニューまで表示されてしまいます。group/* のようにそれぞれのグループに名前をつけることでこの問題を解決できます。スタイリングしたい要素には group-hover/* のようなバリアントをつけます。

色の透明度は / で指定可能

html
<h1 class="text-black/75 bg-red-500/[0.15]">
  Hello world!
</h1>

任意値も使用可能です。

グラデーションの位置調整

html
<h1 class="bg-gradient-to-r from-indigo-500 from-10% via-purple-500 via-[31.56%] to-pink-500 to-90%">
  Hello world!
</h1>

from via to でグラデーションの位置を調整できます。任意の値を使うことも可能。

!!important

html
<h1 class="!font-normal">
  Hello world!
</h1>

! をつけることで !important にすることができます。Tailwind CSS メインのプロジェクトではほとんど使うことはないと思いますが、保守案件など途中から Tailwind CSS を導入した場合は重宝すると思います。ほかへの影響もほぼないのでわりとカジュアルに使えます。

子要素を一括指定

html
<dl class="[&>dt]:font-bold">
  <dt>Foo</dt>
  <dd>Semper cursus dictumst.</dd>
  <dt>Bar</dt>
  <dd>Dapibus rhoncus nec.</dd>
</dl>

上記は特定の子要素を指定する方法ですが、すべての子要素の場合は下記のように * を使って短く書けます。li などのスタイリングで便利です。

html
<ul class="*:border-b">
  <li>1st</li>
  <li>2nd</li>
  <li>3rd</li>
</ul>

上記は [&>*]:border-b に相当します。

子孫要素の一括指定は _ を使う

html
<ul class="[&_a]:block">
  <li><a href="http://example.com/">1st</a></li>
  <li><a href="http://example.com/">2nd</a></li>
  <li><a href="http://example.com/">3rd</a></li>
</ul>

通常の任意値同様スペースが必要な場合は _ を使います。

状態によってスタイルを変える

html
<h1 class="text-black [&.active]:text-red-500">
  Hello world!
</h1>

通常時の色は黒ですが、active というクラスが追加されたら赤になります。特定の CSS クラスが動的に付与されるケースに対応できます。

特定の要素内でスタイルを変える

html
<body class="home">
  <h1 class="text-black [body.home_&]:text-red-500">
    Hello world!
  </h1>
</body>

基本は黒ですが、home ページでだけ赤になります。

html
<body class="group home">
  <h1 class="text-black group-[.home]:text-red-500">
    Hello world!
  </h1>
</body>

v3.2 で追加されたダイナミック group-* でも書けます。

メディアクエリの max-width

html
<h2 class="sr-only lg:not-sr-only">
  Menu
</h2>

Tailwind CSS では通常メディアクエリは min-width を使ったモバイルファーストになっているので、上記のようにモバイルでは非表示にしたい場合、デスクトップでスタイルを戻す必要がありました。

html
<h2 class="max-lg:sr-only">
  Menu
</h2>

max-* バリアントを使えば元に戻すという手間が不要になります。プロパティが複数ある場合はかなりわかりやすく書けるようになります。

ダイナミックブレークポイント

html
<h1 class="text-7xl min-[1440px]:text-[5vw]">
  Hello world!
</h1>

特殊なブレークポイントのために、いちいち screens に設定を追加する必要がなくなります。

CSS ファイル内で Tailwind CSS で設定されている値を使う

css
h1 {
  font-size: min(5vw, theme(fontSize.7xl));
}

CSS ファイル内での基本的なスタイリングは @apply text-7xl; のように記述できますが、関数などで値のみを利用したい場合は theme() 関数で実現できます。theme() 関数の引数は tailwind.config.jsthemeextend のプロパティに対応しています。

任意値内で Tailwind CSS で設定されている値を使う

html
<h1 class="text-[min(5vw,theme(fontSize.7xl))]">
  Hello world!
</h1>

CSS ファイル同様、任意値内でも theme() 関数を利用することで Tailwind CSS テーマの設定値を使うことができます。

theme() 関数での色の透明度も / で指定可能

css
h1 {
  background: theme(colors.red.500 / 25%);
}
html
<h1 class="bg-[theme(colors.red.500/25%))]">
  Hello world!
</h1>

CSS ファイルでも任意値でも利用可能。

おわりに

以上の記述方法を活用すれば、特殊なケースでも CSS を個別に書いたり、tailwind.config.js をカスタマイズしたりする必要がほぼなくなります。開発速度が上がるうえ、メンテナンスコストも減るのでぜひご活用ください。

Discussion