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

—

от автора

Всем привет!

Обычно 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, что позволяет ему расти и развиваться быстрее.

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

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

Милый котик

Милый котик

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


ссылка на оригинал статьи https://habr.com/ru/articles/763126/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *