Обзор

Традиционно, когда вам нужно стилизовать что-то в сети, вы пишете CSS.

Использование традиционного подхода, когда для нестандартного дизайна требуется собственный CSS

ChitChat

У вас новое сообщение!

<div class="chat-notification">
  <div class="chat-notification-logo-wrapper">
    <img class="chat-notification-logo" src="/img/logo.svg" alt="ChitChat Logo">
  </div>
  <div class="chat-notification-content">
    <h4 class="chat-notification-title">ChitChat</h4>
    <p class="chat-notification-message">У вас новое сообщение!</p>
  </div>
</div>

<style>
  .chat-notification {
    display: flex;
    align-items: center;
    max-width: 24rem;
    margin: 0 auto;
    padding: 1.5rem;
    border-radius: 0.5rem;
    background-color: #fff;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  }
  .chat-notification-logo-wrapper {
    flex-shrink: 0;
  }
  .chat-notification-logo {
    height: 3rem;
    width: 3rem;
  }
  .chat-notification-content {
    margin-left: 1.5rem;
  }
  .chat-notification-title {
    color: #1a202c;
    font-size: 1.25rem;
    line-height: 1.25;
  }
  .chat-notification-message {
    color: #718096;
    font-size: 1rem;
    line-height: 1.5;
  }
</style>

С Tailwind вы стилизуете элементы, применяя уже существующие классы непосредственно в Вашем HTML.

Использование служебных классов для создания пользовательского дизайна без написания CSS

ChitChat

У вас новое сообщение!

<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4">
  <div class="shrink-0">
    <img class="size-12" src="/img/logo.svg" alt="ChitChat Logo">
  </div>
  <div>
    <div class="text-xl font-medium text-black">ChitChat</div>
    <p class="text-slate-500">У вас новое сообщение!</p>
  </div>
</div>

В приведенном выше примере мы использовали:

  • Утилиты Tailwind flexbox и padding (flex, shrink-0 и p-6) для управления общим макетом карты
  • Утилиты max-width и margin (max-w-sm и mx-auto) для ограничения ширины карты и ее центрирования по горизонтали
  • Утилиты background color, border radius и box-shadow (bg-white, rounded-xl и shadow-lg) для стилизации внешнего вида карты
  • Утилиты size utilities (size-12) для установки ширины и высоты изображения логотипа
  • Утилиты space-between (space-x-4) для управления интервалом между логотипом и текстом
  • Утилиты font size, text color и font-weight (text-xl, text-black, font-medium и т. д.) для стилизации текста карточки

Такой подход позволяет нам реализовать полностью настраиваемый дизайн компонента без написания ни одной строчки пользовательского CSS.

Теперь я знаю, о чем вы думаете “это злодеяние, какой ужасный беспорядок!” И вы правы, это некрасиво. На самом деле практически невозможно подумать, что это хорошая идея, когда вы впервые ее видите - вы должны действительно попробовать.

Но как только вы действительно построите что-то таким образом, вы быстро заметите некоторые действительно важные преимущества:

  • вы не тратите энергию, изобретая названия классов. Больше не нужно добавлять глупые имена классов, такие как sidebar-inner-wrapper, просто чтобы иметь возможность стилизовать что-то, и больше не нужно мучиться над идеальным абстрактным именем для чего-то, что на самом деле является просто гибким контейнером.
  • ваш CSS перестает расти. При использовании традиционного подхода Ваши CSS-файлы становятся больше каждый раз, когда вы добавляете новую функцию. С помощью утилит все можно использовать повторно, поэтому вам редко нужно писать новый CSS.
  • Вносить изменения безопаснее. CSS глобален, и вы никогда не знаете, что нарушаете, когда вносите изменения. Классы в Вашем HTML являются локальными, поэтому вы можете изменять их, не беспокоясь о том, что что-то еще сломается.

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


Почему бы просто не использовать встроенные стили?

Обычная реакция на этот подход - спросить: “Разве это не просто встроенные стили?” и в некотором смысле это так - вы применяете стили непосредственно к элементам, вместо того, чтобы присваивать им имя класса, а затем стилизовать этот класс.

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

  • Проектирование с ограничениями. При использовании встроенных стилей каждое значение является магическим числом. С помощью утилит вы выбираете стили из предопределенной design system, что значительно упрощает создание визуально согласованных пользовательских интерфейсов.
  • Адаптивный дизайн. Вы не можете использовать медиа-запросы во встроенных стилях, но вы можете использовать responsive utilities Tailwind, чтобы легко создавать полностью адаптивные интерфейсы.
  • Наведение, фокус и другие состояния. Встроенные стили не могут нацеливаться на такие состояния, как наведение или фокус, но state variants Tailwind упрощают стилизацию этих состояний с помощью служебных классов.

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

Женское лицо

Эрин Линдфорд

Инженер по продукту

<div class="py-8 px-8 max-w-sm mx-auto bg-white rounded-xl shadow-lg space-y-2 sm:py-4 sm:flex sm:items-center sm:space-y-0 sm:space-x-6">
  <img class="block mx-auto h-24 rounded-full sm:mx-0 sm:shrink-0" src="/img/erin-lindford.jpg" alt="Женское лицо" />
  <div class="text-center space-y-2 sm:text-left">
    <div class="space-y-0.5">
      <p class="text-lg text-black font-semibold">
        Эрин Линдфорд
      </p>
      <p class="text-slate-500 font-medium">
        Инженер по продукту
      </p>
    </div>
    <button class="px-4 py-1 text-sm text-purple-600 font-semibold rounded-full border border-purple-200 hover:text-white hover:bg-purple-600 hover:border-transparent focus:outline-none focus:ring-2 focus:ring-purple-600 focus:ring-offset-2">Сообщение</button>
  </div>
</div>

Проблемы с обслуживанием

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

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

<!-- PrimaryButton.vue -->
<template>
  <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
    <slot/>
  </button>
</template>

Кроме того, поддержка CSS-проекта, ориентированного на полезность, оказывается намного проще, чем поддержка большой кодовой базы CSS, просто потому, что HTML гораздо проще поддерживать, чем CSS. Крупные компании, такие как GitHub, Netflix, Heroku, Kickstarter, Twitch, Segment и другие, с большим успехом используют этот подход.

Если вы хотите узнать об опыте других, использующих этот подход, ознакомьтесь со следующими ресурсами:

Чтобы узнать больше, ознакомьтесь с Доводы в пользу атомарного/утилитного CSS, куратором которого является Джон Полачек.