DEV Community

Kalimah Apps
Kalimah Apps

Posted on

Increase tailwind classes readability with this eslint plugin

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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 Tailwind Plugin

Provide eslint rules for tailwindcss





Rules

  • @kalimahapps/tailwind/tailwind-sort: Sort tailwind classes in alphabetical order in groups
  • @kalimahapps/tailwind/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
Enter fullscreen mode Exit fullscreen mode

NPM

npm install eslint @kalimahapps/eslint-plugin-tailwind -D
Enter fullscreen mode Exit fullscreen mode


🔧 Usage

Add this to your .eslintrc.js file

module.exports = {
 "plugins": ["@kalimahapps/eslint-plugin-tailwind"],
 "rules": {
    "@kalimahapps/tailwind/sort": "warn",
    "@kalimahapps/tailwind/multiline": "warn"
    }
}
Enter fullscreen mode Exit fullscreen mode

You can apply maxLen rule to tailwind classes by adding this to your .eslintrc.js file

module.exports = {
 "plugins": ["@kalimahapps/eslint-plugin-tailwind"],
 "rules": {
    "@kalimahapps/tailwind/sort": "warn",
    "@kalimahapps/tailwind/multiline": [
        "warn",
        {
            "maxLen": 100
        }
    ]
    }
}
Enter fullscreen mode Exit fullscreen mode

To enable automatic formatting add this to your .vscode/settings.json file

{
    "prettier.enable": false
    "editor.formatOnSave": false,
    "eslint.codeAction.showDocumentation":
Enter fullscreen mode Exit fullscreen mode

👥 Connect
Twitter: @kalimahapps

Top comments (7)

Collapse
 
vincentdorian profile image
Vincent

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?

Collapse
 
kalimahapps profile image
Kalimah Apps

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.

Collapse
 
oliyg profile image
OliverYoung

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.

Collapse
 
kalimahapps profile image
Kalimah Apps

Hard in what sense? It does not change the structure of html

Collapse
 
oliyg profile image
OliverYoung

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.

Thread Thread
 
kalimahapps profile image
Kalimah Apps

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.

Thread Thread
 
oliyg profile image
OliverYoung

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.