Tailwind CSS v2.0

Date
Author
Adam Wathan
@adamwathan

Almost exactly 18 months ago we released Tailwind CSS v1.0, which signalled a commitment to stability while continuing to push the boundaries with exciting new features in every minor release.

Over the course of those 18 months we released nine minor versions that added features like placeholder styling, screenreader visibility, CSS grid, transitions, transforms, animations, layout utilities, integrated tree-shaking, gradients, and tons more.

Today we’re finally releasing Tailwind CSS v2.0.

Tailwind CSS v2.0 is the first major update ever, including:

…and a bunch of other little things too.

Even though Tailwind CSS v2.0 is a new major version, we’ve worked really hard to minimize significant breaking changes, especially ones that would force you to edit tons of your templates. We’ve renamed two classes, removed three that are no longer relevant in modern browsers, and replaced two with more powerful alternatives. Any other breaking changes that might impact you can be remedied with a couple small additions to your tailwind.config.js file. Upgrading shouldn’t take more than about 30 minutes.

Check out the upgrade guide for more details and step-by-step instructions on migrating your project to Tailwind CSS v2.0.

If you’d like to start a brand new project with v2.0, head over to our updated installation documentation to get started fast.

Also how about that brand new website eh? Hot damn.


All-new color palette

We’ve learned a lot about color since the first time we tried to design a general purpose color palette back in the Tailwind CSS v0.1.0 days, and v2.0 represents our best attempt so far.

The new color palette includes 22 colors (compared to 10 previously) with 10 shades each (instead of 9) for a total of 220 values.

New Tailwind CSS color palette

We’ve added an extra light 50 shade for every color, so they go from 50–900 now:

<div class="bg-gray-50">I can't believe it's not white.</div>

The palette even includes 5 different shades of gray now, so you can choose “blue gray” if you want something really cool, or go all the way to “warm gray” for something with a lot more brown in it.

New Tailwind CSS alternate gray

We configure a well-balanced 8-color palette for you out of the box, but the complete color palette lives in a new tailwindcss/colors module that you can import at the top of your config file to curate your own custom palette however you like:

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

module.exports = {
  theme: {
    colors: {
      gray: colors.trueGray,
      indigo: colors.indigo,
      red: colors.rose,
      yellow: colors.amber,
    },
  },
}

Learn more in the new customizing colors documentation.


Dark mode

Ever since iOS added native dark mode all you dark mode nerds haven’t been able to leave me alone about adding it to Tailwind. Well you did it, it’s here, you win.

Open up your tailwind.config.js file and flip darkMode to media:

tailwind.config.js
module.exports = {
  darkMode: 'media',
  // ...
}

Boom — now just add dark: to the beginning of a class like bg-black and it’ll only take effect when dark mode is enabled:

<div class="bg-white dark:bg-black">
  <h1 class="text-gray-900 dark:text-white">Dark mode</h1>
  <p class="text-gray-500 dark:text-gray-300">
    The feature you've all been waiting for.
  </p>
</div>

Works with hover and stuff too:

<button
  class="bg-gray-900 hover:bg-gray-800 dark:bg-white dark:hover:bg-gray-50"
>
  <!-- ... -->
</button>

And responsive stuff:

<div class="... lg:bg-white lg:dark:bg-black">
  <!-- ... -->
</div>

And responsive hover stuff:

<button class="... lg:dark:bg-white lg:dark:hover:bg-gray-50">
  <!-- ... -->
</button>

Check out the dark mode docs for all the gory details.


Extra wide 2XL breakpoint

I’m pretty sure they make an iPhone that is 1280px wide now, so it’s time to step it up.

We’ve added a new 2xl breakpoint out-of-the-box that lets you target things at 1536px and above:

<h1 class="... 2xl:text-9xl">Godzilla</h1>

Exciting I know but also let’s be serious you’ve been able to add this yourself for like three years. Now it’s blessed though, I get it.


New outline ring utilities

You know how the outline property ignores border radius and pretty much just always looks bad? The ring utilities are our attempt to will a better solution into existence through blood, sweat, and tears.

