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

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

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

Настройка вашей темы

Если вы хотите изменить такие вещи, как цветовую палитру, шкалу интервалов, масштаб типографики или контрольные точки, добавьте свои настройки в раздел theme файла tailwind.config.js:

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    screens: {
      sm: '480px',
      md: '768px',
      lg: '976px',
      xl: '1440px',
    },
    colors: {
      'blue': '#1fb6ff',
      'pink': '#ff49db',
      'orange': '#ff7849',
      'green': '#13ce66',
      'gray-dark': '#273444',
      'gray': '#8492a6',
      'gray-light': '#d3dce6',
    },
    fontFamily: {
      sans: ['Graphik', 'sans-serif'],
      serif: ['Merriweather', 'serif'],
    },
    extend: {
      spacing: {
        '128': '32rem',
        '144': '36rem',
      },
      borderRadius: {
        '4xl': '2rem',
      }
    }
  }
}

Дополнительные сведения о настройке темы см. В документации Конфигурация темы.


Использование произвольных значений

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

Когда вам действительно нужно что-то вроде top: 117px, чтобы получить фоновое изображение именно в нужном месте, используйте квадратную скобку Tailwind, чтобы сгенерировать класс на лету с любым произвольным значением:

<div class="top-[117px]">
  <!-- ... -->
</div>

Это в основном похоже на встроенные стили, с основным преимуществом, которое вы можете комбинировать с интерактивными модификаторами, такими как hover, и адаптивными модификаторами, такими как lg:

<div class="top-[117px] lg:top-[344px]">
  <!-- ... -->
</div>

Это работает для всего в фреймворке, включая такие вещи, как цвета фона, размеры шрифтов, содержимое псевдоэлементов и многое другое:

<div class="bg-[#bada55] text-[22px] before:content-['Festivus']">
  <!-- ... -->
</div>

Можно даже использовать функцию theme для ссылки на токены дизайна в вашем файле tailwind.config.js:

<div class="grid grid-cols-[fit-content(theme(spacing.32))]">
  <!-- ... -->
</div>

При использовании переменной CSS в качестве произвольного значения, обертывать переменную в var(...) не нужно - достаточно указать фактическое имя переменной:

<div class="bg-[--my-color]">
  <!-- ... -->
</div>

Произвольные свойства

Если вам когда-нибудь понадобится использовать свойство CSS, для которого Tailwind не входит в стандартную утилиту, вы также можете использовать обозначение квадратных скобок для написания полностью произвольного CSS:

<div class="[mask-type:luminance]">
  <!-- ... -->
</div>

Это действительно похоже на встроенные стили, но опять же с тем преимуществом, что вы можете использовать модификаторы:

<div class="[mask-type:luminance] hover:[mask-type:alpha]">
  <!-- ... -->
</div>

Это может быть полезно и для таких вещей, как переменные CSS, особенно когда их нужно изменить в разных условиях:

<div class="[--scroll-offset:56px] lg:[--scroll-offset:44px]">
  <!-- ... -->
</div>

Произвольные варианты

Произвольные варианты аналогичны произвольным значениям, но для изменения селектора на лету, как вы можете со встроенными вариантами псевдокласса, такими как hover:{utility}, или адаптивными вариантами, такими как md:{utility}, но с использованием квадрата прямо в вашем HTML.

<ul role="list">
  {#each items as item}
    <li class="lg:[&:nth-child(3)]:hover:underline">{item}</li>
  {/each}
</ul>

Узнайте больше в документации по произвольным вариантам.

Обработка пробелов

Когда произвольное значение должно содержать пробел, используйте вместо него символ подчеркивания (_), и Tailwind автоматически преобразует его в пробел во время сборки:

<div class="grid grid-cols-[1fr_500px_2fr]">
  <!-- ... -->
</div>

В ситуациях, когда подчеркивание является обычным явлением, но пробелы недопустимы, Tailwind сохранит подчеркивание вместо преобразования его в пробел, например, в URL-адресах:

<div class="bg-[url('/what_a_rush.png')]">
  <!-- ... -->
</div>

В редком случае, когда вам действительно нужно использовать подчеркивание, но это неоднозначно, потому что пробел также действителен, избегайте подчеркивания с помощью обратной косой черты, и Tailwind не преобразует его в пробел:

<div class="before:content-['hello\_world']">
  <!-- ... -->
</div>

Если вы используете что-то вроде JSX, где обратная косая черта удалена из отображаемого HTML, используйте String.raw(), поэтому обратная косая черта не рассматривается как escape-символ JavaScript:

<div className={String.raw`before:content-['hello\_world']`}>
  <!-- ... -->
</div>

Разрешение неоднозначностей

Многие утилиты в Tailwind имеют общее пространство имен, но соответствуют различным свойствам CSS. Например, text-lg и text-black имеют общее пространство имен text-, но одно для font-size, а другое для color.

При использовании произвольных значений Tailwind обычно может автоматически обрабатывать эту неоднозначность в зависимости от значения, которое вы передаете:

<!-- Сгенерирует утилиту размера шрифта -->
<div class="text-[22px]">...</div>

<!-- Сгенерирует цветовую утилиту -->
<div class="text-[#bada55]">...</div>

Иногда это действительно неоднозначно, например, при использовании переменных CSS:

<div class="text-[var(--my-var)]">...</div>

В этих ситуациях вы можете «намекнуть» на базовый тип Tailwind, добавив перед значением тип данных CSS:

<!-- Сгенерирует утилиту размера шрифта -->
<div class="text-[length:var(--my-var)]">...</div>

<!-- Сгенерирует цветовую утилиту -->
<div class="text-[color:var(--my-var)]">...</div>

Использование CSS и @layer

Когда вам нужно добавить действительно настраиваемые правила CSS в проект Tailwind, самый простой подход - просто добавить настраиваемый CSS в свою таблицу стилей:

main.css
@tailwind base;
@tailwind components;
@tailwind utilities;

.my-custom-style {
  /* ... */
}

Для большей мощности вы также можете использовать директиву @layer для добавления стилей к слоям Tailwind base, components, и utilities:

main.css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  .my-custom-style {
    /* ... */
  }
}
Почему Tailwind группирует стили в “layers”?

В CSS порядок правил в вашей таблице стилей определяет, какое объявление будет лучше, если два селектора имеют одинаковую специфичность:

.btn {
  background: blue;
  /* ... */
}

.bg-black {
  background: black;
}

Здесь обе кнопки будут черными, поскольку .bg-black стоит после .btn в CSS:

<button class="btn bg-black">...</button>
<button class="bg-black btn">...</button>

Чтобы справиться с этим, Tailwind объединяет генерируемые стили в три разных “layers” — концепция, популяризированная ITCSS.

  • base слой предназначен для таких вещей, как правила сброса или стили по умолчанию, применяемые к простым элементам HTML.
  • components слой предназначен для стилей на основе классов, которые вы хотите переопределить с помощью утилит.
  • utilities слой предназначен для небольших одноцелевых классов, которые всегда должны иметь приоритет над любыми другими стилями.

Явное указание на это упрощает понимание того, как ваши стили будут взаимодействовать друг с другом, а использование директивы @layer позволяет вам контролировать окончательный порядок объявления, сохраняя при этом организацию вашего фактического кода так, как вам нравится.

Директива @layer помогает вам контролировать порядок объявления, автоматически перемещая ваши стили в соответствующую директиву @tailwind, а также включает такие функции, как modifiers и tree-shaking для вашего собственного CSS.

Добавление базовых стилей

Если вы просто хотите установить некоторые значения по умолчанию для страницы (например, цвет текста, цвет фона или семейство шрифтов), самый простой вариант - просто добавить несколько классов к элементам html или body:

<!doctype html>
<html lang="en" class="text-gray-900 bg-gray-100 font-serif">
  <!-- ... -->
</html>

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

Если вы хотите добавить свои собственные базовые стили по умолчанию для определенных элементов HTML, используйте директиву @layer, чтобы добавить эти стили к базовому слою base Tailwind:

main.css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  h1 {
    @apply text-2xl;
  }
  h2 {
    @apply text-xl;
  }
  /* ... */
}

Используйте функцию theme или @apply при добавлении пользовательских базовых стилей, если вы хотите сослаться на к любому из значений, определенных в вашей теме.

Добавление классов компонентов

Используйте слой components для любых более сложных классов, которые вы хотите добавить в свой проект, которые вы все равно хотели бы переопределить с помощью классов утилит.

Традиционно это были классы вроде card, btn, badge — и т. д.

main.css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  .card {
    background-color: theme('colors.white');
    border-radius: theme('borderRadius.lg');
    padding: theme('spacing.6');
    box-shadow: theme('boxShadow.xl');
  }
  /* ... */
}

Определив классы компонентов на уровне components, вы по-прежнему можете использовать классы утилит для их переопределения, когда это необходимо:

<!-- Будет похоже на открытку, но с квадратными углами -->
<div class="card rounded-none">
  <!-- ... -->
</div>

Используя Tailwind, вы, вероятно, не так часто нуждаетесь в этих типах классов, как вы думаете. Прочтите наше руководство по Повторное использование стилей, чтобы получить наши рекомендации.

Слой components также является хорошим местом для размещения пользовательских стилей для любых сторонних компонентов, которые вы используете:

main.css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer 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;
  }
  /* ... */
}

Используйте функцию theme или @apply при добавлении стилей пользовательских компонентов, если вы хотите сослаться на к любому из значений, определенных в вашей теме.

Добавление пользовательских утилит

Добавьте любой из ваших собственных пользовательских служебных классов в слой utilities Tailwind:

main.css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer utilities {
  .content-auto {
    content-visibility: auto;
  }
}

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

Использование модификаторов с настраиваемым CSS

Любые пользовательские стили, которые вы добавляете в Tailwind с помощью @layer, будут автоматически поддерживать синтаксис модификатора Tailwind для обработки таких вещей, как состояния наведения, отзывчивые контрольные точки, темный режим и многое другое.

CSS
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer utilities {
  .content-auto {
    content-visibility: auto;
  }
}
HTML
<div class="lg:dark:content-auto">
  <!-- ... -->
</div>

Узнайте больше о том, как работают эти модификаторы, в документации Hover, Focus, and Other States.

Удаление неиспользуемого пользовательского CSS

Любые пользовательские стили, которые вы добавляете к слоям base, components или utilities, будут включены в ваш скомпилированный CSS только в том случае, если эти стили действительно используются в вашем HTML.

main.css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  /* Это не будет включено в ваш скомпилированный CSS, если вы его не используете */
  .card {
    /* ... */
  }
}

Если вы хотите добавить собственный CSS, который всегда должен быть включен, добавьте его в свою таблицу стилей без использования директивы @layer:

main.css
@tailwind base;
@tailwind components;

/* Это всегда будет включено в ваш скомпилированный CSS */
.card {
  /* ... */
}

@tailwind utilities;

Убедитесь, что вы разместили свои пользовательские стили там, где они должны быть, чтобы получить желаемое поведение приоритета. В приведенном выше примере мы добавили класс .card перед @tailwind utilities, чтобы убедиться, что утилиты все еще могут его переопределить.

Использование нескольких файлов CSS

Если вы пишете много CSS и организуете его в несколько файлов, убедитесь, что эти файлы объединены в одну таблицу стилей, прежде чем обрабатывать их с помощью Tailwind, иначе вы увидите ошибки при использовании @layer без соответствующей директивы @tailwind.

Самый простой способ сделать это - использовать плагин postcss-import:

postcss.config.js
module.exports = {
  plugins: {
    'postcss-import': {},
    tailwindcss: {},
    autoprefixer: {},
  }
}

Дополнительные сведения смотрите в нашей документации build-time imports.

Слои и покомпонентный CSS

Компонентные инфраструктуры, такие как Vue и Svelte, поддерживают добавление стилей для каждого компонента в блоке <style>, который находится в каждом файле компонента.

Хотя вы можете использовать такие функции, как @apply и theme внутри таких стилей компонентов, как этот, директива @layer не будет работать, и вы увидите ошибку о том, что @layer используется без соответствующей директивы @tailwind:

Не используйте @layer в стилях компонентов

Card.svelte
<div>
  <slot></slot>
</div>

<style>
  /* Не будет работать, потому что этот файл обрабатывается изолированно */
  @layer components {
    div {
      background-color: theme('colors.white');
      border-radius: theme('borderRadius.lg');
      padding: theme('spacing.6');
      box-shadow: theme('boxShadow.xl');
    }
  }
</style>

Это связано с тем, что внутренние фреймворки, такие как Vue и Svelte, обрабатывают каждый блок <style> независимо и запускают цепочку плагинов PostCSS для каждого из них изолированно.

Это означает, что если у вас есть 10 компонентов, каждый из которых имеет блок <style>, Tailwind запускается 10 отдельных раз, и каждый запуск не имеет сведений о других запусках. Из-за этого Tailwind не может взять стили, которые вы определяете в @layer, и переместить их в соответствующую директиву @tailwind, потому что, насколько Tailwind может сказать, нет директивы @tailwind, чтобы переместить его.

Одно из решений - просто не использовать @layer внутри стилей ваших компонентов:

Добавьте свои стили без использования @layer

Card.svelte
<div>
  <slot></slot>
</div>

<style>
  div {
    background-color: theme('colors.white');
    border-radius: theme('borderRadius.lg');
    padding: theme('spacing.6');
    box-shadow: theme('boxShadow.xl');
  }
</style>

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

Мы рекомендуем вам вообще не использовать такие стили компонентов, а вместо этого использовать Tailwind так, как он предназначен для использования - как единую глобальную таблицу стилей, в которой вы используете классы непосредственно в своем HTML:

Используйте утилиты Tailwind вместо стилей компонентов

Card.svelte
<div class="bg-white rounded-lg p-6 shadow-xl">
  <slot></slot>
</div>

Написание плагинов

Вы также можете добавить собственные стили в свой проект, используя систему плагинов Tailwind вместо использования файла CSS:

tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  // ...
  plugins: [
    plugin(function ({ addBase, addComponents, addUtilities, theme }) {
      addBase({
        'h1': {
          fontSize: theme('fontSize.2xl'),
        },
        'h2': {
          fontSize: theme('fontSize.xl'),
        },
      })
      addComponents({
        '.card': {
          backgroundColor: theme('colors.white'),
          borderRadius: theme('borderRadius.lg'),
          padding: theme('spacing.6'),
          boxShadow: theme('boxShadow.xl'),
        }
      })
      addUtilities({
        '.content-auto': {
          contentVisibility: 'auto',
        }
      })
    })
  ]
}

Узнайте больше о написании собственных плагинов в документации Плагины.