Современная веб-разработка получила в свой арсенал множество CSS-фреймворков, большинство из которых ультимативно диктуют свои стили и правила при создании проекта. Самый популярный CSS-фреймворк Bootstrap предлагает готовую сетку и компонентные стили для большинства элементов UI, таких, как: кнопки, таблицы, табы или инпуты. Итогом является трудность кастомизации налету. Нам необходимо раз за разом переписывать стили Bootstrap, чтобы добиться нужного эффекта для каждого компонента в нашем проекте.

Tailwind предлагает совершенно новый подход к стилизации - он не создает компоненты, а использует небольшие классы-утилиты. В сравнении этих фреймворков удачным будет пример с покупкой готового брендового компьютера и самостоятельной сборки системного блока из отобранных заранее деталей.

Конечно, можно кастомизировать Bootstrap централизовано, но стилизация опять будет применяться для всех компонентов сразу. Нет никакого быстрого способа изменить стиль конкретной кнопки или элемента списка, без написания дополнительного CSS-класса. В этой ситуации нам на помощь приходит Tailwind. В стандартном варианте он включает в себя: сетку на флексбоксах и гридах, контейнеры и всевозможные утилиты, которые покрывают почти все стандартные CSS-свойства.

Например, для создания стандартной кнопки, как в Bootstrap:

<button type="button" class="btn btn-primary">Primary</button>

набор стилей может выглядеть следующим образом:

<button type="button" class="inline text-center bg-blue-500 hover:bg-blue-600 text-white rounded px-4 py-2">Primary</button>

Выглядит громоздко. Но что если Вы захотите быстро сменить отступы внутри кнопки Bootstrap? Вам придётся открыть файл стилей, создать новый класс-модификатор и записать в него новые значения. Времени этот процесс займет немало. В случае с Tailwind достаточно изменить параметры отступов прямо в HTML:

<button type="button" class="inline text-center bg-blue-500 hover:bg-blue-600 text-white rounded px-8 py-4">Primary</button>

То есть утилиты спасают нас от постоянных прыжков от HTML в CSS и обратно, позволяя писать все стили прямо наживую.

А что же делать, когда мы утвердили внешний вид нашей кнопки и она уже может использоваться повсеместно как компонент? Тут тоже нет никаких проблем. Мы просто создаём стиль нашего компонента и копируем в него все стили кнопки в специальную директиву @apply:

.button {
    @apply inline text-center bg-blue-500 hover:bg-blue-600 text-white rounded px-8 py-4;
}

Мы не будем подробно рассматривать все особенности и утилиты фреймворка Tailwind. Подробнее его можно изучить на официальном сайте, а потренироваться в написании стилей на Tailwind.run().

В нашей же статье попытаемся применить его при разработке плагина для CMS WordPress, использовав стили Tailwind в админ-панели.

Создадим простейший плагин из одного файла:

<?php
/*
 * Plugin Name: Talwindcss
 */

function admin_style_tailwindcss() {
	wp_enqueue_style('admin-style-tailwindcss', plugins_url( 'tailwindcss.css', __FILE__ ));
}
add_action('admin_enqueue_scripts', 'admin_style_tailwindcss');


function tailwindcss_admin_menu() {
	add_menu_page('Tailwindcss', 'Tailwindcss', 'edit_others_posts', 'tailwindcss', 'tailwindcss_print_page');
}
add_action('admin_menu', 'tailwindcss_admin_menu');

function tailwindcss_print_page() {
	echo '<div class="wrap tailwindcss"><h2>Tailwindcss</h2><button type="button" class="inline text-center bg-blue-500 hover:bg-blue-600 text-white rounded px-8 py-4">Primary</button></div>';
}

Здесь мы подключаем стиль из папки плагина и создаем страницу плагина в админке для демонстрации работы Tailwind.

Tailwind в готовом виде не подойдет для использования в плагинах WordPress, так как он будет конфликтовать со существующими стилями ядра. Он содержит свой сброс стилей, который мы отключим, а также классы без префиксов, которым мы добавим префикс. Сборку стиля организуем на базе Symfony Encore. Для этого из корня плагина установим необходимые пакеты:

yarn add --dev @symfony/webpack-encore tailwindcss postcss-import postcss-loader autoprefixer

Сразу добавим в packages.json раздел команд сборки в scripts:

{
  "private": true,
  "scripts": {
    "dev-server": "encore dev-server",
    "dev": "encore dev",
    "watch": "encore dev --watch",
    "build": "encore production"
  },
  "devDependencies": {
    "@symfony/webpack-encore": "^0.31.0",
    "autoprefixer": "^9.0.0",
    "postcss-import": "^12.0.0",
    "postcss-loader": "^3.0.0",
    "tailwindcss": "^1.9.6"
  }
}

Внимание! На момент написания статьи Encore для корректной работы требовал autoprefixer 9 версии, postcss-import 12 версии и postcss-loader 3 версии.

После чего инициализируем конфиг Tailwind:

npx tailwindcss init

Эта команда создаст файл tailwind.config.js, в нем сконфигурируем фреймворк. Создадим также исходный файл стилей: tailwind.css в подпапке src со следующим содержимым:

@tailwind base;

@tailwind components;

@tailwind utilities;

Создадим файл конфига PostCSS postcss.config.js:

let tailwindcss = require('tailwindcss');

module.exports = {
    plugins: [
        tailwindcss('./tailwind.config.js'), // your tailwind.js configuration file path
        require('autoprefixer'),
        require('postcss-import')
    ]
}

И конечно же создадим файл для конфига Webpack-encore webpack.config.js:

const Encore = require('@symfony/webpack-encore')
Encore
    .setOutputPath('build')
    .setPublicPath('build')
    .addStyleEntry('tailwindcss', './src/tailwindcss.css')
    // enable post css loader
    .enablePostCssLoader((options) => {
        options.config = {
            // directory where the postcss.config.js file is stored
            path: './postcss.config.js'
        };
    })
module.exports = Encore.getWebpackConfig()

Всё готово, запускаем сборку Tailwind:

yarn run dev

Переходим на страницу опций плагина и видим, что стили применились. Но сейчас эти стили применяются глобально и мы не отключили сброс стилей, встроенный в Tailwind. Изменим файл tailwind.config.js следующим образом:

module.exports = {
  important: '.tailwindcss',
  corePlugins: {
    preflight: false,
  },
  future: {
    // removeDeprecatedGapUtilities: true,
    // purgeLayersByDefault: true,
  },
  purge: [],
  theme: {
    extend: {},
  },
  variants: {},
  plugins: [],
}

Добавленная нами опция important: '.tailwindcss' добавляет всем утилитам фреймворка дополнительную вложенность, теперь все они будут задействованы только внутри элемента с классом talwindcss. Вторая опция preflight: false отключает встроенный сброс стилей.

Теперь всё в порядке и новые стили не будут конфликтовать со стилями ядра или других плагинов. Остаётся только запустить команду сборки для продакшена:

yarn run build

Полный код плагина лежит в репозитории.