Как стать автором
Обновить

Tailwind не только для MVP

Время на прочтение7 мин
Количество просмотров6.5K

Всем привет!

Обычно Tailwind используют для каких-то MVP/админок/не очень больших проектов, но мне кажется, что Tailwind, имеет место быть в средних и крупных проектах. Большинство его минусы решаемы, а плюсы чертовски хороши :)

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

Сначала, коротко о том, что такое Tailwind

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

На главной Tailwind можно прочитать вот это - Rapidly build modern websites without ever leaving your HTML.Что дословно можно перевести как - Быстро создавай вебсайты, не отходя от HTML.

Выглядит как-то так:

Tailwind notation | CSS notation
Tailwind notation | CSS notation

Перейдем к плюсам

  • Плюс который вытекает из заголовка на главной — нам крайне редко нужно обращаться к css файлам, почти все стили мы храним в самой разметке это сильно ускоряет скорость разработки и позволяет не терять фокус при верстке(не нужно постоянно свитчиться между css и файлом с разметкой)

  • Удобный подход к адаптивной верстке, для того чтобы указать определенное свойство для другого разрешения тебе нужно поставить определенный префикс который ты заранее можешь определить в конфигурационном файле, например вот так просто мы можем сделать карточку по горизонтали на мобильном устройстве(отлично работает, если у вас много breakpoints).

<template>
	<div class="flex flex-col gap-2 sm:flex-row">
		<h2>Responsive card</h2>
		<p>Some context</p>
	</div>
</template>
  • Темная тема поддерживается из коробки, все что вам нужно для того, чтобы ее использовать - прописать префикс - dark:

<template>
	<div class="bg-[#000000] dark:bg-[#ffffff]">
		<h2>Responsive card</h2>
		<p>Some context</p>
	</div>
</template>
  • Больше не нужно придумывать названия классов, для твоих элементов, хоть сейчас это и не является большой проблемой, так как есть например css-modules, но даже там нужно давать осмысленные имена и избегать коллизий этих имен.

  • Плагины и расширения, которые есть для Tailwind, вот например статья с 50 таковыми - тык

  • Удобная кастомизация, с помощью tailwind.config, это позволяет очень удобно интегрироваться с дизайн системой(если у вас таковая имеется). Единая система в одном месте, которая может быть пошаренной между большим количеством проектов одновременно(+ к хорошей масштабируемости).

theme: {
    colors: {
      'blue': '#1fb6ff',
      'purple': '#7e5bef',
      'pink': '#ff49db',
      'orange': '#ff7849',
      'green': '#13ce66',
      'yellow': '#ffc82c',
      'gray-dark': '#273444',
      'gray': '#8492a6',
      'gray-light': '#d3dce6',
    },
    fontFamily: {
      sans: ['Graphik', 'sans-serif'],
      serif: ['Merriweather', 'serif'],
    },
    extend: {
      spacing: {
        '8xl': '96rem',
        '9xl': '128rem',
      },
      borderRadius: {
        '4xl': '2rem',
      }
    }
  },
  • Одни и те же css свойства импортируются всего 1 раз

  • Легкая интеграция с различными фреймворками React, Vue, etc…

Самые модные фреймворки
Самые модные фреймворки
  • Можно совмещать с обычным CSS(приятно, когда проект начинает разрастаться), вас никто не ограничивает и не говорит, что нужно писать только на Tailwind, так что вы можете писать что-то такое:

.someClass {
	background: #000000;

	@apply w-10 h-10 rounded-10; 
}
  • 6.5 миллионов скачиваний за последнюю неделю на npm(довольно большое community), у vue например всего 4 миллиона.

  • В выходном css файле у вас не будут присутствовать классы, которые реально не используются в разметке. Чистота и минимизация. Причем это относится и к тем классам, которые добавляются скриптами. Однако если вы хотите, чтобы некий класс всегда присутствовал на выходе, то вы и это можете сделать, объявив его вне директивы @ layer (отличный поинт от комментатора :) )

