🎉

【Tailwind和訳】GETTING STARTED/Using with Preprocessors

2021/10/23に公開約9,100字

この記事について

この記事は、GETTING STARTED/Using with Preprocessorsの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

プリプロセッサとの併用

Sass、Less、Stylus などの一般的な CSS プリプロセッサと Tailwind を併用するためのガイドです。


Tailwind は PostCSS プラグインなので、Autoprefixerのような他の PostCSS プラグインと同様に、Sass、Less、Stylus などのプリプロセッサを使用することを妨げるものは何もありません。

Tailwind では、プリプロセッサを使用する必要はありません。Tailwind のプロジェクトでは、一般的に CSS をほとんど書かないので、プリプロセッサを使用しても、カスタム CSS をたくさん書くプロジェクトの場合ほどのメリットはありません。

このガイドは、何らかの理由で Tailwind とプリプロセッサを統合する必要がある、あるいは統合したいと考えている人のための参考資料として存在しています。


プリプロセッサとしての PostCSS の使用

Tailwind を全く新しいプロジェクトに使用し、既存の Sass/Less/Stylus のスタイルシートと統合する必要がない場合は、個別のプリプロセッサを使用する代わりに、使用するプリプロセッサの機能を追加するために、他の PostCSS プラグインに頼ることを大いに検討すべきです。

これにはいくつかの利点があります。

  • ビルドが速くなります。複数のツールで CSS を解析・処理する必要がないので、PostCSS だけで CSS のコンパイルがより速くなります。
  • クセや回避策がない。Tailwind は、CSS にいくつかの新しい非標準的なキーワード(@tailwind@applytheme()など)を追加するため、プリプロセッサに期待通りの出力をさせるために、煩わしくて難解な方法で CSS を書かなければならないことがよくあります。PostCSS だけで作業すると、このようなことはありません。

利用可能な PostCSS プラグインのかなり包括的なリストについては、PostCSS の GitHub リポジトリを参照してくださいが、ここでは私たちが自分のプロジェクトで使用し、推奨できるいくつかの重要なプラグインを紹介します。

ビルド時のインポート

プリプロセッサが提供する最も便利な機能の一つは、CSS を複数のファイルに整理し、ブラウザではなく事前に@import文を処理することで、ビルド時にそれらを結合する機能です。

PostCSS でこれを処理するための標準的なプラグインがpostcss-importです。

これを使うには、npm 経由でプラグインをインストールします。

Terminal
npm install postcss-import

そして、PostCSS の設定の一番最初のプラグインとして追加します。

// postcss.config.js
module.exports = {
  plugins: [require("postcss-import"), require("tailwindcss"), require("autoprefixer")],
}

postcss-importの重要な点は、CSS の仕様に厳密に準拠しており、ファイルの最上部以外では@import文を禁止していることです。

@import文が最初になければ、動作しません。

/* components.css */

.btn {
  @apply px-4 py-2 rounded font-semibold bg-gray-200 text-black;
}

/* Will not work */
@import "./components/card";

この問題を解決する最も簡単な方法は、通常の CSS とインポートを同じファイルに混在させないことです。その代わりに、インポート用のメインエントリーポイントファイルを 1 つ作り、実際の CSS はすべて別のファイルにします。

✅ インポート用と実際の CSS を別々のファイルにする

/* components.css */
@import "./components/buttons.css";
@import "./components/card.css";
/* components/buttons.css */
.btn {
  @apply px-4 py-2 rounded font-semibold bg-gray-200 text-black;
}
/* components/card.css */
.card {
  @apply p-4 bg-white shadow rounded;
}

このような状況に陥る可能性が高いのは、@tailwind宣言を含むメインの CSS ファイルです。

@import文が最初になければ、動作しません。

@tailwind base;
@import "./custom-base-styles.css";

@tailwind components;
@import "./custom-components.css";

@tailwind utilities;
@import "./custom-utilities.css";

これを解決するには、@tailwind宣言ごとに個別のファイルを作成し、それらのファイルをメインのスタイルシートでインポートすればよいのです。これを簡単にするために、私たちは@tailwind宣言ごとに個別のファイルを用意し、node_modulesから直接インポートできるようにしています。

postcss-importプラグインは、node_modulesフォルダ内のファイルを自動的に探すようになっているので、パス全体を指定する必要はありません - 例えば、"tailwindcss/base “で十分です。

✅ 用意した CSS ファイルを読み込む

@import "tailwindcss/base";
@import "./custom-base-styles.css";

@import "tailwindcss/components";
@import "./custom-components.css";

@import "tailwindcss/utilities";
@import "./custom-utilities.css";

ネスティング

ネストした宣言のサポートを追加するには、バンドルされているtailwindcss/nestingプラグインをお勧めします。これは、postcss-nestedまたはpostcss-nestingをラップする PostCSS プラグインで、@apply@screenのような Tailwind のカスタムシンタックスを、お使いのネスティングプラグインが正しく理解できるようにするための互換性レイヤーとして機能します。

tailwindcssパッケージに直接含まれていますので、使用するためには、Tailwind の前のどこかで、PostCSS の設定に追加するだけです。

// postcss.config.js
module.exports = {
  plugins: [
    require("postcss-import"),
    require("tailwindcss/nesting"),
    require("tailwindcss"),
    require("autoprefixer"),
  ],
}

デフォルトでは、ボンネット内でpostcss-nestedプラグインを使用しています。これは Sass のような構文を使用しており、Tailwind CSS プラグイン APIのネスティングサポートを強化するプラグインです。

postcss-nesting(作業中のCSS Nesting仕様に基づいています)を使用したい場合は、まずプラグインをインストールしてください。

Terminal
npm install postcss-nesting

そして、プラグイン自体を PostCSS の設定でtailwindcss/nestingの引数として渡します。

// postcss.config.js
module.exports = {
  plugins: [
    require("postcss-import"),
    require("tailwindcss/nesting")(require("postcss-nesting")),
    require("tailwindcss"),
    require("autoprefixer"),
  ],
}

これは、何らかの理由で非常に特殊なバージョンのpostcss-nestedを使用する必要があり、tailwindcss/nestingにバンドルされているバージョンを上書きしたい場合にも役立ちます。

なお、プロジェクトでpostcss-preset-envを使用している場合は、ネスティングを無効にしてtailwindcss/nestingに処理させるようにしてください。

// postcss.config.js
module.exports = {
  plugins: [
    require("postcss-import"),
    require("tailwindcss/nesting")(require("postcss-nesting")),
    require("tailwindcss"),
    require("postcss-preset-env")({
      features: { "nesting-rules": false },
    }),
  ],
}

変数について

最近の CSS 変数(正式にはカスタムプロパティ)は、ブラウザのサポートが充実しているので、変数を使うのにプリプロセッサは必要ありません。

:root {
  --theme-color: #52b3d0;
}

/* ... */

.btn {
  background-color: var(--theme-color);
  /* ... */
}

Tailwind では CSS 変数を多用していますので、Tailwind が使えれば、ネイティブな CSS 変数を使うことができます。

また、今まで変数を使っていたものも、Tailwind のtheme()関数を使えば、tailwind.config.jsからデザイントークンに直接アクセスできるようになるので、CSS で置き換えられるかもしれません。

.btn {
  background-color: theme("colors.blue.500");
  padding: theme("spacing.2") theme("spacing.4");
  /* ... */
}

theme()関数の詳細については、 functions and directives documentation をご覧ください。

ベンダープレフィックス

ベンダープレフィックスを CSS で自動的に管理するには、Autoprefixerを使用する必要があります。

使用するには、npm でインストールします。

Terminal
npm install autoprefixer

そして、PostCSS の設定で、プラグインリストの一番最後に追加します。

module.exports = {
  plugins: [require("tailwindcss"), require("autoprefixer")],
}

Sass、Less、Stylus の使用

