Tailwind UI
Browse Pricing Login

Documentation

Getting set up

Add the @tailwindcss/ui plugin

During early access, the components in Tailwind UI depend on some extensions we've added to the default Tailwind CSS config (like extra spacing values, updated, colors, additional shadows, etc.)

These extensions will make their way into Tailwind itself in the future but right now you need to install the @tailwindcss/ui plugin to add these extensions to your project:

# Using npm
npm install @tailwindcss/ui

# Using yarn
yarn add @tailwindcss/ui

Then add @tailwindcss/ui to your Tailwind plugin list:

// tailwind.config.js
module.exports = {
  plugins: [
    require('@tailwindcss/ui'),
  ]
}

Make sure you don't generate your Tailwind config using the --full flag or the extensions added by the plugin will be superseded by the values in your config. Keep any of your own modifications under theme.extend to ensure everything works as expected.

We also have a Tailwind UI-compatible CDN build available if that's more your style:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tailwindcss/ui@latest/dist/tailwind-ui.min.css">

You should really be using a proper build though if you can — the development build of Tailwind is pretty beefy, especially with the Tailwind UI extensions.

For more details on what exactly the plugin adds to Tailwind, see "How @tailwindcss/ui extends Tailwind".

Update your PurgeCSS configuration

The @tailwindcss/ui plugin adds several new utilities that include the . character in their name, so if you're using PurgeCSS for your production builds (I definitely recommend you do), you should update the regex in your PurgeCSS configuration to include the dot:

  // postcss.config.js
  const purgecss = require('@fullhuman/postcss-purgecss')({

    // Specify the paths to all of the template files in your project
    content: [
      './src/**/*.html',
      './src/**/*.vue',
      './src/**/*.jsx',
      // etc.
    ],

    // Include any special characters you're using in this regular expression
-   defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
+   defaultExtractor: content => content.match(/[\w-/.:]+(?<!:)/g) || []
  })

  module.exports = {
    plugins: [
      require('tailwindcss'),
      require('autoprefixer'),
      ...process.env.NODE_ENV == 'production'
        ? [purgecss]
        : []
    ]
  }

Configuring sidebar breakpoints

If you are building a site that uses one of our sidebar layout application shells, you'll want to tweak the breakpoints in your app to account for the width of the sidebar. If you don't, you'll find that wide components like lists and tables may not look right at certain screen sizes because they are expecting to have more space available to them.

The easiest way to do this is using the layout option exposed by our @tailwindcss/ui plugin:

// tailwind.config.js
module.exports = {
  plugins: [
    require('@tailwindcss/ui')({
      layout: 'sidebar',
    })
  ]
}

This will automatically configure your breakpoints to accommodate our standard 256px sidebar width.

Optional: Add the Inter font family

We've used Inter font family for all of the Tailwind UI examples because it's a beautiful font for UI design and is completely open-source and free. Using a custom font is nice because it allows us to make the components look the same on all browsers and operating systems.

You can use any font you want in your own project of course, but if you'd like to use Inter, the easiest way is to first add it via the CDN:

<link rel="stylesheet" href="https://rsms.me/inter/inter.css">

Then add "Inter var" to your "sans" font family in your Tailwind config:

// tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter var', ...defaultTheme.fontFamily.sans],
      },
    },
  },
  plugins: [
    require('@tailwindcss/ui'),
  ]
}

Integrating with JavaScript frameworks

To make Tailwind UI as universal as possible, we've built all the components using HTML only.

The vast majority of components don't need JavaScript at all and are completely ready to go out of the box, but things that are interactive like dropdowns, modals, etc. require a little bit of JS to make them work the way you'd expect.

When you see these components in Tailwind UI, you'll notice we've provided some bare minimum JavaScript to get them behaving closer to how you'd expect using Alpine.js — an incredibly simple, lightweight library for defining declarative DOM interactions directly in your HTML.

Here's what one of our toggle components looks like using Alpine:

<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.0.1/dist/alpine.js" defer></script>

<span role="checkbox" tabindex="0" class="relative inline-block flex-no-shrink h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:shadow-outline"
  x-data="{ on: false }"
  :class="{ 'bg-gray-200': !on, 'bg-indigo-600': on }"
  @click="on = !on"
  @keydown.space.prevent="on = !on"
  :aria-checked="on ? 'true' : 'false'"
>
  <span aria-hidden="true" :class="{ 'translate-x-5': on, 'translate-x-0': !on }" class="inline-block h-5 w-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"></span>
</span>

Our goal with the minimal JS we provide is just to communicate what classes you need to toggle on which elements, and when you need to toggle them.

We originally attempted to document this sort of thing purely using comments in the HTML, but we found the Alpine code to actually be more concise and easier to read than trying to explain it in sentences.

We chose Alpine over other frameworks for a few reasons:

  • Its syntax is almost identical to Vue, so if you know Vue you will have no trouble reading it at all
  • If you know React or Angular, you can almost definitely read and understand what's going on here even though the syntax isn't the same
  • Because it's so declarative, it's much more self-documenting than any imperative vanilla JS we could have provided
  • It's extremely light and unintrusive, so if you don't know Vue/React/Angular/whatever, you could pull Alpine into your project without it being some huge paradigm shift

