top of page

A look into Tailwind

Writer's picture: Leon MekaLeon Meka

Updated: Oct 11, 2024

If you are a web developer, you probably have a decent amount of experience with styling using CSS. Maybe you also came across some form of preprocessor framework like LESS or SASS, which effectively allow you to extend your styling toolset with additional features like variables, mixins, functions, or nesting. Frontend development really is a fast pace environment where additional tooling and frameworks popup ever so often.

Today’s cool kid on the block is Tailwind CSS – A rising star in the frontend dev ecosystem, which comes with an interesting approach on declaring your styles. In this article, we’ll take a closer look at the utility-first framework and showcase some of its most popular UI implementations.


What is Tailwind?

Tailwind is a utility-first CSS framework that enables developers to build modern websites within HTML. To understand what this means, we’ll need to take a look at how we usually define styling. Traditional CSS involves writing custom stylesheets where styles are defined in a separate file and then applied to HTML elements via their tag name, classes or IDs. This is where Tailwind takes a different approach.


Example of some Tailwind-infused markup
Example of some Tailwind-infused markup

 

In essence, Tailwind exposes a bunch of primitive utility classes that can be combined to create more complex designs directly in your markup. For instance, classes like p-4, text-center, and bg-blue-500 apply padding, text alignment, and background color respectively.


“So… inline-styling with extra steps? Isn’t the whole point to separate markup and styling?"


At first glance, Tailwind might seem like it's reintroducing inline styles by embedding styling directly in the markup. This approach appears to contradict the traditional best practice of separating markup from styling. However, there are several compelling reasons why Tailwind's utility-first approach can be more advantageous compared to traditional methods:

Fast Iterations – Utility classes enable developers to style elements directly within their HTML, reducing the need to switch contexts between HTML and CSS files. This rapid development process is particularly beneficial for prototyping or building user interfaces quickly. By leveraging a comprehensive set of pre-defined utility classes, developers can minimize custom CSS, speeding up initial development and reducing the maintenance burden of managing large CSS files.

Consistency – utility classes enforce a consistent design language across an application. Using the same classes repeatedly minimizes unintentional design variations, especially when multiple developers are involved. Tailwind’s config file acts as a centralized location for all design-related settings, ensuring that changes propagate uniformly across the entire application.

Natural Scoping – utility-first CSS simplifies refactoring styles. Changing the appearance of an element involves updating the utility classes directly in the HTML, eliminating the need to modify CSS selectors scattered across multiple files. Additionally, Tailwind’s approach naturally scopes styles to individual components or elements, reducing the risk of unintended side effects common in traditional CSS.

Performance - Tailwind includes only the utility classes actually used in your HTML during the build process. This purging results in smaller CSS files and faster load times, enhancing overall website performance. By avoiding large, monolithic CSS files that include styles for every possible scenario, Tailwind ensures that the final CSS is lean and efficient.

Additionally, Tailwind offers a load of additional functionalities, that allow you to extend its capabilities (see functions & directives, responsive design, state-conditionals & vendor prefixes).


How does it work under the hood?

As mentioned, the majority of what Tailwind does, boils down to providing short-form classes, which abstracts away the need to actually write proper CSS. For this to work, Tailwind generates a comprehensive CSS file that includes all possible utility classes. This file can be quite large, but it ensures that all potential styles are available. Note that this is only needed during development.

For production builds, Tailwind employs a process called "purging", which specifically tries to not do that. Behind the scenes, Tailwind uses PurgeCSS to optimize your code:

  • Scanning Files: PurgeCSS scans all files specified in the configuration (typically HTML, JS, JSX, etc.) to collect a list of classes.

  • Generating Final CSS: Only the styles for the used classes are included in the final CSS build, significantly reducing the file size and improving performance.


Tailwind Configuration

Tailwind’s core configuration is handled through a dedicated config file (typically tailwind.config.js). This file allows developers to customize the framework to fit their needs by defining various aspects such as:

  • Colors: Custom color palettes can be defined, ensuring a consistent color scheme throughout the project.

  • Spacing: Custom spacing scales for padding, margin, and gap can be set.

  • Fonts: Custom fonts and font sizes can be configured.

  • Screens: Responsive breakpoints can be customized to fit the specific needs of the project.

  • Plugins: Additional functionality can be added through community or custom plugins.

  • and much more…