А какие минусы ?

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

  • Существенно разрастается разметка и ее становится тяжело поддерживать

  • Затруднена навигация с помощью devtools. Не так хорошо работает, как с классами

  • Отсутствует переиспользуемость 

Сейчас я расскажу как победить эти минусы

Фотокарточка для хорошего настроения
Фотокарточка для хорошего настроения

Существенно разрастается разметка и ее становится тяжело поддерживать

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

Кошмар верстальщика
Кошмар верстальщика

Не знаю, может кто и пишет так код с помощью Tailwind, но на мой взгляд это еще то извращение.

Я не поленился и переписал ее(да, мне нечем заняться) в нормальном стиле на Tailwind и написал тоже самое на обычный CSS.

Вот два получившихся компонента, по максимуму вынес в обоих случаях общее и получил следующий код:

TailwindNotation.vue
<template>
  <section class="flex justify-center mb-[140px]">
    <div
      class="wrapper"
    >
      <div
        class="block-1 relative bg6 bg-cover bg-center w-full max-w-[1440px] p-[64x] pc:p-[80px] text-white"
      ></div>
      <div
        class="block-2 "
      ></div>
      <div
        class="block-3"
      ></div>
    </div>
  </section>
</template>


<style lang="scss" scoped>
.wrapper {
  &::before, &::after {
    @apply content-[''] absolute
    h-[50px] pc:h-[90px] w-[50px] pc:w-[90px]
    top-[24px] pc:top-[30px]
    bg-[url('*~/assets/images/cta_decoration.png')] bg-cover
  }

  &::before {
    @apply cleft-[24x] pc:left-[30px]
  }

  &::after {
    @apply right-[24px] pc:right-[30px]
  }
}


.block-1 {
  &::before, &::after {
    @apply content-[''] absolute
    w-[calc(100%__164px)] pc:w-[calc(100%_-_260px)]
    left-[82px] pc:left-[130px]
    border-t-2 pc:border-t-4 border-brown3
  }

  &::before {
    @apply top-[32px] pc:top-[40px]
  }

  &::after {
    @apply bottom-[32px] pc:bottom-[40px]
  }

}

.block-2 {
  &::before, &::after {
    @apply absolute
    h-[calc(100%_-_164px)] pc:h-[calc(100%_-_260px)]
    top-[82px] pc:top-[130px]
    border-1-2 pc:border-l-4 border-brown3
  }

  &::before {
    @apply content-[''] 
    left-[32px] pc:left-[40px]
  }

  &::after {
    @apply content-[1] 
    right-[32px] pc:right-[40px]
  }
}

.block-3 {
  &::before, &::after {
    @apply content-[''] absolute
    w-[50px] h-[50px] pc:w-[90px] pc:h-[90px]
    bottom-[24px] pc:bottom-[30px]
    bg-[urt('~/assets/images/cta_decoration.png')] bg-cover
    rotate-180
  }
  
  &::before {
    @apply left-[24x] pc:left-[30px]
    scale-x-[-1]
  }

  &::after {
    @apply right-[24px] pc:right-[30px]
  }
}
</style>

CSSNotation.vue
<template>
  <section class="section">
    <div
      class="wrapper"
    >
      <div
        class="block-1"
      ></div>
      <div
        class="block-2 "
      ></div>
      <div
        class="block-3"
      ></div>
    </div>
  </section>
</template>


<style lang="scss" scoped>
.section {
  display: flex;
  justify-content: center;
  margin-bottom: 140px;
}

.wrapper {
  position: relative;
  width: 100%;
  color: #ffffff;
  background-position: center;
  background-size: cover;
  max-width: 1440px;
  padding: 64px;
  @media (max-width: 1440px) {
    padding: 80px;
  }

  &::before, &::after {
    content: '';
    position: absolute;
    height: 50px;
    width: 50px;
    top: 24px;
    background: url('*~/assets/images/cta_decoration.png');
    background-size: cover;
    @media (max-width: 1440px) {
      height: 90px;
      width: 90px;
      top: 30px;
    }
  }

  &::before {
    left: 24px;
    @media (max-width: 1440px) {
      left: 30px;
    }
  }

  &::after {
    right: 24px;
    @media (max-width: 1440px) {
      right: 30px;
    }
  }
}