It's important to note that Tailwind UI does not require Alpine.js, it just felt like the simplest way to document what classes need to be toggled for components that are supposed to be interactive.

We are not endorsing it as the officially recommended JS framework or anything — I personally use the Tailwind UI components with Vue most of the time myself.

If you hate this, please feel free to chime in on this GitHub issue and we can brainstorm together on a better way to communicate these interactions in the code examples.

Important: Our minimal JS examples are not meant to be "production-ready"

Tailwind UI is very focused on providing design and HTML. There are lots of intricacies you will inevitably be responsible for yourself with interactive components, like ensuring they are fully keyboard accessible, that focus is trapped properly for keyboard users, etc.

Our Alpine.js examples are designed purely to communicate what classes you need to toggle on which elements and when, they are not meant to be battle-tested JS reference implementations.


Creating reusable components and partials

Since Tailwind UI provides components using simple static HTML, there is a lot of repetition that wouldn't actually be there in a real-world project where the HTML was being generated from some dynamic data source. We might give you a list component with 5 list items for example that have all the utilities duplicated on each one, whereas in your project you'll actually be generating those list items in a loop.

We can't predict what tools/frameworks/template languages everyone might be working with so we think this static HTML approach is the best way to make these components available to everyone no matter what ecosystem they normally work in, but to keep your project maintainable we recommend creating reusable template partials or JS components for the Tailwind UI components you use using whatever tools you like.

Learn more about this in the "Extracting Components" documentation on the Tailwind CSS website →


Customizing colors

The new color palette we've included with the @tailwindcss/ui plugin is designed to make the colors much more interchangeable than they were in the past.

For example, every 600 shade has a similar perceived brightness, which means you can take an indigo-600 button with white text and change it to teal-600 without worrying about the contrast being completely different.

That means that to change the colors in a component, it's usually as simple as just doing a global find and replace for "indigo" and swapping it to "teal".

Dealing with inherently light colors

There are some cases where this might not work the way you first expect, like yellow for example. To get a yellow that has the same brightness as a color like blue, the yellow has to actually be more like brown, so swapping blue-600 for yellow-600 isn't going to give you a bright yellow theme like you might be looking for.

That's because you can't use white text on a bright yellow button for example without the text being impossible to read — you actually need to use a dark text color, like say yellow-700 or 800 for text, and yellow-200 for the background.

In these cases you'll have to swap the colors with a bit more care.

In the future we're planning to provide some more "rules" around this to help you make these sorts of changes more confidently, even if you don't trust your own judgment with color.


Icons

The icons we've used in all of the Tailwind UI components are from a custom set we designed called "Heroicons" and are available completely for free here:

https://github.com/refactoringui/heroicons


How @tailwindcss/ui extends Tailwind

Updated color palette

Tailwind UI includes a brand new color palette that is more consistent across colors, and more vivid than the default Tailwind CSS color palette.

It also includes a new "50" shade, so there are now 10 shades per color instead of 9.

50 100 200 300 400 500 600 700 800 900

New gray

The default Tailwind gray is extremely saturated with blue and looks really good with certain colors, but it's a bit too opinionated to work with every color.

We've re-worked gray to be much more neutral (although still with a cool tint to it) and created a new "cool-gray" that has the same sort of look as the default Tailwind gray for people who prefer that one.

New default gray Cool gray

Interchangeable colors

We've done our best to make the colors as interchangeable as possible, so for example if you see a component you like and it's using indigo for all of the colored sections but you want to use blue, you can just find and replace "indigo" for "blue" without changing any of the numbers and you will get really good results.

Some colors are inherently lighter than others (like yellow) so swapping indigo for yellow is going to look much more like brown than yellow so you will probably want to rethink the color combinations a bit in some cases, but generally switching colors is much easier than it was before.

Note that gray isn't swappable with the other colors — it's use cases are a bit different (every site uses gray in combination with brand colors) so that palette has been designed independently. The "gray" and "cool-gray" colors are perfectly interchangeable with each other though.

Solid box shadow for cut-out effects

We've added shadow-solid which is a 2px box shadow with no blur that adopts the current text color so you can use it for cut-out effects, for example:

Colored focus shadows

Tailwind includes a blue shadow-outline utility out of the box for focus styles, but when building the Tailwind UI components we realized we needed colored shadows for focus states on branded elements, high severity buttons, etc.

We've added a shadow-outline-{color} utility for each color so you can have nice focus states for any element:

group-focus variant

We've added a group-focus variant that works just like group-hover, but for focus. We use this a lot for things like changing the color of an icon in a link when the link is focused if the icon needs to be a different color than the text.

New max-w-7xl utility

We've added max-w-7xl which conveniently matches our 1280px breakpoint. This is useful for sidebar layouts where you want to constrain the content area to 1280px, but max-w-screen-xl doesn't actually do what you need since the xl breakpoint has been increased to account for the sidebar width.

More variants enabled by default

We've enabled group-hover, group-focus, focus-within, and active for many of the utilities that don't have them by default.

Bundled the custom forms plugin

Tailwind UI includes the @tailwindcss/custom-forms plugin out of the box so you can actually use custom selects, checkboxes, and radio buttons.