They work a lot like the border utilities, except they add a solid box-shadow rather than a border so they don’t impact the layout:

<button
  class="... focus:outline-none focus:ring-2 focus:ring-blue-300 focus:ring-opacity-50"
>
  <!-- ... -->
</button>

You can even offset them to create a sort of halo effect with ring-offset-{width} utilities:

<button
  class="... focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-300 focus:ring-opacity-50"
>
  <!-- ... -->
</button>

Using a bunch of CSS custom property voodoo we’ve even made them automatically combine with regular box-shadows, too:

<button class="shadow-sm focus:ring-2 ...">
  <!-- Both the shadow and ring will render together -->
</button>

The ring width documentation is the best starting point for learning these new APIs. They seriously turned out so cool, more useful than you probably think.


Utility-friendly form styles

One thing I am constantly surprised by is how few people complain about how unbelievably useless form elements are out of the box with Tailwind. They literally look awful and you can’t do anything about it without writing custom CSS full of weird background-image SVG tricks and worrying about obscure edge cases that require CSS properties you’ve never heard of before like color-adjust.

I tried to solve this a while back with the @tailwindcss/custom-forms plugin, but something about adding a bunch of classes like form-input and form-checkbox just didn’t feel quite right so we didn’t really promote it and didn’t even link to it from the Tailwind documentation. This time though I think we figured it out.

Alongside Tailwind CSS v2.0, we’re releasing a brand new official plugin called @tailwindcss/forms that normalizes and resets all of the basic form controls across browsers to a state that is super easy to style with pure utility classes:

<!-- This will be a nice rounded checkbox with an indigo focus ring and an indigo checked state -->
<input
  type="checkbox"
  class="h-4 w-4 rounded border-gray-300 focus:border-indigo-300 focus:ring-2 focus:ring-indigo-200 focus:ring-opacity-50 text-indigo-500"
/>

It’s not included out of the box but you can add it to your tailwind.config.js file with a single line:

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

Check out the @tailwindcss/forms documentation for more information.


Default line-heights per font-size

Every font-size utility in Tailwind now comes paired with a sensible default line-height:

// Tailwind's default theme
module.exports = {
  theme: {
    // ...
    fontSize: {
      xs: ['0.75rem', { lineHeight: '1rem' }],
      sm: ['0.875rem', { lineHeight: '1.25rem' }],
      base: ['1rem', { lineHeight: '1.5rem' }],
      lg: ['1.125rem', { lineHeight: '1.75rem' }],
      xl: ['1.25rem', { lineHeight: '1.75rem' }],
      '2xl': ['1.5rem', { lineHeight: '2rem' }],
      '3xl': ['1.875rem', { lineHeight: '2.25rem' }],
      '4xl': ['2.25rem', { lineHeight: '2.5rem' }],
      '5xl': ['3rem', { lineHeight: '1' }],
      '6xl': ['3.75rem', { lineHeight: '1' }],
      '7xl': ['4.5rem', { lineHeight: '1' }],
      '8xl': ['6rem', { lineHeight: '1' }],
      '9xl': ['8rem', { lineHeight: '1' }],
    },
  },
}

So now when you add a utility like text-xl, the corresponding default line-height (1.75rem in this case) is added automatically:

<p class="text-xl">This will have a line-height of 1.75rem automatically.</p>

If you want to override this, you can still do it by layering on a leading utility:

<p class="text-3xl leading-normal">Come on don't do this to me.</p>

Check out the font size documentation for some additional details.


Extended spacing, typography, and opacity scales

We’ve extended the default spacing scale to include a bunch of micro values like 0.5, 1.5, 2.5, and 3.5:

<span class="ml-0.5">Just a little nudge.</span>

…as well as a bunch of new values at the top end as well like 72, 80, and 96:

<div class="p-96">This is too much padding.</div>

We’ve also extended the inset (that’s top/right/bottom/left for you dinosaurs) and translate plugins to include the full spacing scale, so now you can do things like this:

<div class="top-8">
  <!-- .... -->
</div>

We’ve extended the default typography scale with new 7xl, 8xl, and 9xl values:

<h1 class="text-9xl font-bold">What is this, an Apple website?</h1>

And we’ve also extended the default opacity scale with steps of 10, as well as 5 and 95 values:

<figure class="opacity-5">
  <blockquote>You can't see me.</blockquote>
  <figcaption>John Cena</figcaption>
</figure>

Peruse the entire default config file to see exactly what’s available.


Use @apply with anything

By far the most common question I’ve gotten over the years is “why doesn’t @apply hover:bg-black work?”

And it’s a fair question, it’s stupid that it doesn’t didn’t work.

It took some serious engineering muscle but we figured it out — now you can @apply literally anything:

.btn {
  @apply bg-indigo-500 hover:bg-indigo-600 focus:ring-2 focus:ring-indigo-200 focus:ring-opacity-50;
}

Check out the updated @apply documentation to learn more.


New text overflow utilities

Up until v2.0, if you wanted to control overflowing text all we really gave you was the fairly heavy-handed truncate utility.

Now we’ve added dedicated overflow-ellipsis and overflow-clip utilities to control just the text-overflow property, in case you wanted to add ellipsis to overflowing text without restricting that text to one line.

<p class="overflow-ellipsis overflow-hidden">
  Look ma no whitespace-nowrap ipsum...
</p>

Check out the new text overflow documentation to see it in action.


Extend variants

You know what sucks? Wanting to enable focus-visible for backgroundColor but having to list every single default variant just to add one extra one:

tailwind.config.js
module.exports = {
  // ...
  variants: {
    backgroundColor: ['responsive', 'hover', 'focus', 'focus-visible'],
  },
}

You know what’s better? Just adding the one you want to enable:

tailwind.config.js
module.exports = {
  // ...
  variants: {
    extend: {
      backgroundColor: ['focus-visible'],
    },
  },
}

Giddy up.


Group-hover and focus-within by default

One of the things we learned working on Tailwind UI is that group-hover and focus-within aren’t nice-to-haves, they’re must-haves.

Anywhere where we enabled hover or focus by default previously now has group-hover and focus-within enabled by default too:

<div class="group ...">
  <span class="group-hover:text-blue-600 ...">Da ba dee da ba daa</span>
</div>

Check out the default variants reference for a full list of what’s enabled where in v2.0.


Default transition duration and easing curve

Until now, any time you wanted to add a transition in Tailwind you typically needed to add three classes:

<button class="... transition duration-150 ease-in-out">Count them</button>

In v2.0, we’ve made it possible to specify a default duration and timing function that is used automatically any time any transitionProperty utility is added:

tailwind.config.js
module.exports = {
  // ...
  theme: {
    // ...
    transitionDuration: {
      DEFAULT: '150ms',
      // ...
    },
    transitionTimingFunction: {
      DEFAULT: 'cubic-bezier(0.4, 0, 0.2, 1)',
      // ...
    },
  },
}

So now you only need to write a single class if you have a common duration and timing function that you use really frequently:

<button class="... transition">Count them again</button>

Of course you can override this by layering on separate duration or timing function utilities:

<button class="... transition duration-300 ease-out">We're back baby</button>

Learn more about transitions in the transition property documentation.


Incompatibility with IE11

We’ve decided to unburden ourselves with caring about IE11 at all, which has allowed us to fully embrace CSS custom properties for all sorts of crazy stuff and is what makes things like the new ring utilities even possible.

Dropping IE11 support means smaller builds even when using PurgeCSS, because we don’t have to ship any CSS variable fallbacks which adds up more than you’d expect.

Cheers to Bootstrap for having the cojones to do this first — I don’t think we would have been so bold if they hadn’t decided to pave the way.

The good news is that if you need to support IE11, you can always use Tailwind CSS v1.9 which is still an amazingly productive framework.


So there you have it folks, that’s Tailwind CSS v2.0 in a (pretty big) nutshell!

What are you waiting for? Go build something awesome.