Tailwind is not just for MVP

Hi all!

Usually Tailwind is used for some MVP/admin/not very large projects, but it seems to me that Tailwind has a place in medium and large projects. Most of its disadvantages can be solved, but its advantages are damn good 🙂

In this article I will describe its pros and cons and how you can turn the cons into advantages.

First, a quick introduction to what Tailwind is.

Tailwind is a CSS framework that provides a set of ready-made classes for styling web interfaces.

On the main Tailwind you can read this – Rapidly build modern websites without ever leaving your HTML.Which literally can be translated as – Quickly create websites without leaving HTML.

It looks something like this:

Tailwind notation |  CSS notation

Tailwind notation | CSS notation

Let’s move on to the positives

  • The advantage that follows from the title on the main page is that we rarely need to access css files, we store almost all of the styles in the markup itself, this greatly speeds up the development speed and allows us not to lose focus during layout (no need to constantly switch between css and the markup file)

  • A convenient approach to adaptive layout, in order to specify a certain property for a different resolution, you need to put a certain prefix that you can define in advance in the configuration file, for example, just like this, we can make a card horizontally on a mobile device (works great if you have a lot breakpoints).

<template>
	<div class="flex flex-col gap-2 sm:flex-row">
		<h2>Responsive card</h2>
		<p>Some context</p>
	</div>
</template>
  • The dark theme is supported out of the box, all you need to use it is to enter the prefix – dark:

<template>
	<div class="bg-[#000000] dark:bg-[#ffffff]">
		<h2>Responsive card</h2>
		<p>Some context</p>
	</div>
</template>
  • You no longer need to come up with class names for your elements, although now this is not a big problem, since there is, for example css-modulesbut even there you need to give meaningful names and avoid collisions of these names.

  • Plugins and extensions that are available for Tailwind, for example, here is an article with 50 of them – poke

  • Convenient customization using tailwind.config, this allows you to very conveniently integrate with the design system (if you have one). A single system in one place, which can be shared between a large number of projects at the same time (+ good scalability).

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',
      }
    }
  },
  • The same css properties are imported only 1 time

  • Easy integration with various frameworks React, Vue, etc…

The most fashionable frameworks

The most fashionable frameworks

  • Can be combined with regular CSS (nice when the project starts to grow), no one limits you or tells you that you need to write only in Tailwind, so you can write something like this:

.someClass {
	background: #000000;

	@apply w-10 h-10 rounded-10; 
}

What are the disadvantages?

I’ll say right away that I’m quite biased towards Tailwind, since I’ve been successfully using it in production for quite a long time and I like everything about it, so there will be a little less cons, it’s honestly great. I have highlighted the most common disadvantages that I usually hear.

  • The markup grows significantly and becomes difficult to maintain.

  • Navigation using devtools is difficult. Doesn’t work as well as with classes

  • No reusability

Now I will tell you how to overcome these disadvantages

Photo card for a good mood

Photo card for a good mood

The markup grows significantly and becomes difficult to maintain.

A picture that inspires horror (the most common picture in favor of not using Tailwind in your projects)

A layout designer's nightmare

A layout designer’s nightmare

I don’t know, maybe someone writes code like this using Tailwind, but in my opinion this is still a perversion.

I wasn’t too lazy and rewrote it (yes, I have nothing better to do) in a normal style on Tailwind and wrote the same thing in regular CSS.

Here are the two resulting components, I took out as much as possible what was common in both cases and got the following code:

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>

And here you can clearly see that if you approach the separation of all this wisely, you will get neat code, but here we cannot do without using a css file and directives applybut this is the exception rather than the rule.

As a result, with this approach, we got that we do not have a footcloth of classes in the markup, but at the same time, our CSS file turned out to be compact – 75 lines using Tailwind and 140 lines using regular styles, the difference is almost 2 times.

And in general, with a high code decomposition, you should not get more than 5-8 properties per element, which is quite readable, and if you have more properties, then apply comes to the rescue

Navigation with devtools does not work as well as with well-named classes

This problem can be solved in many ways, I will describe 2

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>
Navigation using a data attribute selector

Navigation using a data attribute selector

No reusability

  • Using a directive applyyou can do as in the code below and get a reusable class using Tailwind classes

@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;
  }
}
theme: {
    colors: {
      'blue': '#1fb6ff',
      'purple': '#7e5bef',
      'pink': '#ff49db',
      'orange': '#ff7849',
      'green': '#13ce66',
      'yellow': '#ffc82c',
      'gray-dark': '#273444',
      'gray': '#8492a6',
      'gray-light': '#d3dce6',
    },
}

So why isn’t Tailwind just for MVPs?

Tailwind, like many other tools, should be used when appropriate. However, it seems to me that it is unfairly classified as a tool that should not be used for the development of medium and large projects. It has some disadvantages in terms of scalability and extensibility, but as we can see from the solutions to the disadvantages, they can be solved and you can live with them. Tailwind also has a growing community every year, which allows it to grow and develop faster.

The choice is yours!

And finally, I’ll leave here a cute cat for a good mood

Cute cat

Cute cat

If you found this article interesting, then I have TG channelwhere I write about new technologies at the front, share good books and interesting articles by other authors.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *