knowledge-kitchen

Tailwind CSS - The Modern Utility-First Front-End Framework (No Slides, Please)

This document has been autogenerated from slides.


modern, utility-first styling for the web

  1. Front-End Frameworks
  2. Tailwind Overview
  3. Installation
  4. Utility-First Styling
  5. Separation of Concerns?
  6. Responsive Design
  7. Flex & Grid Layout
  8. Customization
  9. Interactive Components with Alpine.js
  10. Conclusions

Front-End Frameworks

Concept

Front-end frameworks, of which Tailwind CSS is one, are toolkits that help web developers create the front-end - the visible user interfaces of web pages and applications.

Two flavors

Front-end frameworks generally fall into one of two categories.

Tailwind Overview

Evolution

Tailwind CSS was first released by Adam Wathan in 2017 as a reaction to the limitations of component-based frameworks like Bootstrap.

Concept

Tailwind CSS is a free collection of small, single-purpose CSS classes for building websites and web applications. It contains …

Installation

The easy way: the Play CDN

Unlike many modern tools, Tailwind CSS can be added to a web page with a single line of code - no terminal commands, no installations, no setup files.

<script src="https://cdn.tailwindcss.com"></script>

A complete starter file

Here is a complete, working HTML file that uses Tailwind CSS:

<!DOCTYPE html>
<html>
  <head>
    <title>My Tailwind Page</title>
    <!-- Link to the Tailwind CSS Play CDN -->
    <script src="https://cdn.tailwindcss.com"></script>
  </head>
  <body>
    <h1 class="text-3xl font-bold text-blue-600">Hello, Tailwind!</h1>
  </body>
</html>

Customization

You can still write your own CSS code alongside Tailwind whenever you want.

<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" type="text/css" href="css/custom.css" />

Utility-First Styling

Concept

Instead of writing CSS in a separate stylesheet, with Tailwind you style elements directly by adding utility classes to them in your HTML.

<button class="bg-blue-500 text-white p-4 rounded-lg">Click me!</button>

Common utilities

A small sampling of the most useful Tailwind utility classes:

Separation of Concerns?

The traditional principle

In the traditional approach to web architecture, we are taught that the three core front-end technologies each have a distinct purpose:

Tailwind appears to break the rule

At first glance, Tailwind looks like it violates the separation of concerns principle.

<!-- Traditional approach -->
<button class="primary-action">Sign up</button>

<style>
  .primary-action {
    background-color: blue;
    color: white;
    padding: 1rem;
    border-radius: 0.5rem;
  }
</style>
<!-- Tailwind approach -->
<button class="bg-blue-500 text-white p-4 rounded-lg">Sign up</button>

Tailwind’s counter-argument

The creators of Tailwind argue that the traditional view misunderstands what “separation of concerns” really means.

A different kind of separation

Tailwind proposes a different boundary line between concerns:

Honest tradeoffs

Neither approach is universally “correct.” Each has real benefits and real costs.

Advantages of utility-first (Tailwind):

Advantages of separated CSS (traditional):

Responsive Design

Concept

Tailwind makes responsive design easy by letting you add a prefix to any utility class so that it only applies at certain browser widths.

The prefixes correspond to the following breakpoints:

Usage

For example, the following heading will be small on phones, larger on tablets, and largest on desktops.

<h1 class="text-xl md:text-3xl lg:text-5xl">
  This heading grows with the screen!
</h1>
<div class="bg-red-200 md:bg-green-200 lg:bg-blue-200">
  Background color changes with the screen size.
</div>

Flex & Grid Layout

Concept

Tailwind provides utility classes for both flexbox and CSS grid - the two modern ways to lay out elements on a page.

Flexbox

Flexbox is great for arranging elements in a single row or column.

<div class="flex gap-4">
  <article class="flex-1">First article</article>
  <article class="flex-1">Second article</article>
</div>
<div class="flex flex-col md:flex-row gap-4">
  <article class="flex-1">First article</article>
  <article class="flex-1">Second article</article>
</div>

Grid

For more complex layouts with rows and columns, use Tailwind’s grid utilities.

<div class="grid grid-cols-12 gap-4">
  <article class="col-span-6">First article</article>
  <article class="col-span-6">Second article</article>
</div>
<div class="grid grid-cols-12 gap-4">
  <article class="col-span-12 md:col-span-6">First article</article>
  <article class="col-span-12 md:col-span-6">Second article</article>
</div>

Centering content

A common task is centering content horizontally on the page. Tailwind makes this easy:

<body>
  <div class="max-w-4xl mx-auto p-4">
    <h1>My page content</h1>
    <p>Everything inside this div is centered with a maximum width.</p>
  </div>
</body>

Interactivity & Customization

State prefixes

Tailwind makes it easy to change an element’s style when the user interacts with it, again by using a prefix on a utility class.

<button class="bg-blue-500 hover:bg-blue-700 text-white p-4 rounded">
  Hover over me!
</button>

Going beyond the defaults

Tailwind comes with sensible default colors, spacing values, and font sizes - but you can use any value you like by putting it in square brackets.

<div class="bg-[#abcdef] w-[37px] text-[22px]">
  Custom values for color, width, and font size.
</div>

Interactive Components with Alpine.js

Concept

Tailwind itself ships no JavaScript - it is purely a CSS framework. To build rich interactive components like modals, dropdowns, accordions, and carousels, the Tailwind community standardly pairs Tailwind with Alpine.js.

Installation

Just like Tailwind, Alpine.js can be added to a web page with a single line of code - no terminal commands, no installations, no setup files.

<!DOCTYPE html>
<html>
  <head>
    <title>My Tailwind + Alpine Page</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script defer src="https://unpkg.com/alpinejs"></script>
  </head>
  <body>
    <!-- Your interactive components go here -->
  </body>
</html>

Alpine basics

Just three core “directives” (special HTML attributes) are enough to build most interactive components:

Example: Dropdown menu

A button that toggles a dropdown menu open and closed.

<div x-data="{ open: false }" class="relative inline-block">
  <button
    @click="open = !open"
    class="bg-blue-500 text-white px-4 py-2 rounded"
  >
    Menu
  </button>
  <div
    x-show="open"
    @click.outside="open = false"
    class="absolute mt-2 bg-white shadow-lg rounded p-2"
  >
    <a href="#" class="block px-4 py-2 hover:bg-gray-100">Home</a>
    <a href="#" class="block px-4 py-2 hover:bg-gray-100">About</a>
    <a href="#" class="block px-4 py-2 hover:bg-gray-100">Contact</a>
  </div>
</div>

Example: Modal dialog

A pop-up dialog with a dimmed backdrop.

<div x-data="{ open: false }">
  <button @click="open = true" class="bg-blue-500 text-white px-4 py-2 rounded">
    Open dialog
  </button>
  <div
    x-show="open"
    x-transition
    class="fixed inset-0 bg-black/50 flex items-center justify-center"
  >
    <div class="bg-white p-6 rounded-lg max-w-md">
      <h2 class="text-xl font-bold">Hello!</h2>
      <p class="mt-2">This is a modal dialog.</p>
      <button @click="open = false" class="mt-4 bg-gray-200 px-4 py-2 rounded">
        Close
      </button>
    </div>
  </div>
</div>

Example: Tooltip

A small message that appears when the user hovers over an element.

<span x-data="{ hovered: false }" class="relative inline-block">
  <button
    @mouseenter="hovered = true"
    @mouseleave="hovered = false"
    class="bg-gray-200 px-3 py-1 rounded"
  >
    Hover me
  </button>
  <span
    x-show="hovered"
    class="absolute bottom-full mb-2 left-1/2 -translate-x-1/2
               bg-black text-white text-sm px-2 py-1 rounded whitespace-nowrap"
  >
    Helpful hint!
  </span>
</span>

Example: Accordion / collapsible

A section of content that can be expanded and collapsed - the equivalent of Bootstrap’s “collapse” component.

<div x-data="{ open: false }" class="border rounded">
  <button @click="open = !open" class="w-full text-left p-4 font-bold">
    Click to expand
  </button>
  <div x-show="open" class="p-4 border-t">
    Hidden content revealed! You can put anything in here - paragraphs, lists,
    images, even other Alpine components.
  </div>
</div>

A slideshow of images with previous/next buttons.

<div
  x-data="{
       current: 0,
       images: ['slide1.jpg', 'slide2.jpg', 'slide3.jpg']
     }"
  class="relative"
>
  <img :src="images[current]" class="w-full rounded-lg" />
  <button
    @click="current = (current - 1 + images.length) % images.length"
    class="absolute left-2 top-1/2 bg-white/80 px-3 py-1 rounded"
  >
    &lsaquo;
  </button>
  <button
    @click="current = (current + 1) % images.length"
    class="absolute right-2 top-1/2 bg-white/80 px-3 py-1 rounded"
  >
    &rsaquo;
  </button>
</div>

Example: Responsive navigation bar

A common site-wide pattern: a horizontal navigation bar that becomes a “hamburger” menu on small screens. This is the example that combines almost everything we have seen so far - utility classes, responsive prefixes, and Alpine state.

<nav x-data="{ menuOpen: false }" class="bg-gray-800 text-white">
  <div class="flex items-center justify-between p-4">
    <a href="/" class="font-bold text-xl">My Site</a>

    <!-- the hamburger button - only visible BELOW the md breakpoint -->
    <button @click="menuOpen = !menuOpen" class="md:hidden">&#9776;</button>

    <!-- the link group - hidden by default on small screens,
         always shown as a flex row from md upward -->
    <div
      :class="menuOpen ? 'block' : 'hidden'"
      class="md:!block absolute md:static top-16 left-0 right-0
                bg-gray-800 md:bg-transparent p-4 md:p-0
                md:flex md:gap-6"
    >
      <a href="#" class="block md:inline">Home</a>
      <a href="#" class="block md:inline">About</a>
      <a href="#" class="block md:inline">Contact</a>
    </div>
  </div>
</nav>

Where to go from here

The examples above can be adapted into a wide range of interactive components, but Alpine.js offers many more features (lists, forms, animations) - explore the Alpine documentation for the full reference.

Conclusions

You have now seen the joy of the Tailwind CSS front-end framework.