.block-1 {
  &::before, &::after {
    position: absolute;
    width: calc(100% - 164px);
    top: 32px;
    border-top-width: 2px;
    border-color: brown;
    left: 82px;
    @media (max-width: 1440px) {
      width: calc(100% - 260px);
      left: 130px;
      top: 40px;
      border-top-width: 4px;
    }
  }

  &::before {
    content: '';
  }

  &::after {
    content: '1';
  }
}

.block-2 {
  &::before, &::after {
    position: absolute;
    width: calc(100% - 164px);
    top: 32px;
    border-top-width: 2px;
    border-color: brown;
    @media (max-width: 1440px) {
      width: calc(100% - 260px);
      top: 40px;
      border-top-width: 4px;
    }
  }

  &::before {
    left: 32px;
    content: '';
    @media (max-width: 1440px) {
      left: 40px;
    }
  }

  &::after {
    right: 32px;
    content: '1';
    @media (max-width: 1440px) {
      right: 40px;
    }
  }
}

.block-3 {
  &::before, &::after {
    content: '';
    position: absolute;
    width: 50px;
    height: 50px;
    bottom: 24px;
    border-top-width: 2px;
    border-color: brown;
    transform: rotate(180deg) scaleX(-1);
    background: url('*~/assets/images/cta_decoration.png');
    background-size: cover;
    @media (max-width: 1440px) {
      width: 90px;
      height: 90px;
      bottom: 30px;
    }
  }

  &::before {
    left: 24px;
    @media (max-width: 1440px) {
      left: 30px;
    }
  }

  &::after {
    right: 24px;
    @media (max-width: 1440px) {
      right: 32px;
    }
  }
}

</style>

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

В итоге при таком подходе мы получили, что у нас нет портянки классов в разметке, но при этом и css файл у нас получился компактным — 75 строк с использование Tailwind и 140 строк с использованием обычных стилей, разница почти в 2 раза.

И в целом при высокой декомпозиции кода, у вас не должно получаться больше 5-8 свойств на элемент, что является довольно читаемым, а если у вас больше свойств, то на помощь приходит apply

Навигация с помощью devtools не так хорошо работает, как с классами с хорошим неймингом.

Это проблему можно решить многими способами, я опишу 2

  • Использование Vue DevTools/React DevTools и хорошее разделение на компоненты

Vue DevTools
Vue DevTools
  • Добавление дата атрибутов и навигация с помощью них, например

<template>
	<div data-id="responsive-card" class="bg-[#000000] dark:bg-[#ffffff]">
		<h2>Responsive card</h2>
		<p>Some context</p>
	</div>
</template>
Навигация с помощью селектора по data атрибуту
Навигация с помощью селектора по data атрибуту

Отсутствует переиспользуемость.

  • С помощью директивы apply, можно сделать как в коде ниже и получить переиспользуемый класс с использованием Tailwind классов

@layer components {
  .btn-primary {
    @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.config.js и пример переиспользуемых цветов

theme: {
    colors: {
      'blue': '#1fb6ff',
      'purple': '#7e5bef',
      'pink': '#ff49db',
      'orange': '#ff7849',
      'green': '#13ce66',
      'yellow': '#ffc82c',
      'gray-dark': '#273444',
      'gray': '#8492a6',
      'gray-light': '#d3dce6',
    },
}

Так почему же Tailwind не только для MVP

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

Выбор за вами!

А напоследок оставлю здесь милого котика для хорошего настроения

Милый котик
Милый котик

Если статья показалась вам интересной, то у меня есть Тг-канал, где я пишу про новые технологии во фронте, делюсь хорошими книжками и интересными статьями других авторов.

Теги:
Хабы:
Всего голосов 10: ↑9 и ↓1+8
Комментарии30

Публикации

Истории

Работа

Ближайшие события

One day offer от ВСК
Дата16 – 17 мая
Время09:00 – 18:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн
Антиконференция X5 Future Night
Дата30 мая
Время11:00 – 23:00
Место
Онлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область