Tailwind is a popular utility-first CSS framework that has gained significant traction in recent years. It is a highly customizable and easy-to-use framework that can help developers streamline their workflow and create visually appealing websites with less code.
One of the biggest advantages of using Tailwind is that it streamlines the development process. The framework provides a set of pre-defined classes that developers can use to style their HTML elements. This eliminates the need to write custom CSS for every single element on the website, saving a significant amount of time and effort.
With such large amounts of pre-defined classes, sometimes it can be difficult to read and understand at first glance how a particular element is styled.
Let's look at this example (taken from flowbite):
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" value="" class="sr-only peer">
<div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"></div>
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">Toggle me</span>
</label>
This is a checkbox that has been styled using Tailwind. It is a single line of code that contains a lot of information. It is not immediately clear how the checkbox is styled.
This is why I developed an eslint plugin that helps developers to better understand how Tailwind classes are being used in their code. The plugin is called @kalimahapps/eslint-plugin-tailwind and it is available on npm. Currently, it has two rules.
tailwind-multiline
With this rule, you can enforce that Tailwind classes are written on multiple lines once they exceed a certain number of characters. This makes it easier to read and understand how the element is styled.
Let's see how the above example would look like with this rule enabled:
<label class="relative inline-flex items-center cursor-pointer">
<input type="checkbox" value="" class="sr-only peer">
<div
class="w-11
h-6
bg-gray-200
peer-focus:outline-none
peer-focus:ring-4
peer-focus:ring-blue-300
dark:peer-focus:ring-blue-800
rounded-full
peer
dark:bg-gray-700
peer-checked:after:translate-x-full
peer-checked:after:border-white
after:content-['']
after:absolute
after:top-[2px]
after:left-[2px]
after:bg-white
after:border-gray-300
after:border
after:rounded-full
after:h-5
after:w-5
after:transition-all
dark:border-gray-600
peer-checked:bg-blue-600"
/>
<span class="ml-3 text-sm font-medium text-gray-900 dark:text-gray-300">Toggle me</span>
</label>
As you can see, the classes are now written on multiple lines and from first glance you can identify which classes are being used to style the element.
tailwind-sort
This is the other rule that is included in the plugin. It helps developers to sort the Tailwind classes in a consistent manner. While tailwind provides a prettier plugin to sort the classes, I found it unintuitive and not very useful. The classes in the base layer will be sorted first, followed by the classes in the components layer, and finally the classes in the utilities layer.
This rule, however, sorts classes alphabetically but in groups. For example, it makes sense that bg-sky-500
and dark:bg-sky-100
are grouped together. This is because they are both background colors. The same goes for text-sky-500
and dark:text-sky-100
.
Let's see how the above example would look like with this rule enabled:
<label class="cursor-pointer inline-flex items-center relative">
<input type="checkbox" value="" class="peer sr-only">
<div
class="bg-gray-200
after:bg-white
dark:bg-gray-700
h-6
after:h-5
peer
dark:peer-focus:ring-blue-800
peer-checked:after:border-white
peer-checked:after:translate-x-full
peer-checked:bg-blue-600
peer-focus:outline-none
peer-focus:ring-4
peer-focus:ring-blue-300
rounded-full
after:rounded-full
w-11
after:w-5
after:absolute
after:border
after:border-gray-300
after:content-['']
after:left-[2px]
after:top-[2px]
after:transition-all
dark:border-gray-600"
/>
<span class="font-medium ml-3 text-gray-900 dark:text-gray-300 text-sm">Toggle me</span>
</label>
I think this is a much more readable and understandable way to write Tailwind classes.
Install and Usage
Currently, the package only works for vue projects. To install and use this plugin in your project checkout readme file:
kalimahapps / eslint-plugin-tailwind
ESLint plugin to sort tailwind classes
KalimahApps Eslint Tailwind Plugin
Provide eslint rules for tailwindcss
β¨ Rules
-
tailwind-sort
: Sort tailwind classes in alphabetical order in groups -
tailwind-multiline
: Break tailwind classes into multiple lines if they exceed the max line length (default: 80)
π½ Installation
PNPM
pnpm add eslint @kalimahapps/eslint-plugin-tailwind -D
NPM
npm install eslint @kalimahapps/eslint-plugin-tailwind -D
π§ Usage
Create eslint.config.js file (or eslint.config.mjs for esm, or eslint.config.cjs for commonjs) in the root of your project and add this
import kalimahAppsTailwind from '@kalimahapps/eslint-plugin-tailwind';
export default [
{
plugins: {
kalimahAppsTailwind,
},
rules: {
'kalimahAppsTailwind/sort': 'warn',
'kalimahAppsTailwind/multiline': 'warn',
},
},
]
The following options can be set to the mutiline rule:
-
maxLen
: break classes as soon as the line length is longer than this (and join if the line is smaller) -
quotesOnNewLine
: put the quotes on different lines to the first and lastβ¦
π₯ Connect
Twitter: @kalimahapps
Top comments (7)
Improving readability of tailwind classes is really nice, but don't you think that this adds too many lines of code and makes your files too bulky?
I guess it comes down to personal choice. Working with a utility-first framework means that you will write many classes (either horizontally or vertically). For me, I prefer the latter. It is a trade-off I am willing to accept given the benefit I get (classes being more readable).
I developed these ESLint rules out of frustration in one of my projects because I had to scroll back and forth to remember what classes I have added to debug a problem.
If you are using VSCode you can check out this extension:
marketplace.visualstudio.com/items...
It helps hiding the classes while reading the file which greatly improve readability of the code overall but not tailwind classes. The other downside is that you need to use VSCode for it work. If you want to review a git log then it will not be as easy to read.
Maybe itβs easier to read style but it cause another problem that I find it really hard to get the structure of html. I have tried and I donβt like it.
Hard in what sense? It does not change the structure of html
It's too long and most of the time I need multiple lines. So why not just give it a scoped classname, it will make my html cleaner.
I thought you are referring to the plugin not Tailwind. I have to say that I shared your opinion before I started using tailwind but after researching a bit and in particular reading this article (by the creator of tailwind) adamwathan.me/css-utility-classes-... I switched. And I have to say it was a very good decision for me.
It works best if you have a build process in your project. So if you are using vue, react .. etc with node it works very well.
At the end of the day, we should not focus on the technology but the project requirements.
Really good article. I have to admit, there are some advantages I really enjoy.
I don't need to come up with a name, I can focus on the style itself. It forces me to create a usable component when I try to write multiples of the same class name, which is a great way to force me to write reusable CSS styles. Before reading this article I thought it was the same as inline-style, but now I realize that arbitrary values are not recommended and we should use the value from the list.
But I'm finding it hard to inspect elements, since the elements don't have it's name.
Or I should try a few more times, maybe I'm just not familiar with the class names or didn't define tailwind.config.js carefully.