Tailwind を Sass、Less、Stylus などの前処理ツールと一緒に使うには、プロジェクトにビルドステップを追加して、前処理した CSS を PostCSS で実行する必要があります。プロジェクトで Autoprefixer を使用している場合は、すでにこのような設定がされています。

具体的な手順は、お使いのビルドツールによって異なりますので、既存のビルドプロセスに Tailwind を組み込む方法については、インストールドキュメントをご覧ください。

プリプロセッサと Tailwind を併用する上で最も重要なことは、Sass、Less、Stylus などのプリプロセッサは、Tailwind の前に別々に実行されるということです。これは、Sass が CSS にコンパイルされ、PostCSS に投入されるまで、theme()関数は実際には評価されないため、例えば、Tailwind のtheme()関数から Sass の color 関数に出力を与えることはできません。

❌ Sass が最初に処理されるため、動作しません。

.alert {
  background-color: darken(theme("colors.red.500"), 10%);
}

最も一貫した開発を行うためには、PostCSS のみを使用することをお勧めします。

それ以外にも、それぞれのプリプロセッサには、Tailwind で使用した場合に独自の癖があり、それを回避する方法を以下にまとめました。

Sass

Tailwind を Sass と一緒に使う場合、@applyと一緒に !important を使うと、正しくコンパイルするために補間が必要になります。

❌ 動作しません。Sass は!important について文句を言います。

.alert {
  @apply bg-red-500 !important;
}

✅ ワークアラウンドとして補間を使用

.alert {
  @apply bg-red-500 #{!important};
}

Less

Tailwind を Less で使用する場合、Tailwind の@screenディレクティブをネストすることはできません。

❌ Less がメディアクエリであることを認識しないため、動作しません。

.card {
  @apply rounded-none;

  @screen sm {
    @apply rounded-lg;
  }
}

代わりに、通常のメディアクエリとtheme()関数を使ってスクリーンサイズを参照するか、単に@screenディレクティブをネストさせないようにします。

✅ 通常のメディアクエリと theme()の使用

.card {
  @apply rounded-none;

  @media (min-width: theme("screens.sm")) {
    @apply rounded-lg;
  }
}

✅ トップレベルの@screen ディレクティブを使用して

.card {
  @apply rounded-none;
}
@screen sm {
  .card {
    @apply rounded-lg;
  }
}

スタイラス

Tailwind を Stylus で使用する場合、Tailwind の@apply機能を使用するには、CSS ルール全体を@cssで囲み、Stylus がリテラル CSS として扱うようにしなければなりません。

❌ 動作しない、Stylus が@apply について文句を言う

.card {
  @apply rounded-lg bg-white p-4;
}

✅ Stylus での処理を避けるために@css を使用する

@css {
  .card {
    @apply rounded-lg bg-white p-4;
  }
}

しかし、これには大きな代償が伴い、@css ブロック内では Stylus の機能を使用することができません

もう一つの方法は、@apply の代わりに theme() 関数を使用して、実際の CSS プロパティを長い形式で記述することです。

✅ @apply の代わりに theme() を使用

.card {
  border-radius: theme("borderRadius.lg");
  background-color: theme("colors.white");
  padding: theme("spacing.4");
}

これに加えて、Stylus は @screen ディレクティブの入れ子をサポートしていません(Less と同様)。

❌ スタイラスはメディアクエリであることを認識していないため、動作しません。

.card {
  border-radius: 0;

  .card { border-radius: 0; @screen sm {
    border-radius: theme('borderRadius.lg');
  }
}

代わりに、通常のメディアクエリと theme() 関数を使ってスクリーンサイズを参照するか、@screen ディレクティブをネストさせないようにします。

✅ 通常のメディアクエリと theme() の使用

.card {
  border-radius: 0;

  .card { border-radius: 0; @media (min-width: theme('s screens.sm')) {border-radius: theme('borderRadius.lg');
  }
}

✅ トップレベルでの@screen ディレクティブの使用

.card {
  border-radius: 0;
}
@screen sm {
  .card {
    border-radius: theme("borderRadius.lg");
  }
}

Discussion

ログインするとコメントできます