โ ๏ธ Breaking Change
Impact Score: 7/10
Tailwind CSS v1.8.0 โ Release Notes & Engineering Impact
Source available โ automated, not human-reviewed
Component: tailwind ยท Channel: stable. Automated analysis, not a compatibility certification. How this works.
Analysis updated: 2026-11-01.
Breaking-change evidence from the source
This is a breaking change (although it probably won't _actually_ affect you), so to make it the default you'll have to opt-in behind the `purgeLayersByDefault` flag:
โก Executive Summary (TL;DR)
Tailwind CSS v1.8.0. Source highlight: Tailwind CSS v1.8 is now available with a handful of new utilities, a couple new features, and an exciting new experiment ๐!
Who Does This Impact? (Role-Based Analysis)
๐ป Software Engineers & Devs
Check the source notes against the package and APIs you use before upgrading.
๐ Product & Engineering Leads
Use the documented changes to assess relevance to your product; release frequency alone is not a quality measure.
โ๏ธ DevOps & Security
Verify the target version, runtime requirements and rollback procedure in the official documentation.
โ ๏ธ Breaking Changes & Deprecations (1)
- This is a breaking change (although it probably won't _actually_ affect you), so to make it the default you'll have to opt-in behind the `purgeLayersByDefault` flag:
โจ New Features & Capabilities (1)
- New features
๐ View Raw Release Notes (Original Developer Log)
# Tailwind CSS v1.8
Tailwind CSS v1.8 is now available with a handful of new utilities, a couple new features, and an exciting new experiment ๐!
- [New features](#new-features)
- [New `font-variant-numeric` utilities](#new-font-variant-numeric-utilities)
- [New grid alignment utilities](#new-grid-alignment-utilities)
- [New `preserveHtmlElements` option for `purge`](#new-preservehtmlelements-option-for-purge)
- [New `layers` mode for `purge`](#new-layers-mode-for-purge)
- [Support configuring variants as functions](#support-configuring-variants-as-functions)
- [Dark mode (experimental)](#dark-mode-experimental)
- [Changes](#changes)
- [`@layer` rules are now grouped together](#layer-rules-are-now-grouped-together)
- [Deprecations](#changes)
- [`conservative` purge mode deprecated in favor of `layers`](conservative-purge-mode-deprecated-in-favor-of-layers)
<a name="new-features"></a>
## New features
<a name="new-font-variant-numeric-utilities"></a>
### New `font-variant-numeric` utilities ([#2305](https://github.com/tailwindlabs/tailwindcss/pull/2305))
We've added a new composable API for the `font-variant-numeric` property, so now you can finally do the whole `tabular-nums` thing!
Here's what's been added:
| Class | Description |
| -------------------- | ---------------------------------------- |
| `normal-nums` | Reset `font-variant-numeric` to `normal` |
| `ordinal` | Enables the `ordinal` feature |
| `slashed-zero` | Enables the `slashed-zero` feature |
| `lining-nums` | Enables the `lining-nums` feature |
| `oldstyle-nums` | Enables the `oldstyle-nums` feature |
| `proportional-nums` | Enables the `proportional-nums` feature |
| `tabular-nums` | Enables the `tabular-nums` feature |
| `diagonal-fractions` | Enables the `diagonal-fractions` feature |
| `stacked-fractions` | Enables the `stacked-fractions` feature |
The exciting thing about how these are implemented is that they are _composable_ in your HTML, so you can enable multiple `font-variant-numeric` features by adding multiple classes:
```html
<p class="slashed-zero tabular-nums diagonal-fractions">12345</p>
```
The `normal-nums` class can be used to reset things, usually used at a particular breakpoint:
```html
<p class="slashed-zero tabular-nums diagonal-fractions md:normal-nums">12345</p>
```
By default, only `responsive` variants are enabled for this new core plugin.
<a name="new-grid-alignment-utilities"></a>
### New grid alignment utilities ([#2306](https://github.com/tailwindlabs/tailwindcss/pull/2306))
We've added a bunch of new utilities for the `place-items`, `place-content`, `place-self`, `justify-items`, and `justify-self` properties!
Here's a complete list of what has been added:
| Core plugin | Class | CSS |
| -------------- | ----------------------- | ------------------------------ |
| `justifyItems` | `justify-items-auto` | `justify-items: auto` |
| `justifyItems` | `justify-items-start` | `justify-items: start` |
| `justifyItems` | `justify-items-end` | `justify-items: end` |
| `justifyItems` | `justify-items-center` | `justify-items: center` |
| `justifyItems` | `justify-items-stretch` | `justify-items: stretch` |
| `justifySelf` | `justify-self-auto` | `justify-self: auto` |
| `justifySelf` | `justify-self-start` | `justify-self: start` |
| `justifySelf` | `justify-self-end` | `justify-self: end` |
| `justifySelf` | `justify-self-center` | `justify-self: center` |
| `justifySelf` | `justify-self-stretch` | `justify-self: stretch` |
| `placeContent` | `place-content-center` | `place-content: center` |
| `placeContent` | `place-content-start` | `place-content: start` |
| `placeContent` | `place-content-end` | `place-content: end` |
| `placeContent` | `place-content-between` | `place-content: space-between` |
| `placeContent` | `place-content-around` | `place-content: space-around` |
| `placeContent` | `place-content-evenly` | `place-content: space-evenly` |
| `placeContent` | `place-content-stretch` | `place-content: stretch` |
| `placeItems` | `place-items-auto` | `place-items: auto` |
| `placeItems` | `place-items-start` | `place-items: start` |
| `placeItems` | `place-items-end` | `place-items: end` |
| `placeItems` | `place-items-center` | `place-items: center` |
| `placeItems` | `place-items-stretch` | `place-items: stretch` |
| `placeSelf` | `place-self-auto` | `place-self: auto` |
| `placeSelf` | `place-self-start` | `place-self: start` |
| `placeSelf` | `place-self-end` | `place-self: end` |
| `placeSelf` | `place-self-center` | `place-self: center` |
| `placeSelf` | `place-self-stretch` | `place-self: stretch` |
By default, `responsive` variants are generated for each of these new core plugins.
<a name="new-preservehtmlelements-option-for-purge"></a>
### New `preserveHtmlElements` option for `purge` ([#2283](https://github.com/tailwindlabs/tailwindcss/pull/2283))
Tailwind v1.8 introduces a new `preserveHtmlElements` option to the `purge` configuration that allows you to safelist all plain HTML elements, like `p`, `blockquote`, `body`, `video`, etc.
```js
// tailwind.config.js
module.exports = {
purge: {
content: [
// Paths...
],
preserveHtmlElements: true,
},
}
```
This helps avoid accidentally purging things like heading elements when your source files are in a format that compiles to HTML, like markdown (since your markdown won't actually contain the string `h1` anywhere).
This option is set to `true` by default.
<a name="new-layers-mode-for-purge"></a>
### New `layers` mode for `purge` ([#2288](https://github.com/tailwindlabs/tailwindcss/pull/2288))
We've introduced a new `layers` purge mode and made it the default, deprecating the existing `conservative` mode.
When configured manually, it looks like this:
```js
// tailwind.config.js
module.exports = {
purge: {
mode: 'layers',
layers: ['base', 'components', 'utilities'],
content: [
// Paths...
],
},
}
```
It allows you to tell Tailwind which _layers_ it should purge (base, components, and/or utilities). The old `conservative` mode was the equivalent of this:
```js
// tailwind.config.js
module.exports = {
purge: {
mode: 'layers',
layers: ['utilities'],
content: [
// Paths...
],
},
}
```
This is a breaking change (although it probably won't _actually_ affect you), so to make it the default you'll have to opt-in behind the `purgeLayersByDefault` flag:
```js
// tailwind.config.js
module.exports = {
future: {
purgeLayersByDefault: true,
},
// ...
}
```
<a name="support-configuring-variants-as-functions"></a>
### Support configuring variants as functions ([#2309](https://github.com/tailwindlabs/tailwindcss/pull/2309))
Adding new variants to a core plugin is annoying right? You have to remember to list _all_ of the existing variants, instead of just specying the _new_ ones you want to add. Completely unacceptable!
Tailwind CSS v1.8 makes it possible to configure variants as functions so you can leverage some helpful utilities we expose to you that make it easy to _extend_ the variant configuration instead of having to re-write the entire list:
```js
// tailwind.config.js
module.exports = {
variants: {
opacity: ({ before }) => before(['group-hover'], 'hover'),
},
}
```
Read [the pull request](https://github.com/tailwindlabs/tailwindcss/pull/2309) for all of the details.
<a name="dark-mode-experimental"></a>
### Dark mode (experimental) ([#2279](https://github.com/tailwindlabs/tailwindcss/pull/2279))
Oh yeah I almost forgot, we added dark mode.
```html
<div class="bg-white text-black dark:bg-black dark:text-white dark:hover:text-gray-300"></div>
```
It's stackable with both responsive variants and pseudo-class variants, so you can use classes like `lg:dark:focus:text-white` no problem.
It can be configured to use a `prefers-color-scheme` media query _or_ a parent class (`.dark`), whichever you prefer:
```js
module.exports = {
dark: 'media', // or 'class'
experimental {
darkModeVariant: true,
}
}
```
It's enabled for `backgroundColor`, `borderColor`, `divideColor`, `textColor`, `gradientColorStops`, and `placeholderColor` by default.
It's experimental right now, so enable it using the `darkModeVariant` experimental flag:
```js
// tailwind.config.js
module.exports = {
experimental: {
darkModeVariant: true,
},
// ...
}
```
Let us know how it works for you and if there's anything we can improve before we tag it as stable!
<a name="changes"></a>
## Changes
<a name="layer-rules-are-now-grouped-together"></a>
### `@layer` rules are now grouped together ([#2312](https://github.com/tailwindlabs/tailwindcss/pull/2312))
Any custom CSS defined within a `@layer` at-rule that matches one of Tailwind's layers is now grouped together with the corresponding Tailwind rules.
For example, this CSS:
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn {
background: blue;
}
}
@layer utilities {
.align-banana {
text-align: banana;
}
}
@layer base {
h1 {
font-weight: bold;
}
}
@layer components {
.card {
border-radius: 12px;
}
}
@layer base {
p {
font-weight: normal;
}
}
@layer utilities {
.align-sandwich {
text-align: sandwich;
}
}
```
...conceptually becomes this:
```css
@tailwind base;
h1 {
font-weight: bold;
}
p {
font-weight: normal;
}
@tailwind components;
.btn {
background: blue;
}
.card {
border-radius: 12px;
}
@tailwind utilities;
.align-banana {
text-align: banana;
}
.align-sandwich {
text-align: sandwich;
}
```
This is useful for avoiding CSS declaration order specificity issues and lets you decouple authoring order from intended render order. This is generally inline with the new `@layer` CSS proposal that came out shortly after we introduced this at-rule to Tailwind ourselves without knowing that existed, heh.
This is a change in behavior to how things worked before but we don't document the `@layer` rule outside of mentioning it in the release notes for Tailwind 1.6. I am going to be a bit bold and classify this as a bugfix, as this is how this always should have worked. Basically a zero percent chance this will break anything for anyone.
<a name="deprecations"></a>
## Deprecations
<a name="conservative-purge-mode-deprecated-in-favor-of-layers"></a>
### `conservative` purge mode deprecated in favor of `layers` ([#2288](https://github.com/tailwindlabs/tailwindcss/pull/2288))
The new `layers` mode replaces the old `conservative` mode and will be the default in v2.0. You'll get a console warning until you update this value in your config file.
If you want to update without any changes in behavior, use this configuration:
```js
// tailwind.config.js
module.exports = {
purge: {
mode: 'layers',
layers: ['utilities'],
content: [
// Paths...
],
},
}
```