Hey folks,
In my previous post, introducing the Rocketicons, a powerful icon library designed to be used with Tailwind, I expressed my love for the framework, how amazing I think it is, and encouraged its use.
A colleague shared an interesting insight that caught my attention.
On one hand, I don’t think this is a problem exclusive to Tailwind, but on the other, I can’t deny it’s a good point that deserves special care from developers. Tailwind is really easy to use and can invite you to just start doing things, but its indiscriminate use can generate problems.
You've probably heard about clean code, good practices, and things like that. If you haven’t figured it out yet, those aren’t about creating code people admire or getting kudos. It’s about how easy it is to look at your code and understand what it does, because this way, you can continue your work. It’s about having a structure that is easy to extend, change, and maintain. Sometimes, even the creator, after some time, looks at the code and thinks, "What does this do? How does it work? How can I change it?" These are situations we must find ways to avoid.
If you're trying to understand why good practices are important, take a look on Understanding Code Quality: The Why Behind Best Practices.
I’m not here to dictate rules because I don’t believe there is a single right way of doing things. Therefore, this is not the ultimate guide for all Tailwind’s good practices, but perhaps with community collaboration, it can become one someday. The absence of a right way definitely does not exclude the possibility of a wrong way, because it does exist. Failing to follow a few principles in code writing will create a maintenance nightmare. By the way, once you create any code, keep in mind that someone will need to maintain it, and that someone could be you!
I’m going to share tips and explanations to help you make great use of Tailwind, using the power of the tool on your side to create amazing experiences for your users.
Learn CSS
How can you style if you don’t know anything about styling?!
Understanding the fundamentals of CSS is crucial before diving into Tailwind. In fact, that point is valid for any framework you are trying to learn. While Tailwind simplifies many styling tasks, a base knowledge of CSS is required to understand how styling works. It’s not just about understanding how Tailwind works under the hood, which helps you use it effectively, but also about seeing the big picture of what styling is. Besides, knowing CSS also empowers you to create custom utilities in Tailwind when the predefined ones don’t meet your needs.
So, the first one is: Learn CSS!
Dominate the tool
Tailwind is powerful, but only if you know how to use it properly.
Tailwind is powerful, but only if you know how to use it properly. Spend time reading the documentation, experimenting with different classes, and understanding how utility-first CSS works. Pay special attention to understanding configuration and how plugins work. This will help you master the tool and know when and how to use each feature. The documentation includes plenty of examples and explanations to get you started and help you become an expert on the framework.
Become a Master of the Tool!
Use of the colors
Tailwind offers a predefined palette of colors, but you can (and should) customize it to match your brand guidelines.
The available options offered out of the box are amazing, inviting us to just use them, creating combinations and coloring everything. What’s the problem, right? I’m just using blue and slate variations all over the code, why is it a problem? But imagine you face a rebranding, and blue now becomes sky. How many places will require changes? How safe is it to just run a replace all? Define a set of colors in the Tailwind configuration file and stick to them. This ensures consistency across your application and makes it easier to manage changes globally.
The documentation is very detailed, so I don’t think you will face any problems doing this. Just take a look at naming your colors to help you achieve it.
My personal preference is for the Material Color System convention. I think it’s clear and suitable for most situations. The color names, such as primary, secondary, and surface, are descriptive and not connected to any specific brand, making them suitable for multiple applications. That’s why I choose it. But don’t be afraid to experiment with different options.
Just avoid hardcoding colors in your HTML.
Customize to match your needs*
Sometimes you need something more specific for your project.
Tailwind's default utilities cover a lot of ground, but don’t hesitate to create your own utilities. This can help keep your HTML clean and make your styling more manageable.
For example, if you frequently use a specific combination of classes, like for text color where you use text-primary dark:text-primary-700
, consider creating a custom utility.
// tailwind.config.js
module.exports = {
theme: {
extend: {},
},
variants: {},
plugins: [
({ addUtilities }) => {
addUtilities({
'.text-default': {
"@apply text-primary dark:text-primary-700": {}
}
})
}
]
}
or using css syntax
@tailwind base;
@tailwind components;
@tailwind utilities;
...
@layer utilities {
.text-default {
@apply text-primary dark:text-primary-700;
}
}
The same goes for variations, breakpoints, etc.
Do be afraid to create our own utilities!
Reuse your code*
Have you heard about DRY (Don’t Repeat Yourself)?
It’s not just because repetition is ugly or wrong. How can code you wrote once nicely and runs well stop working or looking bad just because you copied it twice? The problem, once again, is regarding maintenance.
Imagine you find an issue and need to update the routine for any reason. How many places will need an update? What are the odds you miss one spot and deploy code with a bug? That’s why the DRY principle is so important.
If you’re repeating yourself using Tailwind, take a break and think about how to fix that. What is the best approach to solving that? A component, a loop, a utility, using @apply
? Learn how reusing styles can help you avoid this problem.
If you think about copy and paste, just don’t!
Do not run from the configuration complexity
For God’s sake, you are a developer! You’re built for that!
Sass, SCSS, or even creating breaking points manually in simple CSS are not simple either. The sooner you embrace the complexity of those things, the stronger and more skilled you become. And, to be honest, getting started with Tailwind for learning purposes is really easy, and for most cases, just configuring your color scheme should be enough.
Avoid the Unnecessary Use of Markups
One of the principles of writing clean and maintainable code is to avoid the unnecessary use of markups.
Tailwind encourages a utility-first approach, which means you can apply styles directly to your HTML elements without needing additional wrappers or extraneous elements. Keep in mind the number of style classes will increase a lot, so we must be smart regarding the markup structure. This not only keeps your HTML clean but also enhances readability and maintainability.
Unnecessary markups can bloat your HTML, making it harder to read and maintain. By avoiding them, you can ensure your code remains streamlined and efficient. Here are a few tips to help you avoid unnecessary markups:
- Use Tailwind's Utility Classes: Tailwind provides a comprehensive set of utility classes that can be applied directly to HTML elements. This eliminates the need for additional CSS classes or extra HTML elements.
<!-- AVOID: Using extra divs just styling -->
<div class="p-4">
<div class="bg-surface">
<p class="text-center text-primary">Hello, World!</p>
</div>
</div>
<!-- PREFER: Applying utilities directly to the element -->
<p class="p-4 bg-surface text-center text-primary">Hello, World!</p>
- Simplify Your Structure: Evaluate your HTML structure and remove any elements that don’t serve a specific purpose. Each element should have a clear role, whether it’s for semantic structure or styling purposes.
<!-- AVOID: Nested divs without a clear purpose -->
<div class="outer-wrapper">
<div class="inner-wrapper">
<div class="content">
<p class="text-lg">This is a paragraph.</p>
</div>
</div>
</div>
<!-- PREFER: Simplified structure -->
<p class="text-lg">This is a paragraph.</p>
- Use Tailwind’s Flex and Grid Utilities: Tailwind's flex and grid utilities can often eliminate the need for additional containers. By using these utilities, you can create complex layouts with minimal markup.
<!-- AVOID: Using extra containers for layout -->
<div class="container">
<div class="row">
<div class="col">
<p>Item 1</p>
</div>
<div class="col">
<p>Item 2</p>
</div>
</div>
</div>
<!-- PREFER: Using Tailwind's grid utilities and semantic markup -->
<ul class="grid grid-cols-2 gap-4">
<li>Item 1</li>
<li>Item 2</li>
</ul>
By avoiding unnecessary markups, you can keep your codebase clean, reduce complexity, and make your project easier to maintain. This practice, combined with Tailwind's powerful utility-first approach, will enable you to create efficient and scalable designs.
Use the documentation
Tailwind's documentation is one of its greatest strengths.
It is comprehensive, well-organized, and full of examples. Make it a habit to consult the documentation regularly. Whether you’re looking for a specific utility, trying to understand how to customize the configuration, or searching for best practices, the documentation should be your go-to resource.
Think about global changes
It’s a good exercise to find the balance between writing code that is easy to maintain and not worrying about a future that may not come.
Having that in mind, it’s up to you to decide what should be handled globally or not. For example, if you decide to update your brand colors or adjust the spacing scale, what changes will be required? Can you do it in one place, and the changes will propagate throughout your entire project? Tailwind makes it easy to apply global changes through its configuration file. Take advantage of this feature to maintain consistency and manage styles efficiently.
*Be careful on the use of the @apply
.
Otherwise, we’ll just be writing CSS in a different way. That is not the purpose of Tailwind. The magic of this tool is keeping the view and style in the same place, making it easy to understand how it will behave and appear. The appeal of having all the variations, breakpoints, and pseudo-classes directly in HTML facilitates understanding what is going on, centralizing all the view core changes in one place. That is priceless!
I know, I know… I’ve been talking about good practices and principles until now, and suddenly I’m talking about having the view and style in the same place.
It might sound nonsensical, breaking the separation of concerns principle, but I’d like to propose a reflection here. Should we always follow the principles? Do they always make sense? What about when the paradigm changes? And about evolution? Are those principles still valid nowadays, for the current technologies?
In my personal opinion, based on the code I’ve written, having all the aspects of the view in the same place is a good thing, especially because style doesn’t work without the view. It’s not like a data layer that works alone as a data provider and can be used for multiple applications. The only reason the styling exists is the view.
Looking across CSS files to find which styles apply to the view and must be updated can be a tricky task. But for years, no better way of doing that was available, and keeping those separate was by far the best option. But using Tailwind, it’s not required anymore. I think, maybe, keeping those together can be the modern way.
Anyway, I’m just a guy from Brazil, sharing a few thoughts… Let me know what you think about it.
Top comments (5)
Great post! Your tips for enhancing Tailwind CSS skills are both practical and insightful. The advice on customizing the color palette, creating reusable utilities, and avoiding unnecessary markup is crucial for maintaining clean and efficient code. Your explanations make these concepts easy to understand.
This article is a fantastic resource for anyone looking to master Tailwind CSS. Keep up the good work!
Antonio, CEO & Founder at Litlyx.com
I think this is a great, well thought-out response :)
Didn't know about the section related to creating custom utilities with @apply.
Thanks for explaining that! 🚀
It's really helpful to see a detailed breakdown, Thank you!