Skip to Main Content

Apr 13, 2023 | 9 minute read

TailwindCSS is a Great Fit for Composable

written by James Luterek

Composable architectures offer many benefits, including improved scalability, flexibility, and maintainability. But building an attractive and maintainable UI can be a challenging task, requiring careful consideration of various design principles and the ability to easily reuse and combine components. That's where TailwindCSS comes in. This popular CSS framework provides a utility-first approach to building custom user interfaces, making it an excellent fit for composable. In this article, we’ll get you started on working with Tailwind with a simple development environment that includes hot reloading and finish with an open-source ecommerce template.

The Challenges of CSS

Before CSS all style information was embedded directly in the HTML with style centric tags like <font>, <i>, and <b>. CSS changed the game allowing a separation of presentation and markup and is now the best approach to providing a way to style and layout HTML content. The original approach was built with cascading in mind and a push for semantic HTML.

One of the key challenges of CSS is the need to write and maintain custom styles for every element in a project. This can quickly become an unwieldy task, especially as the number of elements and variations increases. Developers must often create an enormous amount of class names and manage complex class hierarchies to achieve the desired look and feel of their UI.

Another issue with traditional CSS is that it can be difficult to maintain consistency across a project, especially as the number of developers and teams involved increases. Without a standardized approach to styling and layout, developers can easily end up with conflicting styles and a lack of overall coherence in the UI.

These problems gave rise to CSS frameworks with popular options including Bootstrap and Foundation. These frameworks provided the necessary CSS classes to build robust user experiences. They followed the semantic approach offering pre-defined components. So, developers would simply need to add the class PrimaryButton and have a consistent button style across the entire application.

While being a huge boost from writing all CSS from scratch, overriding the default styles was difficult, resulting in many bootstrap websites looking similar. People could quickly identify the “Bootstrap style”. In addition, the goal of separating CSS from HTML was never fully realized as these components required specific HTML to work properly, often with complex nested elements.

The TailwindCSS Approach

TailwindCSS takes a vastly different approach to styling. Rather than relying on pre-built components and complex class hierarchies, TailwindCSS provides a robust set of utilities. So instead of using a semantic component class like PrimaryButton or writing custom CSS for every element in a project, developers use a set of pre-defined utility classes to style and layout their UI.

For example, instead of creating a custom CSS class to set the font size of a text element, a developer using TailwindCSS might apply the text-lg utility class to achieve the same effect. Similarly, instead of writing a custom class to set the margin of an element, a developer might use the m-4 utility class to add a margin.

This approach has several advantages, including:

  • Faster development: By using pre-defined utility classes, developers can style and layout their UI more quickly, without having to write custom CSS for every element.
  • Easier maintenance: Because TailwindCSS provides a standardized set of utility classes, it's easier to maintain consistency across a project and ensure that the UI remains coherent as it evolves.
  • Greater flexibility: By combining and reusing utility classes, developers can achieve a wide variety of styles and layouts, making it easier to build and maintain complex UIs with composable architectures.

Many detractors for utility-first CSS make the argument that having a bunch of these classes is fundamentally the same as just embedding styles directly into the HTML. This fails to recognize the benefit of having a well-defined subset of styles that were well built and curated by a team of designers. It also fails to consider the current trend in development towards SPAs, PWAs, and Transitional Apps.

Viewing the HTML alone it feels as though these classes are constantly repeated and that each time you need to build a button you need to remember a lengthy list of utility classes. This may be true if you were building a website with traditional techniques, but in a modern composable world companies are adopting JavaScript frameworks like ReactJS, VueJS, and Svelte that take a component approach. With these frameworks you will make a button component and as a result that specific list of utility classes will only exist in that JavaScript component and the code can be re-used across the application.

Get hands on with an Elastic Path Free Trial

Start building the commerce experience your unique business demands with a free Elastic Path Commerce Cloud account. Get in touch with us and we will setup a Free Trial store for you for six weeks.

Example Utility Classes

Here are a few examples of the many utility classes provided by Tailwind. By combining and reusing these classes, developers can quickly and easily build custom UIs.

  1. Spacing: TailwindCSS provides a range of utility classes for setting margin and padding values, including m- and p- classes for setting margin and padding, as well as mt-, mr-, mb-, ml-, pt-, pr-, pb-, and pl- classes for setting specific sides of an element.
  2. Typography: TailwindCSS provides a wide range of utility classes for setting typography, including text- classes for setting font size, font weight, line height, and more, as well as font- classes for setting font family and leading- classes for setting line height.
  3. Layout: TailwindCSS provides a range of utility classes for setting layout properties, including flex- and grid- classes for building flexible and grid-based layouts, as well as float-, clear-, and object- classes for setting float, clear, and object properties.
  4. Colors: TailwindCSS provides a comprehensive set of utility classes for setting colors, including bg- and text- classes for setting background and text colors, as well as border- and divide- classes for setting border and divider colors.
  5. Effects: TailwindCSS also provides a range of utility classes for adding visual effects to elements, including hover:, focus:, and active: classes for setting styles on specific states, as well as transition- classes for controlling transitions and opacity- classes for setting opacity.

Getting Started

There are plenty of options in the Tailwind documentation to get you started from their own CLI to embedding Tailwind in a front-end application. Here we will discuss how to set up a local development environment for building HTML templates with Tailwind. It will include a local server along with hot reloading as content changes.

In your bash shell start by creating a new project:

$ mkdir tailwind-template

$ cd tailwind-template

$ npm init

Follow the NPM prompts to create your project allowing us to then install Tailwind and the other necessary NPM packages.

Install tailwindcss, postcss, and autoprefixer for CSS workflow. We will also install five-server for a local development server and concurrently to help with running the tools.

$ npm install -D tailwindcss postcss autoprefixer five-server concurrently

Next initialize Tailwind

$ npx tailwindcss init

Then configure postcss by modifying the postcss.config.js file as follows:

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  }
}

Next, configure tailwind.config.js file and ensure it is looking for any HTML files. Tailwind will selectively include classes based on what is used within your HTML code.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./**/*.{html,js}"],
  theme: {
    extend: {},
  },
  plugins: [],
}

Finally, let’s add some scripts to the package.json to help with building and running the template: 

"scripts": {
    "build:css": "tailwindcss -i ./src/main.css -o ./dist/main.css -w",
    "serve": "five-server",
    "start": "concurrently \"npm run build:css\" \"npm run serve\""
  },

The build css script will execute just the tailwind CLI. This will watch the specified CSS files and build it to the output based on the tailwind configuration. The serve script will run the local web server. The start script will run both the tailwind CLI and local web server concurrently.

$ npm run build:css

$ npm run serve

$ npm run start

We can now start building out our code. We will start by creating our CSS file in /src/main.css and adding the code:

@tailwind base;
@tailwind components;
@tailwind utilities

Now we can create an index.html file and start using TailwindCSS.

<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="/dist/main.css" rel="stylesheet">
</head>
<body>
  <h1 class="text-3xl font-bold underline">
    Hello world!
  </h1>
</body>
</html>

You will notice that the html code points to the dist folder, this is where the final CSS output will be. Now we can run everything and preview the results.

npm run start

Your browser should open running localhost. When files are edited and saved the website will update with the new content.

Ecommerce Template

To help you get up and running fast, you can find all of the code from this tutorial as well as an open-source TailwindCSS Ecommerce template on GitHub. This template includes some basic layouts and pages that you can leverage for your next commerce website.

Elastic Path Commerce Cloud makes the perfect backend for the website. If you would rather theme an existing project please checkout the Elastic Path Composable Frontend or get in touch for more information.