This file essentially serves as the single source of truth for anything styling-related in a codebase, ensuring consistency across your project.


Check it out

In case this sparked your interest, go ahead and try it out yourself by following the Tailwind installation guide. If you can’t be bothered to do all that, here is a minimal react-based codesandbox to play around with.


UI libraries and implementations

Although Tailwind itself already offers a great variety of benefits, you might be interested in still using ready-made components or at least a more opinionated approach on guiding you during development. Following, we’ll take a look at two open-source examples, which serve as a great starting point to dig deeper into some of options available.


Headless UI: Optimizing Web Performance

Headless UI, developed by the creators of Tailwind, offers a collection of completely unstyled, fully accessible UI components designed to integrate with Tailwind. The primary advantage of Headless UI is its focus on accessibility and performance optimization.

To get started with Headless UI, you can install it via npm:


npm install @headlessui/react@latest

Similiar to other component libraries, you can import components and directly use them in your regular components:


import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'
export default function AccountMenu() {
  return (
    <Menu>
      <MenuButton>My account</MenuButton>
      <MenuItems anchor="bottom">
        <MenuItem>
          <a className="block data-[focus]:bg-blue-100" href="/settings">
            Settings
          </a>
        </MenuItem>
        <MenuItem>
          <a className="block data-[focus]:bg-blue-100" href="/support">
            Support
          </a>
        </MenuItem>
        <MenuItem>
          <a className="block data-[focus]:bg-blue-100" href="/license">
            License
          </a>
        </MenuItem>
      </MenuItems>
    </Menu>
  )
}

Note that although this example is suggesting a react-based environment, Headless UI is also available for Vue.js.

Here are a few benefits of using Headless UI:

  • Unstyled Components: Since Headless UI components are unstyled, they offer complete flexibility to style them according to your design system.

  • Accessibility: Headless UI prioritizes accessibility, ensuring that components are compliant with ARIA standards and work well with screen readers.

  • Integration with Tailwind: The components are designed to work out-of-the-box with Tailwind, allowing you to leverage the full power of utility-first styling.

Headless UI includes a variety of components such as dialog boxes, dropdowns, modals, and tabs. By providing the basic functionality and leaving the styling up to the developer, Headless UI ensures that you can maintain a consistent design language throughout your application, while benefiting from accessibility best practices at the same time.


shadcn/ui: A Minimalist Approach to UI Components

shadcn/ui is a relatively new player in the Tailwind landscape, quickly gaining popularity for its minimalist and reusable components. What sets shadcn/ui apart is its unique approach to component usage.

Unlike traditional component libraries, which are installed as dependencies, shadcn/ui components are copied directly into your project. To make this process a bit more comfortable, it offers short CLI snippets that do all of that for you:


npx shadcn-ui@latest add button

Next, you can import components from a dedicated folder and use it in other component or page:


import { Button } from "@/components/ui/button"
export default function Counter() {
  const [count, setCount] = useState(0)
  return (
    <div>
      <p>You clicked {count} times</p>
      <Button onClick={() => setCount(count + 1)}>Click me</Button>
    </div>
  )
}

Apart from its ease of integration, shadcn/ui offers the following benefits:

  • Minimal Styling: shadcn/ui is built on top of radix ui and implements minimal custom styling for its underlying components.

  • Integration with Tailwind: Again, fully integrated with Tailwind, to allow direct modifications using utility classes.

  • Customizable Theming: It supports theming with CSS variables or utility classes, making it easy to adapt the look and feel of the components to your project's design.

  • Framework Support: shadcn/UI is versatile, supporting various frameworks including Next.js, Astro, and Vite. Take a look at there documentation to learn more.

  • Comprehensive Figma UI Kit: Designers can use the Figma UI kit to create and visualize designs before implementation.


Takeaway

Tailwind's approach changes the way we write CSS, offering efficiency, consistency, and flexibility. By integrating styling directly within your markup through utility classes, Tailwind eliminates the need for extensive custom CSS, allowing for faster development cycles and easier maintenance.

For developers seeking ready-made components while maintaining design flexibility, libraries like Headless UI and shadcn/ui offer a repository of beautiful, accessible, and easily integrated components. Both complement Tailwind's philosophy by providing functional components that can be styled to fit any design system, enhancing the overall development workflow.


---


Resources

66 views

Recent Posts

See All

Comments


bottom of page