The goal of separating HTML and CSS is to keep appearance and semantics separate. Changes in the structure of a page should never break its styles. Similarly, a change in style should never necessitate a change in structure. Though it seems straightforward, achieving separation of concerns is not as easy as it sounds.
In the early days of HTML, we could have written something like this:
<h2>
<font color="red" face="sans-serif" size="+1">
<center>
<u>
Hello there!
</u>
</center>
</font>
</h2>
This code mixes structure and style. Font
, center
, and u
elements are only used for styling purposes. In order to change the styling of our document, we would need to change its semantic structure. This is where CSS comes in.
Although content and appearance should be kept separate, they cannot be separable. There needs to be some connection between a particular piece of content and its appearance. CSS classes are the most common link between structure and style.
<article>
<h2 class="main-title">
Hello there!
</h2>
</article>
<style>
article > h2.main-title {
text-align: center;
...
}
</style>
The obvious semantic improvements on HTML come at a less obvious cost: it is now CSS that combines structure and style. Classes such as .main-title
have semantic meaning. When CSS is written this way, it needs to be aware of the semantic structure (ex. article > h2
) and the classes it exposes. As a result, changing our structure can easily break our styles.
We can call this CSS Hell. CSS is dependent on our HTML. Styling is under our full control, but it breaks if we change the HTML structure. If there’s a site-wide .article
class, and a site-wide .featured
class, finding out what’s wrong with <div class=“featured article”>
can be a pain.
The effort to write sound, decoupled CSS that doesn’t break has led to the popularity of CSS writing guidelines such as BEM, which resulted in HTML code such as the following:
<article class="main-article">
<img class="main-article__image" src="..." alt="">
<div class="main-article__content">
<h2 class="main-article__title">The future of CSS</h2>
<p class="main-article__paragraph">
As we all know, HTML & CSS are the main blocks of the …
</p>
</div>
</article>
To further detach CSS styling from HTML, BEM uses long, repetitive class names. But is that really effective? Classes carry more semantic meaning than before, and the roles are almost reversed. Semantic meaning is now defined by CSS, while HTML must adhere to its structure. HTML and CSS may appear decoupled, but they are now more interconnected than ever. As a result, both structure and style now require more effort to update, since the one can’t change without simultaneously changing the other.
Despite its shortcomings, popular CSS frameworks such as Material UI and Bootstrap have adopted this approach. These frameworks fix in part the HTML structure that needs to be followed, but at the same time prevent substantial changes to their CSS. As a result of such à la carte design, many websites using such frameworks have a distinctively similar look.
At this point of CSS evolution, it feels like we are turning in circles. Every time we try to untie the knot between HTML and CSS, the knot gets tighter in ever less obvious ways. How is that happening? There must certainly be some way to :
It is with this purpose in mind that TailwindCSS was created.
Although it seems counter-intuitive, keeping our styles and structure separate does not imply we have to keep them far apart. Our styles and structure can be completely independent from one another, while still being physically close. In fact, the closer our structure is to its styles, the easier it will be to read, understand, and update both.
Here is where Tailwind’s utility-first design comes into play.
Using utility classes, you can define the styling of an element directly on the element itself. As a result, when you look at an element, you can also read its styling. It is no longer necessary to open another file to see how an element is styled or to search through many files to find where a style is defined. Let’s look at our old-school HTML example, rewritten in Tailwind:
<h2 class="text-red-800 text-lg text-center underline font-sans">
Hello there!
</h2>
Here we define a Level 2 Heading, which has text that is dark red, large, centered, underlined, using a sans-serif font. Using utility classes, we can create both semantically sound, readable HTML and non-semantic, readable CSS. HTML and CSS can be updated simultaneously while remaining entirely independent of one another.
Tailwind’s utility classes are designed to fulfill a single purpose at a time, such as changing text size, text color, background color, padding, margins, etc. Tailwind CSS’s thousands of independent utility classes can be combined creatively to build highly customized website components that “just work” no matter where you place them. As a result, you can create entirely new UI components without having to write any new CSS.
Utility classes don’t end there! A pseudo-class can be applied to an element in the class attribute itself. Think of changing the background color of a button on hover, for instance. Here’s how easily you can achieve this:
<button class="bg-blue-500 hover:bg-blue-400">Buy Now</button>
In addition to hover, you can use other pseudo-classes like focus, active, etc.
With TailwindCSS, the days of writing media queries to make our UI responsive are over! We can implement a fully responsive UI using only class utilities. For example, we could change the heading text size based on the screen size:
<h2 class="text-base lg:text-lg xl:text-xl">
Hello there!
</h2>
By default, TailwindCSS provides 5 different breakpoints: sm: 640px
, md: 768px
, lg: 1024px
, xl: 1280px
, and 2xl: 1536px
. TailwindCSS is mobile-first, so the default text size will be determined by text-base
, while text-lg
and text-xl
will be applied after the lg
and xl
breakpoints respectively. As most things in tailwind, breakpoints are configurable, so you can change their values or create your own breakpoints as needed.
TailwindCSS provides infinite customization options. You can set your own defaults for each utility, manually add your own utilities, or, most impressively, generate your own utilities simply by using them! As an example, let’s say we want a heading with a specific color and font size:
<h2 class="text-[19px] text-[#F2F2F2]">
Hello there!
</h2>
TailwindCSS’s Just-In-Time (JIT) builder picks our custom utilities defined using brackets and generates their CSS on the fly. Talk about magic!
TailwindCSS is growing very rapidly and is already one of the most popular CSS frameworks. This is due to many reasons. Its features make it an excellent choice for a wide range of projects, but Tailwind’s strongest advantage is that it allows developers to style their applications very quickly without having to make any compromises in appearance.
TailwindCSS makes it possible to write custom CSS without writing any CSS. This results in a much faster styling process. You can now style your elements, in the time it takes to type your semantic structure. This allows you to code complex layouts in a much shorter time than if you had to go back and forth between html and css.
After you get over the learning curve, it becomes remarkably productive. Personally, I feel like I’m building UIs 10x faster. It’s not just writing the initial interface that is impressively fast, but also the fact that I barely need to debug it after I first write it. Furthermore, it’s difficult to overestimate the feeling of satisfaction you get from completing beautiful UIs quickly.
A big reason Tailwind is so fast to use is that you rarely have to switch contexts. With almost everything you need provided by the framework, you rarely have to leave HTML when creating a design. Getting a design just right won’t require switching from HTML to CSS hundreds of times. It is a much more efficient way to develop your designs.
TailwindCSS styles can easily be read by developers as they scan their code. Additionally, TailwindCSS classes are often more meaningful than their CSS equivalents. Consider setting text size in CSS as follows: font-size: 1.875rem
. Is that too big? Too small? It’s hard to tell. It’s also hard to keep consistent. In one page you can set font-size: 1.825rem
and in another font-size: 1.850rem
resulting in slight inconsistencies in your design that are difficult to track. Over time, this leads to an inconsistent and bloated design.
TailwindCSS’s equivalent would be text-lg
. That makes sense right away. You can go smaller with text-sm
and larger with text-xl
. Using the same sizes over and over, you’ll also maintain consistency without any extra effort.
Have you ever copied code from StackOverflow? Don’t worry, everyone does it. Now it is possible to copy your designs, too! With TailwindCSS you can copy part of your code from a previous application into your current one, and it will mostly just work!
Nothing is more painful in css than having to maintain huge piles of media queries. Responsiveness adds yet another layer of complexity, requiring you to look left and right, up and down to make sure nothing has escaped its original purpose. With built-in breakpoints and a mobile-first approach, TailwindCSS makes responsive design feel like a breeze.
Naming CSS classes can be needlessly time consuming. Two words to describe a complex yet flexible element? Having to do that over and over is a huge bottleneck, and Tailwind eliminates it completely in most scenarios.
A major challenge when switching between projects is having to learn CSS name conventions from scratch. This is especially true for development agencies that switch between projects frequently. TailwindCSS allows you to standardize your CSS across multiple projects, making it easy for developers to jump from one project to another. Eventually, your team will be able to create bug-free interfaces faster, and even reuse components across projects, regardless of the front-end framework used.
TailwindCSS allows you to create designs that are scoped by default. No more CSS hell! With regular CSS, changes to your styles in one part of your application might have unintended consequences in other parts. With TailwindCSS, any changes you make will be applied only to the current elements on the page you are working on. As your HTML elements don’t interfere with each other, debugging is greatly simplified and you can make changes to your codebase with much greater confidence.
With TailwindCSS, it is easy to create reusable components without having to use React or other JS libraries. Although Tailwind does not come with reusable component styles like .modal
or .navbar
, you can easily create custom components from combinations of other utilities using the @apply
directive in your CSS. For example, let’s create a custom button class:
.main-button {
@apply w-32 h-10 bg-blue-700 hover:bg-blue-800 rounded text-white;
}
Since its initial release, TailwindCSS has proven to be a stable framework, backed by top-notch engineers. Bugs are infrequent, while a lot of work has been done to make it an ideal framework for production settings.
Most applications use only a tiny fraction of the utility classes provided by Tailwind. Tailwind’s “purge” feature removes any unnecessary utility classes from the production build. By eliminating unused classes, we can reduce the size of the CSS shipped to users and make our site load faster. Additionally, unlike regular CSS, your styles will not grow as your project grows. Since you’re using a set of standardized classes throughout your project, your CSS file will typically remain small.
In addition to being an excellent framework, Tailwind also comes with very clear documentation. The documentation provides a lot of digestible information regarding the framework. It is easy to navigate the website through any topic, and the search bar lets you quickly discover nearly anything.
A good idea before switching to a new framework is to gauge its popularity. It’s easier to find great developers and supportive online communities for frameworks that have a large following. Tailwind has certainly attracted quite a following since its release. Tailwind CSS has been used by more than 760k developers and that number keeps growing by the day. With Tailwind’s enormous popularity in the developer community, potential problems can be solved more easily.
VSCode developers will benefit greatly from Tailwind’s official extension. By using auto-complete, you can select from the available utility classes, and by hovering over a class name, you can see useful explanations about which CSS class is being used. For example, hovering over text-3xl
will display the following:
.text-3xl {
font-size: 1.875rem /* 30px */;
line-height: 2.25rem /* 36px */;
}
As with any framework, Tailwind isn’t perfect. For example, long strings of classes can become difficult to read, even in common use cases. In most cases, however, its benefits far outweigh the downsides. If you’re looking for a new CSS framework, I would strongly urge you to try Tailwind!