Работа с дублированием и поддержание ремонтопригодности проектов, ориентированных на полезность.
Tailwind поощряет рабочий процесс utility-first, когда проекты изначально реализуются с использованием только служебных классов, чтобы избежать преждевременной абстракции.
Начало нового бизнеса - это тяжелая работа. Вот пять идей, которые вы можете использовать, чтобы найти своих первых клиентов.
<div class="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl">
<div class="md:flex">
<div class="md:flex-shrink-0">
<img class="h-48 w-full object-cover md:w-48" src="/img/store.jpg" alt="Человек смотрит на товар в магазине">
</div>
<div class="p-8">
<div class="uppercase tracking-wide text-sm text-indigo-500 font-semibold">Пример использования</div>
<a href="#" class="block mt-1 text-lg leading-tight font-medium text-black hover:underline">Поиск клиентов для вашего нового бизнеса</a>
<p class="mt-2 text-gray-500">Начало нового бизнеса - это тяжелая работа. Вот пять идей, которые вы можете использовать, чтобы найти своих первых клиентов.</p>
</div>
</div>
</div>
Но по мере роста проекта вы неизбежно будете повторять общие комбинации утилит для воссоздания одного и того же компонента во многих разных местах. Это наиболее очевидно с небольшими компонентами, такими как кнопки, элементы формы, значки и т. д.
<!-- Повторение этих классов для каждой кнопки может быть болезненным -->
<button class="py-2 px-4 bg-green-500 text-white font-semibold rounded-lg shadow-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-400 focus:ring-opacity-75">
Нажмите на меня
</button>
Синхронизация длинного списка служебных классов между многими экземплярами компонентов может быстро стать реальной проблемой обслуживания, поэтому, когда вы начинаете сталкиваться с болезненным дублированием, как это, рекомендуется извлечь компонент.
Очень редко вся информация, необходимая для определения компонента пользовательского интерфейса, может полностью храниться в CSS - почти всегда есть важная соответствующая структура HTML, которую вам также нужно использовать.
Не полагайтесь на классы CSS для извлечения сложных компонентов
<style>
.vacation-card { /* ... */ }
.vacation-card-info { /* ... */ }
.vacation-card-eyebrow { /* ... */ }
.vacation-card-title { /* ... */ }
.vacation-card-price { /* ... */ }
</style>
<!-- Даже с настраиваемым CSS вам все равно нужно дублировать эту HTML-структуру -->
<div class="vacation-card">
<img class="vacation-card-image" src="..." alt="Beach in Cancun">
<div class="vacation-card-info">
<div>
<div class="vacation-card-eyebrow">Частная вилла</div>
<div class="vacation-card-title">
<a href="/vacations/cancun">Расслабляющий курорт "все включено" в Канкуне</a>
</div>
<div class="vacation-card-price">$299 за ночь</div>
</div>
</div>
</div>
По этой причине часто лучше извлекать повторно используемые части Вашего пользовательского интерфейса в части шаблона или компонентах JavaScript вместо написания пользовательских классов CSS.
Создав единый источник истины для шаблона, вы можете продолжать использовать служебные классы без какой-либо нагрузки на обслуживание, создаваемой дублированием одних и тех же классов в нескольких местах.
Создайте частичный шаблон или компонент JavaScript
<!-- In use -->
<VacationCard
img="/img/cancun.jpg"
imgAlt="Пляж в Канкуне"
eyebrow="Частная вилла"
title="Расслабляющий курорт "все включено" в Канкуне"
pricing="$299 за ночь"
url="/vacations/cancun"
/>
<!-- ./components/VacationCard.vue -->
<template>
<div>
<img class="rounded" :src="img" :alt="imgAlt">
<div class="mt-2">
<div>
<div class="text-xs text-gray-600 uppercase font-bold">{{ eyebrow }}</div>
<div class="font-bold text-gray-700 leading-snug">
<a :href="url" class="hover:underline">{{ title }}</a>
</div>
<div class="mt-2 text-sm text-gray-600">{{ pricing }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['img', 'imgAlt', 'eyebrow', 'title', 'pricing', 'url']
}
</script>
В приведенном выше примере используется Vue, но тот же подход можно использовать с компонентами React, ERB partials, компонентами Blade, Twig includes и т. д.
Для небольших компонентов, таких как кнопки и элементы формы, создание части шаблона или компонента JavaScript часто может показаться слишком тяжелым по сравнению с простым классом CSS.
В таких ситуациях вы можете использовать директиву Tailwind @apply
, чтобы легко извлекать общие служебные шаблоны в классы компонентов CSS.
Вот как может выглядеть класс btn-indigo
при использовании @apply
для его составления из существующих утилит:
<button class="btn-indigo">
Нажмите на меня
</button>
<style>
.btn-indigo {
@apply py-2 px-4 bg-indigo-500 text-white font-semibold rounded-lg shadow-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-400 focus:ring-opacity-75;
}
</style>
Чтобы избежать непреднамеренных проблем со специфичностью, мы рекомендуем обернуть ваши стили пользовательских компонентов директивой @layer components { ... }
, чтобы сообщить Tailwind, к какому слою принадлежат эти стили:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn-blue {
@apply py-2 px-4 bg-blue-500 text-white font-semibold rounded-lg shadow-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-75;
}
}
Tailwind автоматически переместит эти стили в то же место, что и @tailwind components
, так что вам не нужно беспокоиться о правильном порядке в Ваших исходных файлах.
Использование директивы @layer
также проинструктирует Tailwind учитывать эти стили для очистки при очистке слоя components
. Прочтите нашу документацию по оптимизации для продакшена для получения более подробной информации.
Как и в случае с пользовательскими утилитами, вы можете генерировать responsive
, hover
, focus
, active
и другие варианты своих собственных компонентов, используя директиву @variants
:
/* ... */
@layer components {
@variants responsive, hover {
.btn-blue {
@apply py-2 px-4 bg-blue-500 ...;
}
}
}
Подробнее читайте в документации директивы @variants.
Помимо написания классов компонентов непосредственно в Ваших файлах CSS, вы также можете добавить классы компонентов в Tailwind, написав свой собственный плагин:
// tailwind.config.js
const plugin = require('tailwindcss/plugin')
module.exports = {
plugins: [
plugin(function({ addComponents, theme }) {
const buttons = {
'.btn': {
padding: `${theme('spacing.2')} ${theme('spacing.4')}`,
borderRadius: theme('borderRadius.md'),
fontWeight: theme('fontWeight.600'),
},
'.btn-indigo': {
backgroundColor: theme('colors.indigo.500'),
color: theme('colors.white'),
'&:hover': {
backgroundColor: theme('colors.indigo.600')
},
},
}
addComponents(buttons)
})
]
}
Это может быть хорошим выбором, если вы хотите опубликовать компоненты Tailwind в виде библиотеки или упростить совместное использование компонентов в нескольких проектах.
Подробнее читайте в документации подключаемого модуля к компоненту.