カスタマイズ
プロジェクトのコンテンツソースを設定します。
tailwind.config.js
ファイルのcontent
セクションでは、HTMLテンプレート、JavaScriptコンポーネント、およびTailwindクラス名を含むその他のすべてのソースファイルのパスを設定します。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
// ...
}
このガイドでは、プロジェクトに必要なすべてのCSSをTailwindが生成できるようにするために知っておくべきすべての事項を説明します。
Tailwind CSSは、すべてのHTML、JavaScriptコンポーネント、およびその他のテンプレートファイルをクラス名でスキャンし、それらのスタイルに対応するすべてのCSSを生成することによって機能します。
Tailwindがあなたに必要なすべてのCSSを生成するためには、あなたのプロジェクト内のTailwindクラス名を含むすべての単一のファイルを知る必要があります。
設定ファイルのcontent
セクションですべてのコンテンツファイルのパスを設定します。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}'
],
// ...
}
パスはglobパターンとして構成されているため、大量の設定なしにプロジェクト内のすべてのコンテンツファイルに簡単に一致させることができます。
*
を使用します。**
を使用します。{}
の間にコンマ区切りの値を使用して、オプションのリストと一致させます。Tailwindは、内部でfast-globライブラリを使用しています。サポートされているその他のパターン機能については、ドキュメントを確認してください。
パスは、tailwind.config.js
ファイルではなく、プロジェクトのルートからの相対パスです。したがって、tailwind.config.js
ファイルがカスタムの場所にある場合は、プロジェクトのルートを基準にしてパスを記述する必要があります。
最高のパフォーマンスを実現し、誤検出を回避するには、コンテンツ構成をできるだけ具体的にしてください。
このような非常に広範なパターンを使用すると、Tailwindはnode_modules
のコンテンツもスキャンします。これはおそらく望ましいものではありません。
非常に広範なパターンを使用しないでください。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./**/*.{html,js}',
],
// ...
}
プロジェクトのルートにあるスキャンする必要のあるファイル(多くの場合、index.html
ファイル)がある場合は、他のパターンをより具体的にするために、そのファイルを個別にリストします。
コンテンツパターンを具体的にします。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./components/**/*.{html,js}',
'./pages/**/*.{html,js}',
'./index.html',
],
// ...
}
一部のフレームワークでは、メインのHTMLエントリポイントが残りのテンプレートとは異なる場所(多くの場合public/index.html
)に隠されているため、そのファイルにTailwindクラスを追加する場合は、構成に含めるようにしてください。
該当する場合は、HTMLエントリポイントを含めることを忘れないでください。
module.exports = {
content: [
'./public/index.html',
'./src/**/*.{html,js}',
],
// ...
}
HTMLを操作してクラスを追加するJavaScriptファイルがある場合は、それらも必ず含めてください。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
// ...
'./src/**/*.js',
],
// ...
}
// ...
menuButton.addEventListener('click', function () {
let classList = document.getElementById('nav').classList
classList.toggle('hidden')
classList.toggle('block')
})
// ...
また、CSSファイルをスキャンしないことも重要です。Tailwindを構成して、クラス名が使用されているテンプレートをスキャンし、Tailwindが生成しているCSSファイルをスキャンしないでください。
コンテンツ構成にCSSファイルを含めないでください。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./src/**/*.css',
],
// ...
}
Tailwindがソースコードをクラス名でスキャンする方法は、意図的に非常に単純です。実際に記述されている言語でコードを解析または実行するのではなく、正規表現を使用して、クラス名である可能性のあるすべての文字列を抽出します。
たとえば、すべての潜在的なクラス名文字列が個別に強調表示されたHTMLを次に示します。
<div class="md:flex">
<div class="md:flex-shrink-0">
<img class="rounded-lg md:w-56" src="/img/shopping.jpg" alt="Woman paying for a purchase">
</div>
<div class="mt-4 md:mt-0 md:ml-6">
<div class="uppercase tracking-wide text-sm text-indigo-600 font-bold">
Marketing
</div>
<a href="/get-started" class="block mt-1 text-lg leading-tight font-semibold text-gray-900 hover:underline">
Finding customers for your new business
</a>
<p class="mt-2 text-gray-600">
Getting a new business off the ground is a lot of hard work.
Here are five ideas you can use to find your first customers.
</p>
</div>
</div>
class="..."
属性への検索を制限するだけではありません。たとえば、メニューを切り替えるためのJavaScriptなど、クラスをどこでも使用できるからです。
<script>
menuButton.addEventListener('click', function () {
let classList = document.getElementById('nav').classList
classList.toggle('hidden')
classList.toggle('block')
})
</script>
この非常にシンプルなアプローチを使用することにより、TailwindはJSXなどのプログラミング言語と非常に信頼性の高い方法で連携します。
const sizes = {
md: 'px-4 py-2 rounded-md text-base',
lg: 'px-5 py-3 rounded-lg text-lg',
}
const colors = {
indigo: 'bg-indigo-500 hover:bg-indigo-600 text-white',
cyan: 'bg-cyan-600 hover:bg-cyan-700 text-white',
}
export default function Button({ color, size, children }) {
let colorClasses = colors[color]
let sizeClasses = sizes[size]
return (
<button type="button" className={`font-bold ${sizeClasses} ${colorClasses}`}>
{children}
</button>
)
}
Tailwindがクラス名を抽出する方法の最も重要な意味は、ソースファイルに完全な途切れていない文字列として存在するクラスのみを見つけるということです。
文字列補間を使用したり、部分的なクラス名を連結したりすると、Tailwindはそれらを見つけないため、対応するCSSは生成されません。
クラス名を動的に構築しないでください。
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
上記の例では、文字列text-red-600
およびtext-green-600
は存在しないため、Tailwindはこれらのクラスを生成しません。
代わりに、使用しているクラス名が完全に存在することを確認してください。
常に完全なクラス名を使用してください。
<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
ReactやVueのようなコンポーネントライブラリを使用している場合、これはpropsを使用してクラスを動的に構築すべきではないことを意味します。
propsを使用してクラス名を動的に構築しないでください。
function Button({ color, children }) {
return (
<button className={`bg-${color}-600 hover:bg-${color}-500 ...`}>
{children}
</button>
)
}
代わりに、ビルド時に静的に検出可能な完全なクラス名にpropsをマップします。
常にpropsを静的なクラス名にマップします。
function Button({ color, children }) {
const colorVariants = {
blue: 'bg-blue-600 hover:bg-blue-500',
red: 'bg-red-600 hover:bg-red-500',
}
return (
<button className={`${colorVariants[color]} ...`}>
{children}
</button>
)
}
これにより、たとえば、さまざまなプロップ値をさまざまな色合いにマッピングできるという追加の利点があります。
function Button({ color, children }) {
const colorVariants = {
blue: 'bg-blue-600 hover:bg-blue-500 text-white',
red: 'bg-red-500 hover:bg-red-400 text-white',
yellow: 'bg-yellow-300 hover:bg-yellow-400 text-black',
}
return (
<button className={`${colorVariants[color]} ...`}>
{children}
</button>
)
}
コード内で常に完全なクラス名を使用している限り、Tailwindは常に完璧にすべてのCSSを生成します。
もしあなたが、(例えばSelect2のような)サードパーティのライブラリを使っていて、そのライブラリを独自のカスタムCSSでスタイリングしている場合、Tailwindの@layer
機能を使わずにそれらのスタイルを書くことをお勧めします。
@tailwind base;
@tailwind components;
.select2-dropdown {
@apply rounded-b-lg shadow-md;
}
.select2-search {
@apply border border-gray-300 rounded;
}
.select2-results__group {
@apply text-lg font-bold text-gray-900;
}
/* ... */
@tailwind utilities;
これにより、Tailwindはそれらのスタイルを常にCSSに含めるようになり、サードパーティライブラリのソースコードをスキャンするようにTailwindを設定するよりもずっと簡単になります。
もしあなたがTailwindでスタイリングされた再利用可能なコンポーネントのセットを作成し、それらを複数のプロジェクトでインポートしている場合、Tailwindがそれらのコンポーネントのクラス名をスキャンするように設定してください。
module.exports = {
content: [
'./components/**/*.{html,js}',
'./pages/**/*.{html,js}',
'./node_modules/@my-company/tailwind-components/**/*.js',
],
// ...
}
これにより、Tailwindがそれらのコンポーネントに必要なすべてのCSSを生成するようになります。
もしあなたがワークスペースを持つモノレポで作業している場合、Tailwindがコンテンツファイルを見つけられるように、require.resolve
を使用する必要があるかもしれません。
const path = require('path');
module.exports = {
content: [
'./components/**/*.{html,js}',
'./pages/**/*.{html,js}',
path.join(path.dirname(require.resolve('@my-company/tailwind-components')), '**/*.js'),
],
// ...
}
デフォルトでは、Tailwindは非絶対コンテンツパスを、tailwind.config.js
ファイルではなく、現在の作業ディレクトリからの相対パスとして解決します。これは、異なるディレクトリからTailwindを実行した場合、予期しない結果につながる可能性があります。
常にtailwind.config.js
ファイルからの相対パスとして解決するには、content
設定にオブジェクト記法を使用し、relative
プロパティをtrue
に設定してください。
module.exports = {
content: {
relative: true,
files: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
},
// ...
}
これは、フレームワークの次のメジャーバージョンでデフォルトの動作になる可能性があります。
何らかの理由で、Tailwindにファイルのコンテンツではなく、生のコンテンツをスキャンするように設定する必要がある場合は、パスの代わりにraw
キーを持つオブジェクトを使用してください。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
{ raw: '<div class="font-bold">', extension: 'html' },
],
// ...
}
これには有効なユースケースはあまりありません。通常はセーフリスティングが本当に必要なものです。
ファイルサイズを最小限に抑え、開発体験を向上させるために、Tailwindにどのクラスを生成するかを指示するために、できる限りcontent
設定に依存することを強くお勧めします。
セーフリスティングは最後の手段であり、特定のコンテンツのクラス名をスキャンすることが不可能な場合にのみ使用する必要があります。このような状況はまれであり、この機能がほとんど必要になることはありません。
コンテンツファイルに存在しない特定のクラス名をTailwindに生成させたい場合は、safelist
オプションを使用してください。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
'bg-red-500',
'text-3xl',
'lg:text-4xl',
]
// ...
}
この機能が役立つ例の1つは、サイトでユーザーが生成したコンテンツを表示する場合で、ユーザーが自分のサイトのソースファイルに存在しない可能性のあるTailwindクラスの制約されたセットをコンテンツで使用できるようにしたい場合です。
Tailwindは、多くのクラスをセーフリストする必要がある状況に対応するために、パターンベースのセーフリスティングをサポートしています。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
'text-2xl',
'text-3xl',
{
pattern: /bg-(red|green|blue)-(100|200|300)/,
},
],
// ...
}
パターンは、/bg-red-.+/
のようなベースユーティリティ名に対してのみ一致し、/hover:bg-red-.+/
のようにバリアント修飾子が含まれている場合は一致しません。
一致したクラスのバリアントを強制的にTailwindに生成させたい場合は、variants
オプションを使用して含めてください。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
'text-2xl',
'text-3xl',
{
pattern: /bg-(red|green|blue)-(100|200|300)/,
variants: ['lg', 'hover', 'focus', 'lg:hover'],
},
],
// ...
}
Tailwindはコンテンツ内のクラス名を検出するために非常に単純なアプローチを使用しているため、実際には必要のないクラスが生成されていることに気づくかもしれません。
たとえば、このHTMLは、container
クラスが実際には使用されていなくても、生成されます。
<div class="text-lg leading-8 text-gray-600">
Every custom pool we design starts as a used shipping container, and is
retrofitted with state of the art technology and finishes to turn it into
a beautiful and functional way to entertain your guests all summer long.
</div>
また、Tailwindのクラスが既存のCSSと競合する場合に、Tailwindクラスにすべてプレフィックスを付けるほどではない場合に、特定のクラスがTailwindによって生成されないようにすることもできます。
このような状況では、blocklist
オプションを使用して、コンテンツ内で検出された特定のクラスをTailwindに無視するように指示できます。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
blocklist: [
'container',
'collapse',
],
// ...
}
blocklist
オプションは、Tailwindによって生成されるCSSにのみ影響し、自分で作成したカスタムCSSや別のライブラリからインポートしたCSSには影響しません。
safelist
とは異なり、blocklist
オプションは文字列のみをサポートしており、正規表現を使用してクラスをブロックすることはできません。
(Markdownのように)HTMLにコンパイルされる形式でコンテンツを作成している場合は、クラス名をスキャンする前に、そのコンテンツをHTMLにコンパイルするのが理にかなっていることがよくあります。
特定のファイル拡張子に一致するコンテンツを変換してからクラスを抽出するには、content.transform
オプションを使用します。
const remark = require('remark')
module.exports = {
content: {
files: ['./src/**/*.{html,md}'],
transform: {
md: (content) => {
return remark().process(content)
}
}
},
// ...
}
content.transform
を使用する場合は、content
の下のトップレベルの配列としてではなく、content.files
を使用してソースパスを提供する必要があります。
特定のファイル拡張子に対するクラス名の検出にTailwindが使用するロジックをオーバーライドするには、extract
オプションを使用します。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: {
files: ['./src/**/*.{html,wtf}'],
extract: {
wtf: (content) => {
return content.match(/[^<>"'`\s]*/g)
}
}
},
// ...
}
これは高度な機能であり、ほとんどのユーザーは必要ありません。Tailwindのデフォルトの抽出ロジックは、ほとんどすべてのプロジェクトで非常にうまく機能します。
変換と同様に、content.extract
を使用する場合は、content
の下のトップレベルの配列としてではなく、content.files
を使用してソースパスを提供する必要があります。
Tailwindがクラスを生成しない場合は、content
設定が正しく、すべての適切なソースファイルと一致していることを確認してください。
よくある間違いは、Reactコンポーネントにjs
の代わりにjsx
を使用している場合など、ファイル拡張子が欠落していることです。
module.exports = {
content: [
'./src/**/*.{html,js}',
'./src/**/*.{html,js,jsx}'
],
// ...
}
または、プロジェクトの途中で、元々カバーされていなかった新しいフォルダを作成し、それを設定に追加するのを忘れていることです。
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
'./util/**/*.{html,js}'
],
// ...
}
また、動的なクラス名を使用しようとしている可能性もあります。Tailwindは実際にソースコードを評価せず、静的な切れ目のないクラス文字列のみを検出できるため、動的なクラス名は機能しません。
クラス名を動的に構築しないでください。
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
常にコードで完全なクラス名を使用するようにしてください。
常に完全なクラス名を使用してください。
<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
詳細については、動的なクラス名に関するドキュメントをお読みください。
CSSが無限ループで再構築されているように見える場合、それは、ビルドツールが、PostCSSの依存関係を登録するときにglob
オプションをサポートしていない可能性が高いです。
多くのビルドツール(webpackなど)はこのオプションをサポートしておらず、その結果、特定のファイルまたはディレクトリ全体を監視するように指示することしかできません。たとえば、ディレクトリ内の*.html
ファイルのみを監視するようにwebpackに指示することはできません。
つまり、CSSをビルドすることで、これらのディレクトリ内のいずれかのファイルが変更された場合、変更されたファイルがglobの拡張子と一致しない場合でも、再ビルドがトリガーされます。
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
// With some build tools, your CSS will rebuild
// any time *any* file in `src` changes.
'./src/**/*.{html,js}',
],
// ...
}
したがって、src/**/*.html
の変更を監視しているが、CSS出力ファイルをsrc/css/styles.css
に書き込んでいる場合、一部のツールでは無限の再ビルドループが発生します。
理想的には、コンソールでこれについて警告できますが、多くのツールは(独自のCLIツールを含め)完全に正常にサポートしており、使用しているビルドツールを確実に検出する方法はありません。
この問題を解決するには、content
設定でより具体的なパスを使用し、CSSのビルド時に変更されないディレクトリのみを含めるようにしてください。
module.exports = {
content: [
'./src/**/*.{html,js}',
'./src/pages/**/*.{html,js}',
'./src/components/**/*.{html,js}',
'./src/layouts/**/*.{html,js}',
'./src/index.html',
],
// ...
}
必要に応じて、実際のプロジェクトディレクトリ構造を調整して、CSSファイルやマニフェストファイルなどの他のビルド成果物を誤ってキャッチすることなく、テンプレートファイルをターゲットにできるようにしてください。
どうしてもコンテンツ設定やディレクトリ構造を変更できない場合は、globサポートが完全なツールでCSSを個別にコンパイルするのが最善の方法です。TailwindでCSSをコンパイルするための高速でシンプルな専用ツールであるTailwind CLIを使用することをお勧めします。
もし出力に奇妙で説明しにくい問題が発生した場合や、全く動作していないように見える場合は、ビルドツールがPostCSSの依存関係メッセージを正しくサポートしていない(または全くサポートしていない)可能性が高いです。現在、既知の例としてStencilがあります。
これらの種類の問題が発生した場合は、既存のツールにTailwindを統合しようとするのではなく、Tailwind CLIを使用してCSSを個別にコンパイルすることをお勧めします。
npm-run-all
やconcurrently
のようなパッケージを使用して、以下のようにプロジェクトにスクリプトを追加することで、通常の開発コマンドと並行してCSSをコンパイルできます。
// package.json
{
// ...
"scripts": {
"start": "concurrently \"npm run start:css\" \"react-scripts start\"",
"start:css": "tailwindcss -o src/tailwind.css --watch",
"build": "npm run build:css && react-scripts build",
"build:css": "NODE_ENV=production tailwindcss -o src/tailwind.css -m",
},
}
いずれにしても、既存の問題がないか確認するか、新しい問題を開いて、問題を把握し、使用しているツールとの互換性を改善できるようにしてください。