ExtJS and Tailwind CSS

Luca Minuti - Oct 14 - - Dev Community

Over the past few months, I've been using Tailwind for some WebApp projects not related to ExtJS. Tailwind is a framework very different from Bootstrap or similar products. In fact, it uses a utility-first approach where CSS classes are linked to functionalities rather than components.

How Tailwind CSS Works

To try to clarify the concept a bit, I'll use the same example from the official website.

Let's take this component:

Simple web page

Using a traditional approach, we would need to use code like this:

<div class="chat-notification">
  <div class="chat-notification-logo-wrapper">
    <img class="chat-notification-logo" src="/img/logo.svg" alt="ChitChat Logo">
  </div>
  <div class="chat-notification-content">
    <h4 class="chat-notification-title">ChitChat</h4>
    <p class="chat-notification-message">You have a new message!</p>
  </div>
</div>

<style>
  .chat-notification {
    display: flex;
    align-items: center;
    max-width: 24rem;
    margin: 0 auto;
    padding: 1.5rem;
    border-radius: 0.5rem;
    background-color: #fff;
    box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
  }
  .chat-notification-logo-wrapper {
    flex-shrink: 0;
  }
  .chat-notification-logo {
    height: 3rem;
    width: 3rem;
  }
  .chat-notification-content {
    margin-left: 1.5rem;
  }
  .chat-notification-title {
    color: #1a202c;
    font-size: 1.25rem;
    line-height: 1.25;
  }
  .chat-notification-message {
    color: #718096;
    font-size: 1rem;
    line-height: 1.5;
  }
</style>
Enter fullscreen mode Exit fullscreen mode

With Tailwind, however, something like this is enough:

<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4">
  <div class="shrink-0">
    <img class="size-12" src="/img/logo.svg" alt="ChitChat Logo">
  </div>
  <div>
    <div class="text-xl font-medium text-black">ChitChat</div>
    <p class="text-slate-500">You have a new message!</p>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

The purpose of this article is not to go into the details of how Tailwind works, but even at first glance, what we see is the difference in size of the code block, but also a series of horrible CSS classes.

Personally, I'm used to give classes a name that help me understand their meaning (button, card, grid, column, ...), and this certainly makes it easier to read the HTML code; in some way, it's like adding comments to the code. Instead, with Tailwind, the classes refer to a single specific aspect to assign to HTML tags. For each tag it's often necessary to insert more than one class, making the whole thing particularly complex.

The big advantage is that you practically don't write CSS anymore and use almost only Tailwind classes. In this way, besides not wasting time inventing class names, often even bizarre ones (item-inner-column-wrapper, etc.), you use conventions that help the site be more homogeneous and coherent.

Moreover Tailwind has a whole series of interesting features for supporting responsive sites, creating custom themes, dark mode, a plethora of plugins, and much more. For this refer to the official guide.

Tailwind and ExtJS

When some time ago I resumed an ExtJS project and found myself writing complex templates, with CSS classes and many styles, I realized I missed Tailwind. Let's take an example:

    items: [{
        xtype: 'list',
        store: ...,
        itemTpl: 
            '<div class="list-item">' +
                '<div class="item-icon {iconCls}"></div>' +
                '<div class="list-item-data">' +
                    '<div class="list-item-name">{name}</div>' +
                    '<div class="list-item-detail">{detail}</div>' +
                '</div>' +
            '</div>'
    }]

Enter fullscreen mode Exit fullscreen mode

with its CSS:


.list-item {
    display: flex; 
    align-items: center;
    padding: 4px;
}

.list-item-data {
    display: flex; 
    flex-direction: column;
}

.list-item-name {
    font-size: 18px;
}

.list-item-detail {
    font-style: italic;
}

Enter fullscreen mode Exit fullscreen mode

With Tailwind, the following code is enough without even touching the CSS files:

    items: [{
        xtype: 'list',
        store: ...,
        itemTpl: 
            '<div class="flex items-center p-1">' +
                '<div class="item-icon {iconCls}"></div>' +
                '<div class="flex flex-col">' +
                    '<div class="text-lg">{name}</div>' +
                    '<div class="italic">{detail}</div>' +
                '</div>' +
            '</div>'
    }]
Enter fullscreen mode Exit fullscreen mode

Configuration

Using Tailwind with ExtJS is quite simple because in the end, what the engine does is scan all our code looking for Tailwind classes (flex, grid, text-lg, p-1, p-2, etc.) and generate a CSS file containing only the classes we've used. If you use the new Open tooling based on npm, you can follow Tailwind's installation guide. Otherwise, if you use SenchaCmd, the simplest thing to do is to download the CLI from here.

With this new CLI installed, you can initialize Tailwind by going to the root directory of your project and write:

# Create a tailwind.config.js file
./tailwindcss init
Enter fullscreen mode Exit fullscreen mode

This will create the tailwind.config.js file. I changed it like this, but of course, it depends on your application:

/** @type {import('tailwindcss').Config} */
module.exports = {
    content: ['./app/**/*.{html,js}','./index.html'],
    // Remove all corePlugins
    corePlugins: {
      preflight: false,
    },
    // Remove all preset
    //presets: [],
    theme: {
        extend: {
          boxShadow: {
            'outline': '2px 2px 8px 0 rgba(0, 0, 0, 0.4)',
          }
        },
    },
    plugins: [],
};
Enter fullscreen mode Exit fullscreen mode

The content option is the most important, where you must define the directories that Tailwind will scan to find CSS classes. With the corePlugins and plugins configuration, I removed all plugins to generate the lightest possible CSS. Finally, I added a customization to the theme to generate a new shadow-outline class with the specified configuration. If you will, you could remove the standard presets, but then some classes wouldn't work.

Then we can use the CLI again to generate the classes:

tailwindcss -o sass\src\tailwind.css --watch
Enter fullscreen mode Exit fullscreen mode

With this command, Tailwind will constantly check the files specified in the configuration and generate the classes in the sass\src\tailwind.css file. Finally we have to tell ExtJS to use that CSS file. We need to modify the application configuration in the scss section of the app.json file:

    "sass": {
        ...
        "src": [
            "sass/src",
            "sass/src/tailwind.css"
        ]
    ]
Enter fullscreen mode Exit fullscreen mode

Optionally, you can automate the creation of CSS during the production build by adding the following code to your build.xml file:

    <target name="-before-build">
        <if>
            <equals arg1="production" arg2="${build.environment}"/>
            <then>
                <x-echo message="Build CSS with Tailwind"/>
                <exec executable="tailwindcss">
                    <arg value="-o"/>
                    <arg value="sass\src\tailwind.css"/>
                </exec>
            </then>
        </if>

    </target>

Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . .