Настройка контента
Настройка источников контента для вашего проекта.
Раздел content вашего файла tailwind.config.js предназначен для настройки путей ко всем вашим HTML-шаблонам, JavaScript-компонентам и другим исходным файлам, содержащим классы Tailwind.
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
// ...
}Это руководство охватывает все необходимое для того, чтобы убедиться, что Tailwind генерирует весь необходимый CSS для вашего проекта.
Настройка путей к исходным файлам
Tailwind CSS работает, сканируя все ваши HTML-файлы, JavaScript-компоненты и другие шаблоны на наличие имен классов, а затем генерирует соответствующий CSS для этих стилей.
Для генерации всего необходимого CSS Tailwind должен знать о каждом файле в вашем проекте, содержащем имена классов Tailwind.
Настройте пути ко всем вашим файлам содержимого в разделе content вашего файла конфигурации:
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}'
],
// ...
}Пути настраиваются как шаблоны glob, что облегчает соответствие всем файлам содержимого в вашем проекте без большого количества настроек:
- Используйте
*для соответствия всему, кроме слэшей и скрытых файлов - Используйте
**для соответствия нулю или более каталогам - Используйте запятую для разделения значений между
{}для сопоставления с несколькими вариантами
Tailwind использует библиотеку fast-glob — ознакомьтесь с их документацией для ознакомления с другими поддерживаемыми функциями шаблонов.
Пути относительны к корню вашего проекта, а не к вашему файлу tailwind.config.js, поэтому, если ваш файл tailwind.config.js находится в нестандартном расположении, вы все равно должны указывать пути относительно корня вашего проекта.
Рекомендации по шаблонам
Для лучшей производительности и избегания ложных срабатываний, делайте шаблоны для содержимого максимально конкретными.
Если вы используете очень широкий шаблон, подобный этому, Tailwind будет сканировать даже node_modules на предмет содержимого, что, вероятно, не то, что вам нужно:
Не используйте чрезвычайно общие шаблоны
module.exports = {
content: [
'./**/*.{html,js}',
],
// ...
}Если у вас есть файлы, которые нужно сканировать, находящиеся в корне вашего проекта (часто файл index.html), укажите этот файл отдельно, чтобы другие ваши шаблоны были более конкретными:
Используйте конкретные шаблоны для содержимого
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}',
],
// ...
}
Если у вас есть JavaScript-файлы, которые изменяют ваш HTML для добавления классов, обязательно включите и их:
module.exports = {
content: [
// ...
'./src/**/*.js',
],
// ...
}// ...
menuButton.addEventListener('click', function () {
let classList = document.getElementById('nav').classList
classList.toggle('hidden')
classList.toggle('block')
})
// ...Также важно не сканировать файлы CSS — настраивайте Tailwind для сканирования ваших шаблонов, где используются ваши имена классов, а не файлов CSS, которые генерирует Tailwind.
Никогда не включайте файлы CSS в конфигурацию содержимого
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, это означает, что вы не должны использовать свойства для динамического построения классов:
Не используйте свойства для динамического построения имён классов
function Button({ color, children }) {
return (
<button className={`bg-${color}-600 hover:bg-${color}-500 ...`}>
{children}
</button>
)
} Вместо этого сопоставляйте свойства со полными именами классов, которые статически обнаруживаются на этапе сборки:
Всегда сопоставляйте свойства со статическими именами классов
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, мы рекомендуем писать эти стили без использования функции @layer Tailwind:
@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 для этих компонентов.
Если вы работаете в монорепозитории с рабочими пространствами, вам может потребоваться использовать require.resolve для того, чтобы Tailwind смог видеть ваши файлы содержимого:
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 вместо пути:
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
{ raw: '<div class="font-bold">', extension: 'html' },
],
// ...
}Практических случаев использования для этого не так много — безопасный список обычно является тем, что вам на самом деле нужно.
Безопасный список классов
Для наименьшего размера файла и лучшего опыта разработки мы настоятельно рекомендуем использовать вашу конфигурацию content для указания Tailwind, какие классы необходимо сгенерировать.
Безопасный список — это крайний случай и должен использоваться только в ситуациях, когда невозможно просканировать определенное содержимое на наличие имен классов. Такие ситуации редки, и вам почти никогда не понадобится эта функция.
Если вам нужно убедиться, что Tailwind генерирует определенные имена классов, которые не существуют в ваших файлах содержимого, используйте параметр safelist:
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
safelist: [
'bg-red-500',
'text-3xl',
'lg:text-4xl',
]
// ...
}Один пример, где это может быть полезно, — если ваш сайт отображает пользовательское содержимое, и вы хотите, чтобы пользователи могли использовать ограниченный набор классов Tailwind в своём содержимом, которые могут отсутствовать в исходных файлах вашего сайта.
Использование регулярных выражений
Tailwind поддерживает безопасную подстановку на основе шаблонов в ситуациях, когда вам нужно подставить много классов:
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:
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.
В этих ситуациях вы можете использовать опцию blocklist, чтобы указать Tailwind игнорировать определённые классы, которые он обнаруживает в вашем контенте:
module.exports = {
content: [
'./pages/**/*.{html,js}',
'./components/**/*.{html,js}',
],
blocklist: [
'container',
'collapse',
],
// ...
}Опция blocklist влияет только на CSS, который будет сгенерирован Tailwind, а не на настраиваемый CSS, который вы написали самостоятельно или импортировали из другой библиотеки.
В отличие от safelist, опция blocklist поддерживает только строки и вы не можете блокировать классы с помощью регулярных выражений.
Преобразование исходных файлов
Если вы создаёте контент в формате, который компилируется в HTML (например, Markdown), часто имеет смысл скомпилировать этот контент в HTML перед сканированием его на наличие имён классов.
Используйте опцию content.transform для преобразования любого контента, соответствующего определённому расширению файла, перед извлечением классов:
const remark = require('remark')
module.exports = {
content: {
files: ['./src/**/*.{html,md}'],
transform: {
md: (content) => {
return remark().process(content)
}
}
},
// ...
}При использовании content.transform, вам нужно предоставить пути к исходникам с использованием content.files, а не как массив верхнего уровня в content.
Настройка логики извлечения
Используйте опцию extract для переопределения логики, которую Tailwind использует для обнаружения имён классов для определённых расширений файлов:
module.exports = {
content: {
files: ['./src/**/*.{html,wtf}'],
extract: {
wtf: (content) => {
return content.match(/[^<>"'`\s]*/)
}
}
},
// ...
}Это расширенная функция, и большинству пользователей она не потребуется — стандартная логика извлечения в Tailwind работает очень хорошо практически для всех проектов.
Как и при преобразовании, при использовании content.extract, вам нужно предоставить пути к исходникам с использованием content.files вместо массива верхнего уровня в content.
Отладка
Классы не генерируются
Если Tailwind не генерирует классы, убедитесь, что ваша конфигурация content правильная и соответствует всем нужным исходным файлам.
Распространённая ошибка — пропущенное расширение файла, например, если вы используете jsx вместо js для ваших компонентов React:
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, кажется, перестраивается в бесконечном цикле, есть большая вероятность, что это происходит потому, что ваша среда разработки не поддерживает опцию glob при регистрации зависимостей PostCSS.
Многие среды разработки (например, webpack) не поддерживают эту опцию, и в результате мы можем только сказать им следить за определёнными файлами или целыми каталогами. Мы не можем сказать webpack, например, только отслеживать файлы *.html в каталоге.
Это означает, что если сборка вашего CSS вызывает любые изменения в этих каталогах, перестроение будет выполнено, даже если изменённый файл не соответствует расширению в вашем глобальном шаблоне.
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, у вас возникнет бесконечный цикл перестроения при использовании некоторых сред разработки.
В идеале, мы могли бы предупредить вас об этом в консоли, но многие среды разработки поддерживают это без проблем (включая наш собственный инструмент командной строки), и у нас нет надёжного способа определить, какую среду разработки вы используете.
Для решения этой проблемы используйте более конкретные пути в вашей конфигурации content , убедившись, что вы включаете только каталоги, которые не будут изменяться при сборке CSS:
module.exports = {
content: [
'./src/**/*.{html,js}',
'./src/pages/**/*.{html,js}',
'./src/components/**/*.{html,js}',
'./src/layouts/**/*.{html,js}',
'./src/index.html',
],
// ...
}
При необходимости скорректируйте фактическую структуру каталогов проекта, чтобы убедиться, что вы можете нацеливаться на файлы шаблонов, не захватывая случайно ваш файл CSS или другие артефакты сборки, такие как файлы манифеста.
Если вы абсолютно не можете изменить вашу конфигурацию содержимого или структуру каталогов, ваш лучший вариант — скомпилировать CSS отдельно с помощью инструмента, который полностью поддерживает глобальные шаблоны. Мы рекомендуем использовать Tailwind CLI, который является быстрым, простым и специализированным инструментом для компиляции вашего CSS с Tailwind.
Всё просто не работает должным образом
Если у вас возникают странные, трудноописуемые проблемы с выводом или что-то просто не работает должным образом, есть большая вероятность, что это связано с тем, что ваша среда разработки не правильно поддерживает сообщения о зависимостях PostCSS (или вообще не поддерживает). Один известный пример этого в настоящее время — Stencil.
При возникновении таких проблем мы рекомендуем использовать Tailwind CLI для отдельной компиляции CSS вместо попытки интегрировать Tailwind в вашу существующую среду разработки.
Вы можете использовать пакеты, такие как 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",
},
} В любом случае, обязательно проверьте существующие проблемы или откройте новую, чтобы мы могли выяснить проблему и попытаться улучшить совместимость с используемым вами инструментом.
© 2022 Tailwind Labs Inc.
https://tailwindcss.com/docs/content-configuration