Compare Versions - tailwindcss
npm / tailwindcss / Compare Versions
Added
- Support Vite 8 in
@tailwindcss/vite(#19790)
Fixed
- Don't crash when candidates contain prototype properties like
row-constructor(#19725) - Canonicalize
calc(var(--spacing)*…)expressions into--spacing(…)(#19769) - Fix crash in canonicalization step when handling utilities containing
@propertyat-rules (e.g.shadow-sm border) (#19727) - Skip full reload for server only modules scanned by client CSS when using
@tailwindcss/vite(#19745) - Improve canonicalization for bare values exceeding default spacing scale suggestions (e.g.
w-1234 h-1234→size-1234) (#19809) - Fix canonicalization resulting in empty list (e.g.
w-5 h-5 size-5→''instead ofsize-5) (#19812)
Added
- Add mauve, olive, mist, and taupe color palettes to the default theme (#19627)
- Add
@tailwindcss/webpackpackage to run Tailwind CSS as a webpack plugin (#19610) - Add
pbs-*andpbe-*utilities forpadding-block-startandpadding-block-end(#19601) - Add
mbs-*andmbe-*utilities formargin-block-startandmargin-block-end(#19601) - Add
scroll-pbs-*andscroll-pbe-*utilities forscroll-padding-block-startandscroll-padding-block-end(#19601) - Add
scroll-mbs-*andscroll-mbe-*utilities forscroll-margin-block-startandscroll-margin-block-end(#19601) - Add
border-bs-*andborder-be-*utilities forborder-block-startandborder-block-end(#19601) - Add
inline-*,min-inline-*,max-inline-*utilities forinline-size,min-inline-size, andmax-inline-size(#19612) - Add
block-*,min-block-*,max-block-*utilities forblock-size,min-block-size, andmax-block-size(#19612) - Add
inset-s-*,inset-e-*,inset-bs-*,inset-be-*utilities forinset-inline-start,inset-inline-end,inset-block-start, andinset-block-end(#19613) - Add
font-features-*utility forfont-feature-settings(#19623)
Fixed
- Prevent double
@supportswrapper forcolor-mixvalues (#19450) - Allow whitespace around
@source inline()argument (#19461) - Emit comment when source maps are saved to files when using
@tailwindcss/cli(#19447) - Detect utilities containing capital letters followed by numbers (#19465)
- Fix class extraction for Rails' strict locals (#19525)
- Align
@utilityname validation with Oxide scanner rules (#19524) - Fix infinite loop when using
@variantinside@custom-variant(#19633) - Allow multiples of
.25inaspect-*fractions (e.g.aspect-8.5/11) (#19688) - Ensure changes to external files listed via
@sourcetrigger a full page reload when using@tailwindcss/vite(#19670) - Improve performance of Oxide scanner in bigger projects by reducing file system walks (#19632)
- Ensure import aliases in Astro v5 work without crashing when using
@tailwindcss/vite(#19677) - Allow escape characters in
@utilitynames to improve support with formatters such as Biome (#19626) - Fix incorrect canonicalization results when canonicalizing multiple times (#19675)
- Add
.jjto default ignored content directories (#19687)
Deprecated
- Deprecate
start-*andend-*utilities in favor ofinset-s-*andinset-e-*utilities (#19613)
Fixed
- Ensure validation of
source(…)happens relative to the file it is in (#19274) - Include filename and line numbers in CSS parse errors (#19282)
- Skip comments in Ruby files when checking for class names (#19243)
- Skip over arbitrary property utilities with a top-level
!in the value (#19243) - Support environment API in
@tailwindcss/vite(#18970) - Preserve case of theme keys from JS configs and plugins (#19337)
- Write source maps correctly on the CLI when using
--watch(#19373) - Handle special defaults (like
ringColor.DEFAULT) in JS configs (#19348) - Improve backwards compatibility for
contenttheme key from JS configs (#19381) - Upgrade: Handle
futureandexperimentalconfig keys (#19344) - Try to canonicalize any arbitrary utility to a bare value (#19379)
- Validate candidates similarly to Oxide (#19397)
- Canonicalization: combine
text-*andleading-*classes (#19396) - Correctly handle duplicate CLI arguments (#19416)
- Don’t emit color-mix fallback rules inside
@keyframes(#19419) - CLI: Don't hang when output is
/dev/stdout(#19421)
Fixed
- Fix Safari devtools rendering issue due to
color-mixfallback (#19069) - Suppress Lightning CSS warnings about
:deep,:slotted, and:global(#19094) - Fix resolving theme keys when starting with the name of another theme key in JS configs and plugins (#19097)
- Allow named groups in combination with
not-*,has-*, andin-*(#19100) - Prevent important utilities from affecting other utilities (#19110)
- Don’t index into strings with the
theme(…)function (#19111) - Fix parsing issue when
\tis used in at-rules (#19130) - Upgrade: Canonicalize utilities containing
0values (#19095) - Upgrade: Migrate deprecated
break-wordstowrap-break-word(#19157)
Changed
- Remove the
postinstallscript from oxide (#19149)
Fixed
- Handle
'syntax in ClojureScript when extracting classes (#18888) - Handle
@variantinside@custom-variant(#18885) - Merge suggestions when using
@utility(#18900) - Ensure that file system watchers created when using the CLI are always cleaned up (#18905)
- Do not generate
grid-columnutilities when configuringgrid-column-startorgrid-column-end(#18907) - Do not generate
grid-rowutilities when configuringgrid-row-startorgrid-row-end(#18907) - Prevent duplicate CSS when overwriting a static utility with a theme key (#18056)
- Show Lightning CSS warnings (if any) when optimizing/minifying (#18918)
- Use
defaultexport condition for@tailwindcss/vite(#18948) - Re-throw errors from PostCSS nodes (#18373)
- Detect classes in markdown inline directives (#18967)
- Ensure files with only
@themeproduce no output when built (#18979) - Support Maud templates when extracting classes (#18988)
- Upgrade: Do not migrate
variant = 'outline'during upgrades (#18922) - Upgrade: Show version mismatch (if any) when running upgrade tool (#19028)
- Upgrade: Ensure first class inside
classNameis migrated (#19031) - Upgrade: Migrate classes inside
*ClassNameand*Classattributes (#19031)
Changed
- Drop warning from browser build (#18731)
- Drop exact duplicate declarations when emitting CSS (#18809)
Fixed
- Don't transition
visibilitywhen usingtransition(#18795) - Discard matched variants with unknown named values (#18799)
- Discard matched variants with non-string values (#18799)
- Show suggestions for known
matchVariantvalues (#18798) - Replace deprecated
clipwithclip-pathinsr-only(#18769) - Hide internal fields from completions in
matchUtilities(#18820) - Ignore
.vercelfolders by default (can be overridden by@source …rules) (#18855) - Consider variants starting with
@-to be invalid (e.g.@-2xl:flex) (#18869) - Do not allow custom variants to start or end with a
-or_(#18867, #18872) - Upgrade: Migrate
ariatheme keys to@custom-variant(#18815) - Upgrade: Migrate
datatheme keys to@custom-variant(#18816) - Upgrade: Migrate
supportstheme keys to@custom-variant(#18817)
Fixed
- Don't consider the global important state in
@apply(#18404) - Add missing suggestions for
flex-<number>utilities (#18642) - Fix trailing
)from interfering with extraction in Clojure keywords (#18345) - Detect classes inside Elixir charlist, word list, and string sigils (#18432)
- Track source locations through
@pluginand@config(#18345) - Allow boolean values of
process.env.DEBUGin@tailwindcss/node(#18485) - Ignore consecutive semicolons in the CSS parser (#18532)
- Center the dropdown icon added to an input with a paired datalist by default (#18511)
- Extract candidates in Slang templates (#18565)
- Improve error messages when encountering invalid functional utility names (#18568)
- Discard CSS AST objects with
falseorundefinedproperties (#18571) - Allow users to disable URL rebasing in
@tailwindcss/postcssviatransformAssetUrls: false(#18321) - Fix false-positive migrations in
addEventListenerand JavaScript variable names (#18718) - Fix Standalone CLI showing default Bun help when run via symlink on Windows (#18723)
- Read from
--border-color-*theme keys individe-*utilities for backwards compatibility (#18704) - Don't scan
.hdrand.exrfiles for classes by default (#18734)
Fixed
- Fix incorrectly generated CSS when using percentages in arbitrary values with calc (e.g.
w-[calc(100%-var(--offset))]) (#18289)
Fixed
- Correctly parse custom properties with strings containing semicolons (#18251)
- Upgrade: Migrate arbitrary modifiers without percentage signs to bare values (e.g.
/[0.16]→/16) (#18184) - Upgrade: Migrate CSS variable shorthands where fallback value contains function call (#18184)
- Upgrade: Migrate negative arbitrary values to negative bare values (e.g.
mb-[-32rem]→-mb-128) (#18212) - Upgrade: Do not migrate
blurinwire:model.blur(#18216) - Don't add spaces around CSS dashed idents when formatting math expressions (#18220)
Added
- Improve error messages when
@applyfails (#18059)
Fixed
- Upgrade: Do not migrate declarations that look like candidates in
<style>blocks (#18057, 18068) - Upgrade: Don't error when looking for
tailwindcssin pnpm monorepos (#18065) - Upgrade: Don't error when updating dependencies in pnpm monorepos (#18065)
- Upgrade: Migrate deprecated
order-nonetoorder-0(#18126) - Support Leptos
class:attributes when extracting classes (#18093) - Fix "Cannot read properties of undefined" crash on malformed arbitrary value (#18133)
- Upgrade: Migrate
-mt-[0px]tomt-[0px]instead of the other way around (#18154) - Fix Haml pre-processing crash when there is no
\nat the end of the file (#18155) - Ignore
.pnpm-storefolders by default (can be overridden by@source …rules) (#18163) - Fix PostCSS crash when calling
toJSON()(#18083)
Added
- Upgrade: Migrate bare values to named values (#18000)
- Upgrade: Added cache to improve template migration performance (#18025)
Fixed
- Allow
_before numbers during candidate extraction (#17961) - Prevent duplicate suggestions when using
@themeand@utilitytogether (#17675) - Ensure that media queries within
::beforeand::afterpseudo selectors create valid CSS rules in production builds (#17979) - Ensure that the standalone CLI does not leave temporary files behind (#17981)
- Ensure
-rotate-*utilities properly negate arbitrary values (#18014) - Ignore custom variants using
:merge(…)selectors in legacy JS plugins (#18020) - Ensure classes containing
.are properly extracted from Clojure files (#18038) - Upgrade: Fix error when using
@import … source(…)(#17963) - Upgrade: Change casing of utilities with named values to kebab-case to match updated theme variables (#18017)
- Upgrade: Don't migrate strings that match utility names in Vue attribute bindings other than
class(#18025)
Added
- Upgrade: Automatically convert arbitrary values to named values when possible (e.g.
h-[1lh]toh-lh) (#17831, #17854) - Upgrade: Update dependencies in parallel for improved performance (#17898)
- Add detailed logging about
@sourcedirectives, discovered files and scanned files when usingDEBUG=*(#17906, #17952) - Add support for generating source maps in development (#17775)
Fixed
- Ensure negative arbitrary
scalevalues generate negative values (#17831) - Fix HAML extraction with embedded Ruby (#17846)
- Don't scan files for utilities when using
@reference(#17836) - Fix incorrectly replacing
_within arbitrary modifier shorthandbg-red-500/(--my_opacity)(#17889) - Don't scan
.logfiles for classes by default (#17906) - Ensure that custom utilities applying other custom utilities don't swallow nested
@applyrules (#17925) - Download platform specific package if
optionalDependenciesare skipped (#17929)
Added
- Support using
@tailwindcss/upgradeto upgrade between versions of v4.* (#17717) - Add
h-lh/min-h-lh/max-h-lhutilities (#17790) - Transition
display,visibility,content-visibility,overlay, andpointer-eventswhen usingtransitionto simplify@starting-styleusage (#17812)
Fixed
- Don't scan
.geojsonor.dbfiles for classes by default (#17700, #17711) - Hide default shadow suggestions when missing default shadow theme keys (#17743)
- Replace
_with.in theme suggestions for@utilityif surrounded by digits (#17733) - Skip
color-mix(…)when opacity is100%(#17815) - PostCSS: Ensure that errors in imported stylesheets are recoverable (#17754)
- Upgrade: Bump all Tailwind CSS related dependencies during upgrade (#17763)
- Upgrade: Don't add
-to variants starting with@(#17814) - Upgrade: Don't format stylesheets that didn't change when upgrading (#17824)
Added
- Add experimental
@tailwindcss/oxide-wasm32-wasitarget for running Tailwind in browser environments like StackBlitz (#17558)
Fixed
- Ensure
color-mix(…)polyfills do not cause used CSS variables to be removed (#17555) - Ensure
color-mix(…)polyfills create fallbacks for theme variables that reference other theme variables (#17562) - Fix brace expansion in declining ranges like
{10..0..5}and{0..10..-5}(#17591) - Work around a Chrome rendering bug when using the
skew-*utilities (#17627) - Ensure container query variant names can contain hyphens (#17628)
- Ensure
shadow-inherit,inset-shadow-inherit,drop-shadow-inherit, andtext-shadow-inheritinherit the shadow color (#17647) - Ensure compatibility with array tuples used in
fontSizeJS theme keys (#17630) - Ensure folders with binary file extensions in their names are scanned for utilities (#17595)
- Upgrade: Convert
fontSizearray tuple syntax to CSS theme variables (#17630)
Fixed
- Don't rely on the presence of
@layer baseto polyfill@property(#17506) - Support setting multiple inset shadows as arbitrary values (#17523)
- Fix
drop-shadow-*utilities that are defined with multiple shadows (#17515) - PostCSS: Fix race condition when two changes are queued concurrently (#17514)
- PostCSS: Ensure files containing
@tailwind utilitiesare processed (#17514) - Ensure the
color-mix(…)polyfill creates fallbacks even when using colors that cannot be statically analyzed (#17513) - Fix slow incremental builds with
@tailwindcss/viteand@tailwindcss/postscss(especially on Windows) (#17511) - Vite: Fix missing CSS file in Qwik setups (#17533)
Added
- Add
details-contentvariant (#15319) - Add
inverted-colorsvariant (#11693) - Add
noscriptvariant (#11929, #17431) - Add
items-baseline-lastandself-baseline-lastutilities (#13888, #17476) - Add
pointer-none,pointer-coarse, andpointer-finevariants (#16946) - Add
any-pointer-none,any-pointer-coarse, andany-pointer-finevariants (#16941) - Add safe alignment utilities (#14607)
- Add
user-validanduser-invalidvariants (#12370) - Add
wrap-anywhere,wrap-break-word, andwrap-normalutilities (#12128) - Add
@source inline(…)and@source not inline(…)(#17147) - Add
@source not "…"(#17255) - Add
text-shadow-*utilities (#17389) - Add
mask-*utilities (#17134) - Add
bg-{position,size}-*utilities for arbitrary values (#17432) - Add
shadow-*/<alpha>,inset-shadow-*/<alpha>,drop-shadow-*/<alpha>, andtext-shadow-*/<alpha>utilities to control shadow opacity (#17398, #17434) - Add
drop-shadow-<color>utilities (#17434) - Improve compatibility with older versions of Safari and Firefox (#17435)
Fixed
- Follow symlinks when resolving
@sourcedirectives (#17391) - Don't scan ignored files for classes when changing an ignored file triggers a rebuild using
@tailwindcss/cli(#17255) - Support negated
contentrules in legacy JavaScript configuration (#17255) - Interpret syntax like
@("@")md:…as@md:…in Razor files (#17427) - Disallow top-level braces, top-level semicolons, and unbalanced parentheses and brackets in arbitrary values (#17361)
- Ensure the
--theme(…)function still resolves to the CSS variables when using legacy JS plugins (#17458) - Detect used theme variables in CSS module files (#17433, #17467)
Changed
- Ignore
node_modulesby default (can be overridden by@source …rules) (#17255) @sourcerules that include file extensions or point insidenode_modules/folders no longer consider your.gitignorerules (#17255)- Deprecate
bg-{left,right}-{top,bottom}in favor ofbg-{top,bottom}-{left,right}utilities (#17378) - Deprecate
object-{left,right}-{top,bottom}in favor ofobject-{top,bottom}-{left,right}utilities (#17437)
Added
- Add support for literal values in
--value('…')and--modifier('…')(#17304)
Fixed
- Fix class extraction followed by
(in Pug (#17320) - Ensure
@keyframesfor theme animations are emitted if they are referenced following a comma (#17352) - Vite: Ensure that updates to an imported CSS file are properly propagated after updating source files (#17347)
- Pre process
Slimtemplates embedded in Ruby files (#17336) - Error when input and output files resolve to the same file when using the CLI (#17311)
- Add missing suggestions when
--spacing(--value(integer, number))is used (#17308) - Add
::-webkit-details-markerpseudo tomarkervariant (#17362)
Fixed
- Fix incorrect angle in
-bg-conic-*utilities (#17174) - Fix
border-[12px_4px]being interpreted as aborder-colorinstead of aborder-width(#17248) - Work around a crash in Safari 16.4 and 16.5 when using the default Preflight styles (#17306)
- Pre-process
<template lang="…">in Vue files (#17252) - Ensure that all CSS variables used by Preflight are prefixed (#17036)
- Prevent segfault when loaded in a worker thread on Linux (#17276)
- Ensure multiple
--value(…)or--modifier(…)calls don't delete subsequent declarations (#17273) - Fix class extraction followed by
(in Slim (#17278) - Export
PluginUtilsfromtailwindcss/pluginfor compatibility with v3 (#17299) - Remove redundant
line-height: initialfrom Preflight (#15212) - Increase Standalone hardware compatibility on macOS x64 builds (#17267)
- Ensure that the CSS file rebuilds if a new CSS variable is used from templates (#17301)
Changed
- The
--theme(…)function now returns CSS variables from your theme variables unless used inside positions where CSS variables are invalid (e.g. inside@mediaqueries) (#17036)
Fixed
- Fix Haml pre-processing (#17051)
- Ensure
.nodeand.wasmfiles are not scanned for utilities (#17123) - Improve performance when scanning JSON files (#17125)
- Fix extracting candidates containing dots in Haml, Pug, and Slim pre processors (#17094, #17085, #17113)
- Don't create invalid CSS when encountering a link wrapped in square brackets (#17129)
Fixed
- Vite: Fix
url(…)rebasing in transitively imported CSS files (#16965) - PostCSS: Rebase
url(…)s in imported CSS files (#16965) - Ensure utilities are sorted based on their actual property order (#16995)
- Ensure strings in Pug and Slim templates are handled correctly (#17000)
- Ensure classes between
}and{are properly extracted (#17001) - Fix
razor/cshtmlpre-processing (#17027) - Ensure extracting candidates from JS embedded in a PHP string works as expected (#17031)
Fixed
- Ensure classes containing
--are extracted correctly (#16972) - Ensure classes containing numbers followed by dash or underscore are extracted correctly (#16980)
- Ensure arbitrary container queries are extracted correctly (#16984)
- Ensure classes ending in
[are extracted in Slim templating language (#16985) - Ensure arbitrary variables with data types are extracted correctly (#16986)
Added
- Add
col-<number>androw-<number>utilities forgrid-columnandgrid-row(#15183)
Fixed
- Ensure
not-*does not remove:is(…)from variants (#16825) - Ensure
@keyframesare correctly emitted when using a prefix (#16850) - Don't swallow
@utilitydeclarations when@applyis used in nested rules (#16940) - Ensure
outline-hiddenbehaves likeoutline-noneoutside of forced colors mode (#16943) - Allow
!importanton CSS variables again (#16873) - Vite: Do not crash when encountering an
.svgfile with#or?in the filename (#16957) - Ensure utilities are properly detected within square brackets (#16306)
- Ensure utilities are properly detected using Angular's conditional class binding syntax (#16306)
- Ensure utilities starting with numbers are properly extracted from Slim templates (#16306)
- Discard arbitrary property candidates that have guaranteed-invalid property names (#16306)
Changed
Fixed
- Make JS APIs available to plugins and configs in the Standalone CLI (#15934)
- Vite: Don't crash when importing a virtual module from JavaScript that ends in
.css(#16780) - Fix an issue where
@reference "…"would sometimes omit keyframe animations (#16774) - Ensure
z-*!utilities are properly marked as!important(#16795) - Read UTF-8 CSS files that start with a byte-order mark (BOM) (#16800)
- Ensure nested functions in selectors used with JavaScript plugins are not truncated (#16802)
Changed
- Emit variable fallbacks when using
@reference "…"instead of duplicate CSS variable declarations (#16774)
Added
- Allow
@importwiththeme(…)options for stylesheets that contain more than just@themerules (#16514)
Fixed
- Don't add
!importantto CSS variable declarations when using the important modifier (#16668) - Vite: Ignore files and directories specified in your
.gitignorefile when using automatic source detection(#16631) - Vite: Don't rely on the module graph for detecting candidates to ensure setups with multiple Vite builds work as expected (#16631)
- Vite: Ensure Astro production builds always contain classes used in client-only components (#16631)
- Vite: Always scan raw file contents for utility classes before any other transforms have been applied to ensure utility classes are scanned without any additional escaping (#16631)
- Ensure utilities with more declarations are always sorted before utilities with fewer declarations when utilities only define CSS variables (#16715)
- Only include
translate-z-pxutilities once in compiled CSS (#16718)
Changed
Fixed
- Export
tailwindcss/lib/util/flattenColorPalette.jsfor backward compatibility (#16411) - Fix sorting of numeric utility suggestions when they have different magnitudes (#16414)
- Show suggestions for fractions in IntelliSense (#16353)
- Don’t replace
_in suggested theme keys (#16433) - Ensure
--default-outline-widthcan be used to change theoutline-widthvalue of theoutlineutility (#16469) - Ensure drop shadow utilities don't inherit unexpectedly (#16471)
- Export config and plugin types from
tailwindcss/pluginfor backward compatibility (#16505) - Ensure JavaScript plugins that emit nested rules referencing the utility name work as expected (#16539)
- Statically link Visual Studio redistributables in
@tailwindcss/oxideWindows builds (#16602) - Ensure that Next.js splat routes are scanned for classes (#16457)
- Pin exact version of
tailwindcssin@tailwindcss/*packages (#16623) - Upgrade: Report errors when updating dependencies (#16504)
- Upgrade: Ensure a
darkModeJS config setting with block syntax converts to use@slot(#16507) - Upgrade: Ensure the latest version of
tailwindcssand@tailwindcss/postcssare installed when upgrading (#16620)
Fixed
- Revert change to no longer include theme variables that aren't used in compiled CSS (#16403)
Fixed
- Fix a crash when setting JS theme values to
null(#16210) - Ensure escaped underscores in CSS variables in arbitrary values are properly unescaped (#16206)
- Ensure that the
containersJS theme key is added to the--container-*namespace (#16169) - Ensure theme
@keyframesare generated even if an--animation-*variable spans multiple lines (#16237) - Vite: Skip parsing stylesheets with the
?commonjs-proxyflag (#16238) - Fix
order-firstandorder-lastfor Firefox (#16266) - Fix support for older instruction sets on Linux x64 builds of the standalone CLI (#16244)
- Ensure
NODE_PATHis respected when resolving JavaScript and CSS files (#16274) - Ensure Node addons are packaged correctly with FreeBSD builds (#16277)
- Fix an issue where
@variantinside a referenced stylesheet could cause a stack overflow (#16300)
Fixed
- Only generate positive
grid-cols-*andgrid-rows-*utilities (#16020) - Ensure escaped theme variables are handled correctly (#16064)
- Ensure we process Tailwind CSS features when only using
@referenceor@variant(#16057) - Refactor gradient implementation to work around prettier/prettier#17058 (#16072)
- Vite: Ensure hot-reloading works with SolidStart setups (#16052)
- Vite: Fix a crash when starting the development server in SolidStart setups (#16052)
- Vite: Don't rebase URLs that appear to be aliases (#16078)
- Vite: Transform
<style>blocks in HTML files (#16069) - Prevent camel-casing CSS custom properties added by JavaScript plugins (#16103)
- Do not emit
@keyframesin@theme reference(#16120) - Discard invalid declarations when parsing CSS (#16093)
- Do not emit empty CSS rules and at-rules (#16121)
- Handle
@variantwhen at the top-level of a stylesheet (#16129)
Added
- Include
:openpseudo-class in existingopenvariant (#15349)
Fixed
- Remove invalid
min-w/h-noneutilities (#15845) - Discard CSS variable shorthand utilities that don't use valid CSS variables (#15738)
- Ensure font-size utilities with
nonemodifier have a line-height set e.g.text-sm/none(#15921) - Ensure font-size utilities with unknown modifier don't generate CSS (#15921)
- Don’t suggest font weight utilities more than once (#15857)
- Suggest container query variants (#15857)
- Disable bare value suggestions when not using the
--spacingvariable (#15857) - Ensure suggested classes are properly sorted (#15857)
- Don’t look at .gitignore files outside initialized repos (#15941)
- Find utilities when using the Svelte class shorthand syntax across multiple lines (#15974)
- Find utilities when using the Angular class shorthand syntax (#15974)
- Find utilities when using functions inside arrays (#15974)
- Ensure that
@tailwindcss/browserdoes not pollute the global namespace (#15978) - Ensure that
tailwind-mergeis not scanned when using the Vite plugin (#16005) - Ensure CSS theme variables are available within shadow roots (#15975)
- Fix crash when project lives in the
/directory (#15988) - Ensure custom variants have a non-empty selector list (#16009)
- Upgrade: Ensure JavaScript config files on different drives are correctly migrated (#15927)
- Upgrade: Migrate
leading-[1]toleading-none(#16004) - Upgrade: Do not migrate arbitrary leading utilities to bare values (#16004)
Holy shit it's actually done — we just tagged Tailwind CSS v4.0.
Tailwind CSS v4.0 is an all-new version of the framework optimized for performance and flexibility, with a reimagined configuration and customization experience, and taking full advantage of the latest advancements the web platform has to offer.
- New high-performance engine — where full builds are up to 5x faster, and incremental builds are over 100x faster — and measured in microseconds.
- Designed for the modern web — built on cutting-edge CSS features like cascade layers, registered custom properties with
@property, andcolor-mix(). - Simplified installation — fewer dependencies, zero configuration, and just a single line of code in your CSS file.
- First-party Vite plugin — tight integration for maximum performance and minimum configuration.
- Automatic content detection — all of your template files are discovered automatically, with no configuration required.
- Built-in import support — no additional tooling necessary to bundle multiple CSS files.
- CSS-first configuration — a reimagined developer experience where you customize and extend the framework directly in CSS instead of a JavaScript configuration file.
- CSS theme variables — all of your design tokens exposed as native CSS variables so you can access them anywhere.
- Dynamic utility values and variants — stop guessing what values exist in your spacing scale, or extending your configuration for things like basic data attributes.
- Modernized P3 color palette — a redesigned, more vivid color palette that takes full advantage of modern display technology.
- Container queries — first-class APIs for styling elements based on their container size, no plugins required.
- New 3D transform utilities — transform elements in 3D space directly in your HTML.
- Expanded gradient APIs — radial and conic gradients, interpolation modes, and more.
- @starting-style support — a new variant you can use to create enter and exit transitions, without the need for JavaScript.
- not-* variant — style an element only when it doesn't match another variant, custom selector, or media or feature query.
- Even more new utilities and variants — including support for
color-scheme,field-sizing, complex shadows,inert, and more.
Start using Tailwind CSS v4.0 today by installing it in a new project, or playing with it directly in the browser on Tailwind Play.
For existing projects, we've published a comprehensive upgrade guide and built an automated upgrade tool to get you on the latest version as quickly and painlessly as possible.
For a deep-dive into everything that's new, check out the announcement post.
Fixed
- Improve support for raw
supports-[…]queries in arbitrary values (#13605) - Fix
require.cacheerror when loaded through a TypeScript file in Node 22.18+ (#18665) - Support
import.meta.resolve(…)in configs for new enough Node.js versions (#18938) - Allow using newer versions of
postcss-load-configfor better ESM and TypeScript PostCSS config support with the CLI (#18938) - Remove irrelevant utility rules when matching important classes (#19030)
Fixed
- Ensure using
@applywith utilities that use@defaultsworks with rules defined in the base layer when usingoptimizeUniversalDefaults(#14427)
Fixed
- No longer warns when broad glob patterns are detecting
vendorfolders
Fixed
- Disable automatic
var()injection for anchor properties (#13826) - Use no value instead of
blur(0px)forbackdrop-blur-noneandblur-noneutilities (#13830) - Add
.mtsand.ctsconfig file detection (#13940) - Don't generate utilities like
px-1unnecessarily when using utilities likepx-1.5(#13959) - Always generate
-webkit-backdrop-filterforbackdrop-*utilities (#13997)
Fixed
- Make it possible to use multiple
<alpha-value>placeholders in a single color definition (#13740) - Don't prefix classes in arbitrary values of
has-*,group-has-*, andpeer-has-*variants (#13770) - Support negative values for
{col,row}-{start,end}utilities (#13781) - Update embedded browserslist database (#13792)
Fixed
- Ensure max specificity of
0,0,1for button and input Preflight rules (#12735) - Improve glob handling for folders with
(,),[or]in the file path (#12715) - Split
:hasrules when usingexperimental.optimizeUniversalDefaults(#12736) - Sort arbitrary properties alphabetically across multiple class lists (#12911)
- Add
mix-blend-plus-darkerutility (#12923) - Ensure dashes are allowed in variant modifiers (#13303)
- Fix crash showing completions in Intellisense when using a custom separator (#13306)
- Transpile
import.meta.urlin config files (#13322) - Reset letter spacing for form elements (#13150)
- Fix missing
xx-largeand remove doublex-largeabsolute size (#13324) - Don't error when encountering nested CSS unless trying to
@applya class that uses nesting (#13325) - Ensure that arbitrary properties respect
importantconfiguration (#13353) - Change dark mode selector so
@applyworks correctly with pseudo elements (#13379)
Fixed
- Don't remove keyframe stops when using important utilities (#12639)
- Don't add spaces to gradients and grid track names when followed by
calc()(#12704) - Restore old behavior for
classdark mode strategy (#12717)
Added
- Add new
selectorandvariantstrategies for dark mode (#12717)
Changed
- Support
rtlandltrvariants on same element asdirattribute (#12717)
Tailwind CSS v3.4 has arrived! Check out the announcement post for a guided tour through all of the highlights.
Added
- Add
svh,lvh, anddvhvalues to defaultheight/min-height/max-heighttheme (#11317) - Add
has-*variants for:has(...)pseudo-class (#11318) - Add
text-wraputilities includingtext-balanceandtext-pretty(#11320, #12031) - Extend default
opacityscale to include all steps of 5 (#11832) - Update Preflight
htmlstyles to include shadow DOM:hostpseudo-class (#11200) - Increase default values for
grid-rows-*utilities from 1–6 to 1–12 (#12180) - Add
size-*utilities (#12287) - Add utilities for CSS subgrid (#12298)
- Add spacing scale to
min-w-*,min-h-*, andmax-w-*utilities (#12300) - Add
forced-color-adjustutilities (#11931) - Add
forced-colorsvariant (#11694, #12582) - Add
appearance-autoutility (#12404) - Add logical property values for
floatandclearutilities (#12480) - Add
*variant for targeting direct children (#12551)
Changed
Fixed
- Don’t add spaces to negative numbers following a comma (#12324)
- Don't emit
@configin CSS when watching via the CLI (#12327) - Improve types for
resolveConfig(#12272) - Ensure configured
font-feature-settingsformonoare included in Preflight (#12342) - Improve candidate detection in minified JS arrays (without spaces) (#12396)
- Don't crash when given applying a variant to a negated version of a simple utility (#12514)
- Fix support for slashes in arbitrary modifiers (#12515)
- Fix source maps of variant utilities that come from an
@layerrule (#12508) - Fix loading of built-in plugins when using an ESM or TypeScript config with the Standalone CLI (#12506)
Fixed
- Improve normalisation of
calc()-like functions (#11686) - Skip
calc()normalisation in nestedtheme()calls (#11705) - Fix incorrectly generated CSS when using square brackets inside arbitrary properties (#11709)
- Make
contentoptional for presets in TypeScript types (#11730) - Handle variable colors that have variable fallback values (#12049)
- Batch reading content files to prevent
too many open fileserror (#12079) - Skip over classes inside
:not(…)when nested in an at-rule (#12105) - Update types to work with
Node16module resolution (#12097) - Don’t crash when important and parent selectors are equal in
@apply(#12112) - Eliminate irrelevant rules when applying variants (#12113)
- Improve RegEx parser, reduce possibilities as the key for arbitrary properties (#12121)
- Fix sorting of utilities that share multiple candidates (#12173)
- Ensure variants with arbitrary values and a modifier are correctly matched in the RegEx based parser (#12179)
- Fix crash when watching renamed files on FreeBSD (#12193)
- Allow plugins from a parent document to be used in an iframe (#12208)
- Add types for
tailwindcss/nesting(#12269) - Bump
jiti,fast-glob, andbrowserlistdependencies (#11550) - Improve automatic
varinjection for properties that accept a<dashed-ident>(#12236)
Fixed
- Fix issue where some pseudo-element variants generated the wrong selector (#10943, #10962, #11111)
- Make font settings propagate into buttons, inputs, etc. (#10940)
- Fix parsing of
theme()insidecalc()when there are no spaces around operators (#11157) - Ensure
repeating-conic-gradientis detected as an image (#11180) - Move unknown pseudo-elements outside of
:isby default (#11345) - Escape animation names when prefixes contain special characters (#11470)
- Don't prefix arbitrary classes in
groupandpeervariants (#11454) - Sort classes using position of first matching rule (#11504)
- Allow variant to be an at-rule without a prelude (#11589)
- Make PostCSS plugin async to improve performance (#11548)
- Don’t error when a config file is missing (f97759f)
Added
- Add
aria-busyutility (#10966)
Changed
- Reset padding for
<dialog>elements in preflight (#11069)
Fixed
- Don’t move unknown pseudo-elements to the end of selectors (#10943, #10962)
- Inherit gradient stop positions when using variants (#11002)
- Honor default
toposition of gradient when using implicit transparent colors (#11002) - Ensure
@tailwindcss/oxidedoesn't leak in the stable engine (#10988) - Ensure multiple
theme(spacing[5])calls with bracket notation in arbitrary properties work (#11039) - Normalize arbitrary modifiers (#11057)
Changed
- Drop support for Node.js v12 (#11089)
Fixed
- Fix edge case bug when loading a TypeScript config file with webpack (#10898)
- Fix variant,
@apply, andimportantselectors when using:is()or:has()with pseudo-elements (#10903) - Fix
safelistconfig types (#10901) - Fix build errors caused by
@tailwindcss/line-clampwarning (#10915, #10919) - Fix "process is not defined" error (#10919)
Tailwind CSS v3.3 is here! Check out the announcement post for a deep dive into all of the cool new stuff.
Added
- Support ESM and TypeScript config files (#10785)
- Extend default color palette with new 950 shades (#10879)
- Add
line-heightmodifier support tofont-sizeutilities (#9875) - Add support for using variables as arbitrary values without
var(...)(#9880, #9962) - Add logical properties support for inline direction (#10166)
- Add
hyphensutilities (#10071) - Add
from-{position},via-{position}andto-{position}utilities (#10886) - Add
list-style-imageutilities (#10817) - Add
caption-sideutilities (#10470) - Add
line-clamputilities from@tailwindcss/line-clampto core (#10768, #10876, #10862) - Add
delay-0andduration-0utilities (#10294) - Add
justify-normalandjustify-stretchutilities (#10560) - Add
content-normalandcontent-stretchutilities (#10645) - Add
whitespace-break-spacesutility (#10729) - Add support for configuring default
font-variation-settingsfor afont-family(#10034, #10515)
Fixed
- Disallow using multiple selectors in arbitrary variants (#10655)
- Sort class lists deterministically for Prettier plugin (#10672)
- Ensure CLI builds have a non-zero exit code on failure (#10703)
- Ensure module dependencies for value
null, is an emptySet(#10877) - Fix format assumption when resolving module dependencies (#10878)
Changed
Added
- Add standalone CLI build for 64-bit Windows on ARM (
node16-win-arm64) (#10001)
Fixed
- Cleanup unused
variantOrder(#9829) - Fix
foo-[abc]/[def]not being handled correctly (#9866) - Add container queries plugin to standalone CLI (#9865)
- Support renaming of output files by PostCSS plugins in CLI (#9944)
- Improve return value of
resolveConfig, unwrapResolvableTo(#9972) - Clip unbalanced brackets in arbitrary values (#9973)
- Don’t reorder webkit scrollbar pseudo elements (#9991)
- Deterministic sorting of arbitrary variants (#10016)
- Add
datakey to theme types (#10023) - Prevent invalid arbitrary variant selectors from failing the build (#10059)
- Properly handle subtraction followed by a variable (#10074)
- Fix missing
string[]in thetheme.dropShadowtypes (#10072) - Update list of length units (#10100)
- Fix not matching arbitrary properties when closely followed by square brackets (#10212)
- Allow direct nesting in
rootor@layernodes (#10229) - Don't prefix classes in arbitrary variants (#10214)
- Fix perf regression when checking for changed content (#10234)
- Fix missing
blocklistmember in theConfigtype (#10239) - Escape group names in selectors (#10276)
- Consider earlier variants before sorting functions (#10288)
- Allow variants with slashes (#10336)
- Ensure generated CSS is always sorted in the same order for a given set of templates (#10382)
- Handle variants when the same class appears multiple times in a selector (#10397)
- Handle group/peer variants with quoted strings (#10400)
- Parse alpha value from rgba/hsla colors when using variables (#10429)
- Sort by
layerinsidevariantslayer (#10505) - Add
--watch=alwaysoption to prevent exit when stdin closes (#9966)
Changed
Fixed
- Escape special characters in resolved content base paths (#9650)
- Don't reuse container for array returning variant functions (#9644)
- Exclude non-relevant selectors when generating rules with the important modifier (#9677)
- Fix merging of arrays during config resolution (#9706)
- Ensure configured
font-feature-settingsare included in Preflight (#9707) - Fix fractional values not being parsed properly inside arbitrary properties (#9705)
- Fix incorrect selectors when using
@applyin selectors with combinators and pseudos (#9722) - Fix cannot read properties of undefined (reading 'modifier') (#9656, aa979d6)
We just released Tailwind CSS v3.2! Read the announcement post for more details about the most exciting new features.
Added
- Add new
@configdirective (#9405) - Add new
relative: trueoption to resolve content paths relative to the config file (#9396) - Add new
supports-*variant (#9453) - Add new
min-*andmax-*variants (#9558) - Add new
aria-*variants (#9557, #9588) - Add new
data-*variants (#9559, #9588) - Add new
break-keeputility forword-break: keep-all(#9393) - Add new
collapseutility forvisibility: collapse(#9181) - Add new
fill-noneutility forfill: none(#9403) - Add new
stroke-noneutility forstroke: none(#9403) - Add new
place-content-baselineutility forplace-content: baseline(#9498) - Add new
place-items-baselineutility forplace-items: baseline(#9507) - Add new
content-baselineutility foralign-content: baseline(#9507) - Add support for configuring default
font-feature-settingsfor a font family (#9039) - Add standalone CLI build for 32-bit Linux on ARM (
node16-linux-armv7) (#9084) - Add future flag to disable color opacity utility plugins (#9088)
- Add negative value support for
outline-offset(#9136) - Add support for modifiers to
matchUtilities(#9541) - Allow negating utilities using
min/max/clamp(#9237) - Implement fallback plugins when there is ambiguity between plugins when using arbitrary values (#9376)
- Support
sortfunction inmatchVariant(#9423) - Upgrade to
postcss-nestedv6.0 (#9546)
Fixed
- Use absolute paths when resolving changed files for resilience against working directory changes (#9032)
- Fix ring color utility generation when using
respectDefaultRingColorOpacity(#9070) - Sort tags before classes when
@apply-ing a selector with joined classes (#9107) - Remove invalid
outline-hiddenutility (#9147) - Honor the
hiddenattribute on elements in preflight (#9174) - Don't stop watching atomically renamed files (#9173, #9215)
- Fix duplicate utilities issue causing memory leaks (#9208)
- Fix
fontFamilyconfig TypeScript types (#9214) - Handle variants on complex selector utilities (#9262)
- Fix shared config mutation issue (#9294)
- Fix ordering of parallel variants (#9282)
- Handle variants in utility selectors using
:where()and:has()(#9309) - Improve data type analysis for arbitrary values (#9320)
- Don't emit generated utilities with invalid uses of theme functions (#9319)
- Revert change that only listened for stdin close on TTYs (#9331)
- Ignore unset values (like
nullorundefined) when resolving the classList for intellisense (#9385) - Improve type checking for formal syntax (#9349, #9448)
- Fix incorrect required
contentkey in custom plugin configs (#9502, #9545) - Fix content path detection on Windows (#9569)
- Ensure
--contentis used in the CLI when passed (#9587)
Added
- Support configuring a default
font-weightfor each font size utility (#8763) - Add support for alpha values in safe list (#8774)
Fixed
- Improve types to support fallback values in the CSS-in-JS syntax used in plugin APIs (#8762)
- Support including
tailwindcssandautoprefixerinpostcss.config.jsin standalone CLI (#8769) - Fix using special-characters as prefixes (#8772)
- Don’t prefix classes used within arbitrary variants (#8773)
- Add more explicit types for the default theme (#8780)
Fixed
- Fix extraction of multi-word utilities with arbitrary values and quotes (#8604)
- Fix casing of import of
corePluginListtype definition (#8587) - Ignore PostCSS nodes returned by
addVariant(#8608) - Fix missing spaces around arithmetic operators (#8615)
- Detect alpha value in CSS
theme()function when using quotes (#8625) - Fix "Maximum call stack size exceeded" bug (#8636)
- Allow functions returning parallel variants to mutate the container (#8622)
- Remove text opacity CSS variables from
::marker(#8622)
We just released Tailwind CSS v3.1 — the first new feature release since v3.0 came out last year!
Read the announcement post for all the details, and watch the YouTube video for a tour of some of the highlights.
Added
- Support PostCSS
Documentnodes (#7291) - Add
text-startandtext-endutilities (#6656) - Support customizing class name when using
darkMode: 'class'(#5800) - Add
--polloption to the CLI (#7725) - Add new
border-spacingutilities (#7102) - Add
enabledvariant (#7905) - Add TypeScript types for the
tailwind.config.jsfile (#7891) - Add
backdropvariant (#7924, #8526) - Add
grid-flow-denseutility (#8193) - Add
mix-blend-plus-lighterutility (#8288) - Add arbitrary variants (#8299)
- Add experimental
matchVariantAPI (#8310, 34fd0fb8) - Add
prefers-contrastmedia query variants (#8410) - Add opacity support when referencing colors with
themefunction (#8416) - Add
postcss-importsupport to the CLI (#8437) - Add
optionalvariant (#8486) - Add
<alpha-value>placeholder support for custom colors (#8501)
Fixed
- Types: allow for arbitrary theme values (for 3rd party plugins) (#7926)
- Don’t split vars with numbers in them inside arbitrary values (#8091)
- Require matching prefix when detecting negatives (#8121)
- Handle duplicate At Rules without children (#8122)
- Allow arbitrary values with commas in
@apply(#8125) - Fix intellisense for plugins with multiple
@applyrules (#8213) - Improve type detection for arbitrary color values (#8201)
- Support PostCSS config options in config file in CLI (#8226)
- Remove default
[hidden]style in preflight (#8248) - Only check selectors containing base apply candidates for circular dependencies (#8222)
- Rewrite default class extractor (#8204)
- Move
importantselector to the front when@apply-ing selector-modifying variants in custom utilities (#8313) - Error when registering an invalid custom variant (#8345)
- Create tailwind.config.cjs file in ESM package when running init (#8363)
- Fix
matchVariantsthat use at-rules and placeholders (#8392) - Improve types of the
tailwindcss/plugin(#8400) - Allow returning parallel variants from
addVariantormatchVariantcallback functions (#8455) - Try using local
postcssinstallation first in the CLI (#8270) - Allow default ring color to be a function (#7587)
- Don't inherit
tovalue from parent gradients (#8489) - Remove process dependency from log functions (#8530)
- Ensure we can use
@import 'tailwindcss/...'without node_modules (#8537)
Changed
Fixed
- Prevent nesting plugin from breaking other plugins (#7563)
- Recursively collapse adjacent rules (#7565)
- Preserve source maps for generated CSS (#7588)
- Split box shadows on top-level commas only (#7479)
- Use local user CSS cache for
@apply(#7524) - Invalidate context when main CSS changes (#7626)
- Only add
!to selector class matching template candidate when using important modifier with multi-class selectors (#7664) - Correctly parse and prefix animation names with dots (#7163)
- Fix extraction from template literal/function with array (#7481)
- Don't output unparsable arbitrary values (#7789)
- Fix generation of
div:not(.foo)if.foois never defined (#7815) - Allow for custom properties in
rgb,rgba,hslandhslacolors (#7933) - Remove autoprefixer as explicit peer-dependency to avoid invalid warnings in situations where it isn't actually needed (#7949)
- Ensure the
percentagedata type is validated correctly (#8015)
Changed
Fixed
- Fix preflight border color fallback (#7288)
- Correctly parse shadow lengths without a leading zero (#7289)
- Don't crash when scanning extremely long class candidates (#7331)
- Use less hacky fix for URLs detected as custom properties (#7275)
- Correctly generate negative utilities when dash is before the prefix (#7295)
- Detect prefixed negative utilities in the safelist (#7295)
Fixed
- Allow use of falsy values in theme config (#6917)
- Ensure we can apply classes that are grouped with non-class selectors (#6922)
- Improve standalone CLI compatibility on Linux by switching to the
linuxstaticbuild target (#6914) - Ensure
@applyworks consistently with or without@layer(#6938) - Only emit defaults when using base layer (#6926)
- Emit plugin defaults regardless of usage (#6926)
- Move default border color back to preflight (#6926)
- Change
experimental.optimizeUniversalDefaultsto only work with@tailwind base(#6926)
Fixed
- Improve
DEBUGflag (#6797, #6804) - Ensure we can use
<and>characters in modifiers (#6851) - Validate
theme()works in arbitrary values (#6852) - Properly detect
theme()value usage in arbitrary properties (#6854) - Improve collapsing of duplicate declarations (#6856)
- Remove support for
TAILWIND_MODE=watch(#6858)
Fixed
- Don't mutate custom color palette when overriding per-plugin colors (#6546)
- Improve circular dependency detection when using
@apply(#6588) - Only generate variants for non-
userlayers (#6589) - Properly extract classes with arbitrary values in arrays and classes followed by escaped quotes (#6590)
- Improve jsx interpolation candidate matching (#6593)
- Ensure
@applyof a rule inside an AtRule works (#6594)
Added
- Warn about invalid globs in
content(#6449) - Add standalone tailwindcss CLI (#6506)
- Add
lito list-style reset (00f60e6)
Fixed
- Don't output unparsable values (#6469)
- Fix text decoration utilities from overriding the new text decoration color/style/thickness utilities when used with a modifier (#6378)
- Move defaults to their own always-on layer (#6500)
- Support negative values in safelist patterns (6480)
Fixed
- Temporarily disable optimize universal defaults, fixes issue with transforms/filters/rings not being
@apply-able in CSS modules/Svelte components/Vue components (#6461)
Tailwind CSS v3.0 is here — bringing incredible performance gains, huge workflow improvements, and a seriously ridiculous number of new features.
Read the announcement post for all the details.
Added
- Add colored box shadow utilities (#5979)
- Add native
aspect-ratioutilities (#5359) - Add
columnutilities (#5457) - Add
break-before,break-insideandbreak-afterutilities (#5530) - Add
text-indentutilities (#5449) - Add
text-decoration-{color/style/thickness/offset}utilities (#5760, #6004) - Add
outline-style,outline-color,outline-widthandoutline-offsetutilities (#5887) - Add
align-subandalign-supervertical-align utilities (#5486) - Add
accent-colorutilities (#5387) - Add
scroll-snaputilities (#5637) - Add
scroll-behaviorutilities (#5388) - Add
touch-actionutilities (#5603, #6115) - Add
flex-basisutilities (#5671) - Add
grow-*andshrink-*utilities, deprecateflex-grow-*andflex-shrink-*(#5733) - Add
border-xandborder-ywidth and color utilities (#5639) - Add
border-hiddenutility (#5485) - Add
overflow-clip,overflow-x-clipandoverflow-y-cliputilities (#5630) - Add
inheritto default color palette (#5597) - Add full color palette for
fill-*andstroke-*utilities (#5933) - Add
fit-contentvalues formin/max-width/heightutilities (#5638) - Add
min/max-contentvalues formin/max-heightutilities (#5729) - Add
will-changeutilities (#5448) - Add all standard
cursor-*values by default (#5734) - Add
printvariant for targeting printed media (#5885) - Add
placeholdervariant (#6106) - Add
filevariant for::file-selector-buttonpseudo element (#4936) - Add
[open]variant (#5627) - Add
portraitandlandscapevariants (#6046) - Add
menureset to preflight (#6213) - Add comprehensive "arbitrary value" support (#5568, #6233, #6259, #6258, #6283)
- Add "arbitrary properties" support (#6161)
- Add first-class negative value support (#5709, c48e629)
- Add new declarative
addVariantAPI (#5809)
Changed
- Remove AOT engine, make JIT the default (#5340)
- Enable extended color palette by default with updated color names (#5384)
- Rename
overflow-cliptotext-clipandoverflow-ellipsistotext-ellipsis(#5630) - Deprecate
decoration-sliceanddecoration-breakin favorbox-decoration-sliceandbox-decoration-break(#6004) - Move
vertical-alignvalues to config file instead of hard-coding (#5487) - Throw when trying to
@applythegroupclass (#4666) - Remove dependency on
modern-normalize, inline and consolidate with Preflight (#5358) - Remove
prefixas a function (#5829) - Don't use pointer cursor on disabled buttons by default (#5772)
- Set default content value in preflight instead of within each before/after utility (#5820)
- Preserve original color format when adding opacity whenever possible (#5154)
- Unify config callback helpers into single object (#5382)
Thanks to everyone who contributed to this release: @95jonpet, @AviAvinav, @DavydeVries, @DoctorDerek, @MatteoGauthier, @MichaelAllenWarner, @RobinMalfait, @TCatinaud, @adamwathan, @bradlc, @bytedance, @codytooker, @dance2die, @dcastil, @ericbf, @geshii, @hardfist, @htunnicliff, @iksaku, @innocenzi, @kwaa, @lukewarlow, @nifte, @reinink, @sachinraja, @seanpdoyle, @xiBread, @xzfd1010
Fixed
- Configure chokidar's
awaitWriteFinishsetting to avoid occasional stale builds on Windows (#5758)
Fixed
- Ensure using CLI without
-ifor input file continues to work even though deprecated (#5464)
Fixed
- Only use
@defaultsin JIT, switch back toclean-cssin case there's any meaningful differences in the output (bf248cb)
Fixed
- Fix broken CDN build
Fixed
- Rebundle to fix missing CLI peer dependencies
Fixed
- Improve accessibility of default link focus styles in Firefox (#5082)
- JIT: Fix animation variants corrupting keyframes rules (#5223)
- JIT: Ignore escaped commas when splitting selectors to apply prefixes (#5239)
- Nesting: Maintain PostCSS node sources when handling
@apply(#5249) - JIT: Fix support for animation lists (#5252)
- JIT: Fix arbitrary value support for
object-positionutilities (#5245) - CLI: Abort watcher if stdin is closed to avoid zombie processes (#4997)
- JIT: Ignore arbitrary values with unbalanced brackets (#5293)
Fixed
- Temporarily revert runtime performance optimizations introduced in v2.2.5, use universal selector again (#5060)
Added
- Added
self-baselineutility (I know this is a patch release, no one's going to die relax) (#5000)
Changed
-
JIT: Optimize universal selector usage by inlining only the relevant selectors (#4850))
This provides a very significant performance boost on pages with a huge number of DOM nodes, but there's a chance it could be a breaking change in very rare edge cases we haven't thought of. Please open an issue if anything related to shadows, rings, transforms, filters, or backdrop-filters seems to be behaving differently after upgrading.
Fixed
- Fix support for
step-startandstep-endin animation utilities (#4795)) - JIT: Prevent presence of
!*in templates from ruining everything (#4816)) - JIT: Improve support for quotes in arbitrary values (#4817))
- Fix filter/backdrop-filter/transform utilities being inserted into the wrong position if not all core plugins are enabled (#4852))
- JIT: Fix
@layerrules being mistakenly inserted during incremental rebuilds (#4853)) - Improve build performance for projects with many small non-Tailwind stylesheets (#4644)
- Ensure
[hidden]works as expected on elements where we override the defaultdisplayvalue in Preflight (#4873) - Fix variant configuration not being applied to
backdropOpacityutilities (#4892)
Fixed
- Remove
postinstallscript that was preventing people from installing the library (1eacfb9)
Added
- Pass extended color palette to theme closures so it can be used without installing Tailwind when using
npx tailwindcss(359252c)
Fixed
- JIT: Explicitly error when
-is used as a custom separator (#4704) - JIT: Don't add multiple
~when stackingpeer-*variants (#4757) - Remove outdated focus style fix in Preflight (#4780)
- Enable
purgeif provided on the CLI (#4772) - JIT: Fix error when not using a config file with postcss-cli (#4773)
- Fix issue with
resolveConfignot being importable in Next.js pages (#4725)
Fixed
- JIT: Reintroduce
transform,filter, andbackdrop-filterclasses purely to create stacking contexts to minimize the impact of the breaking change (#4700)
Tailwind CSS v2.2.0
Six weeks ago I didn't even have v2.2 on my roadmap and yet somehow here we are today, with one of the biggest Tailwind CSS feature releases of all-time?!
This release is loaded with tons of cool new stuff, mostly targeting the new Just-in-Time mode which unlocks so many cool ideas we probably couldn't have pulled off if we had to keep being mindful of the CSS file size in development.
To upgrade, install the latest version via npm:
npm install -D tailwindcss@latest
Note that we've had to make a couple small changes to the JIT engine as we've added features, fixed bugs, and improved the overall reliability, so make sure to read about the changes and deprecations when upgrading if you are using just-in-time mode.
-
- All-new improved Tailwind CLI
- Before and after variants
- First-letter/line variants
- Selected text variants
- List marker variants
- Sibling selector variants
- Exhaustive pseudo-class support
- Shorthand color opacity syntax
- Extended arbitrary value support
- Improved nesting support
- Caret color utilities
- Background origin utilities
- Simplified transform and filter composition
- Per-side border color utilities
- Built-in safelist, transform, and extract support
New features
All-new improved Tailwind CLI
We've rewritten the Tailwind CLI tool from the ground-up with a performance-first mindset, while also adding support for a bunch of new features.
npx tailwindcss -o dist/tailwind.css --watch --jit --purge="./src/**/*.html"
Here are some of the highlights:
- No installation or configuration necessary — simply
npx tailwindcss -o output.cssto compile Tailwind from anywhere. You can even enable JIT mode with the--jitflag and pass in your content files using the--purgeoption, all without creating a config file. - Watch mode — so you can automatically rebuild your CSS whenever you make any changes.
- JIT performance optimizations — since our CLI is Tailwind-specific we've been able to make tons of optimizations that make it the absolute fastest build tool for compiling your CSS in JIT mode.
- Minification support — now you can minify your CSS with cssnano just by adding the
--minifyflag. - PostCSS plugin support — the new CLI will read and respect any extra plugins you configure using a
postcss.config.jsfile.
It's fully backwards-compatible with the previous CLI, so if you've got any scripts set up already you should be able to upgrade to v2.2 without making any changes to your scripts.
Check out our updated Tailwind CLI documentation to learn more.
Note that if you were using the tailwindcss-cli wrapper package, you can safely switch to tailwindcss as we've managed to resolve the peer-dependency issues that forced us to create the wrapper package in the first place.
Before and after pseudo-element variants (#4461)
This feature is only available in Just-in-Time mode.
People have been asking for this for years and it's finally here! We've added first-party support for styling pseudo-elements like before and after:
<div class="before:block before:bg-blue-500 after:flex after:bg-pink-300"></div>
We set content: "" automatically any time you use a before or after variant to make sure the elements are rendered, but you can override it using the new content utilities which have full arbitrary value support:
<div class="before:content-['hello'] before:block ..."></div>
You can even grab the content from an attribute using the CSS attr() function:
<div before="hello world" class="before:content-[attr(before)] before:block ..."></div>
This can be super helpful when your content has spaces in it, since spaces can't be used in CSS class names.
First-letter/line variants (#4482)
This feature is only available in Just-in-Time mode.
We've added variants for the first-letter and first-line pseudo-elements, so you can do stuff like drop caps:
<p class="first-letter:text-4xl first-letter:font-bold first-letter:float-left">
The night was March 31, 1996, and it was finally time for Bret Hart to face off against Shawn
Michaels in the long anticipated Iron Man match — a 60 minute war of endurance where the man who
scored the most number of falls would walk away as the WWF World Heavyweight Champion.
</p>
Selected text variants (#4482)
This feature is only available in Just-in-Time mode.
We've added a new selection variant that makes it super easy to style highlighted to match your design:
<p class="selection:bg-pink-200">
After nearly a grueling hour of warfare with neither man scoring a fall, Hart locked in the
Sharpshooter, his signature submission hold. As Michaels screamed in pain, the crowd were certain
that Hart was about to walk away from WrestleMania XII as the still-World Heavyweight Champion.
</p>
We've even built this feature in such a way that it can be applied to a parent element and cascade down, so you can set a highlight color for your whole site by applying a utility to the body:
<body class="selection:bg-pink-200">
<!-- ... -->
<p>
But Michaels didn't give up — he held on until the bell rang and the designated 60 minutes was
up. Hart walked away content, thinking that without a clear winner, the title was his to hold.
He was not prepared for what would happen next, when Gorilla Monsoon declared the match would
continue under sudden death rules.
</p>
</body>
List marker variants (#4482)
This feature is only available in Just-in-Time mode.
You can use the new marker variant to style the bullets or numbers at the beginning of a list:
<h1>WrestleMania XII Results</h1>
<ol class="marker:text-gray-500 marker:font-medium">
<li>
The British Bulldog, Owen Hart, and Vader defeated Ahmed Johnson, Jake Roberts, and Yokozuna
</li>
<li>Roddy Piper defeated Goldust</li>
<li>Stone Cold Steve Austin defeated Savio Vega</li>
<li>The Ultimate Warrior defeated Hunter Hearst Helmsley</li>
<li>The Undertaker defeated Diesel</li>
<li>Shawn Michaels defeated Bret Hart</li>
</ol>
Like the selection variant, we've implemented this in a way that it cascades from the parent, so you don't have to repeat it for each list item.
Sibling selector variants (#4556)
This feature is only available in Just-in-Time mode.
Tailwind CSS v2.2 adds new peer-* variants that behave much like the group-* variants, but for targeting sibling elements instead of parent elements.
This is useful for things like styling an element when a preceding checkbox is checked, doing things like floating labels, and lots more:
<label>
<input type="checkbox" class="peer sr-only">
<span class="h-4 w-4 bg-gray-200 peer-checked:bg-blue-500">
<!-- ... -->
</label>
Just like group can be combined with any other variant, peer can as well, so you have variants like peer-hover, peer-focus, peer-disabled, and loads more at your fingertips.
The generated CSS uses the general sibling combinator and looks like this:
.peer:checked ~ .peer-checked\:bg-blue-500 {
background-color: #3b82f6;
}
So just like in vanilla CSS, it will only work for targeting previous siblings, not siblings that appear later in the DOM.
Exhaustive pseudo-class support (#4482)
This feature is only available in Just-in-Time mode.
We've added variants for basically every single missing pseudo-class we could think of in this release:
only(only-child)first-of-typelast-of-typeonly-of-typetargetdefaultindeterminateplaceholder-shownautofillrequiredvalidinvalidin-rangeout-of-range
Personal favorite in the list is placeholder-shown — when combined with the new sibling selector variants it makes it possible to do cool stuff like floating labels:
<div class="relative">
<input id="name" class="peer ...">
<label for="name" class="peer-placeholder-shown:top-4 peer-focus:top-0 ...">
</div>
Shorthand color opacity syntax (#4348)
This feature is only available in Just-in-Time mode.
Instead of using utilities like bg-opacity-50, text-opacity-25, or placeholder-opacity-40, Tailwind CSS v2.2 gives you a new color opacity shorthand you can use to tweak the alpha channel of a color directly in the color utility itself:
- <div class="bg-red-500 bg-opacity-25">
+ <div class="bg-red-500/25">
This means you can now change the opacity of colors anywhere in Tailwind, even where we previously didn’t have specific opacity utilities, like in gradients for example:
<div class="bg-gradient-to-r from-red-500/50"></div>
The opacity values are taken from your opacity scale, but you can also use arbitrary opacity values using square bracket notation:
<div class="bg-red-500/[0.31]"></div>
If I'm being honest, I am more excited about never having to create another core plugin like placeholderOpacity.js for you people again than I am about actually using the feature. And I'm really excited about the feature, so that says something.
Extended arbitrary value support (#4263)
This feature is only available in Just-in-Time mode.
We've gone over every core plugin in Tailwind to try and add the most flexible arbitrary value support we possibly could, and I think we've covered pretty much everything at this point.
You should be able to whatever arbitrary values you want, just about wherever you want:
<div class="col-start-[73] placeholder-[#aabbcc] object-[50%] ..."></div>
If you find one we missed, open an issue and we'll sort it out.
In addition to making arbitrary value support more comprehensive, we've also added a new type-hint syntax to handle ambiguous situations. For example, if you are using a CSS variable as an arbitrary value, it's not always clear what the generated CSS should be:
<!-- Is this a font size utility, or a text color utility? -->
<div class="text-[var(--mystery-var)]"></div>
Now you can provide a hint to the engine by prefixing the arbitrary value with the type name:
<div class="text-[color:var(--mystery-var)]"></div>
Currently, the supported types are:
lengthcoloranglelist
We'll probably flesh this out even more over time as people discover new edge cases but this should get you very far.
Improved nesting support (#4318)
Since Tailwind introduces a lot of non-standard CSS at-rules like @tailwind and @apply, you can often run into weird output when combining it with a PostCSS nesting plugin like postcss-nested or postcss-nesting.
To ease the pain here, we've included a new PostCSS plugin in the tailwindcss package that acts as a lightweight compatibility layer between existing nesting plugins and Tailwind itself.
So if you need nesting support in your project, use our plugin, and stick it before Tailwind in your PostCSS plugin list:
// postcss.config.js
module.exports = {
plugins: [
// ...
require('tailwindcss/nesting'),
require('tailwindcss'),
// ...
],
}
By default, it uses postcss-nested under the hood (since that's what we use to support nesting in Tailwind plugins), but if you'd like to use postcss-nesting instead, just call our plugin as a function and pass through the postcss-nesting plugin:
// postcss.config.js
module.exports = {
plugins: [
// ...
require('tailwindcss/nesting')(require('postcss-nesting')),
require('tailwindcss'),
// ...
],
}
Under the hood, this uses a new screen() function we've introduced that you can use to get the expanded media expression from any of your configured breakpoints:
/* Input */
@media screen(sm) {
/* ... */
}
/* Output */
@media (min-width: 640px) {
/* ... */
}
You probably won't need to use this yourself but it could be helpful if you're ever integrating Tailwind with another tool that understands @media but doesn't handle @screen properly.
- @screen sm { /* ... */ }
+ @media screen(sm) { /* ... */ }
Caret color utilities (#4499)
This feature is only available in Just-in-Time mode.
You can now set the color of the cursor in form fields using the new caret-{color} utilities:
<input class="caret-red-500" />
These are customizable using the caretColor key in the theme section of your tailwind.config.js file.
Background origin utilities (#4117)
We've added new utilities for the background-origin property, which let you control where an element's background is positioned relative to the element's border, padding box, or content:
<div class="bg-origin-border p-4 border-4 border-dashed ..." style="background-image: url(...)">
Background is rendered under the border
</div>
<div class="bg-origin-padding p-4 border-4 border-dashed ..." style="background-image: url(...)">
Background is rendered within the border but on top of any padding
</div>
<div class="bg-origin-content p-4 border-4 border-dashed ..." style="background-image: url(...)">
Background is rendered within any padding and under the content
</div>
Learn more in the background origin documentation.
Simplified transform and filter composition (#4604, #4614)
This feature is only available in Just-in-Time mode.
The transform, filter, and backdrop-filter classes are no longer necessary to "enable" their respective set of composable utilities.
- <div class="transform scale-50 filter grayscale backdrop-filter backdrop-blur-sm">
+ <div class="scale-50 grayscale backdrop-blur-sm">
Now those features are automatically enabled any time you use any of the relevant sub-utilities.
It's important to understand though that because these utilities aren't needed anymore, you can no longer expect transforms and filters to be "dormant" by default. If you were relying on conditionally "activating" transforms or filters by toggling these classes, you will want to make sure you are toggling the sub-utilities themselves instead:
- <div class="scale-105 -translate-y-1 hover:transform">
+ <div class="hover:scale-105 hover:-translate-y-1">
I don't expect this will be a real problem for most people, but it's technically a breaking change which is why we've limited this improvment to the JIT engine only.
Per-side border color utilities (#4404)
This feature is only available in Just-in-Time mode.
Requested at least once a month for the last four years, I'm excited to share that we've finally added per-side border color support now that we don't have to sweat the development stylesheet size.
<div class="border-2 border-t-blue-500 border-r-pink-500 border-b-green-500 border-l-yellow-500">
<!-- ... -->
</div>
Go forth and build ugly websites! (Kidding, kidding, I know they are useful settle the hell down.)
Built-in safelist, transform, and extract support (#4469, #4580)
We've added first-class support for a bunch of important PurgeCSS features and made them work in the JIT engine as well, which doesn't actually even use PurgeCSS.
First is safelist, which is super useful if you need to protect specific classes from being removed from your production CSS, perhaps because they are used in content that comes from a database or similar:
// tailwind.config.js
module.exports = {
purge: {
content: ['./src/**/*.html'],
safelist: [
'bg-blue-500',
'text-center',
'hover:opacity-100',
// ...
'lg:text-right',
],
},
// ...
}
Note that while the classic engine will accept regular expressions here, the JIT engine will not. That's because when we're generating classes on demand, the class doesn't exist until it's used so we have nothing to match the expression against. So if you're using just-in-time mode, make sure you're providing complete class names to get the expected result.
Next is transform, which lets you transform content for different file extensions before scanning it for potential class names:
// tailwind.config.js
let remark = require('remark')
module.exports = {
purge: {
content: ['./src/**/*.{html,md}'],
transform: {
md: (content) => {
return remark().process(content)
},
},
},
// ...
}
This is really useful if you have templates that are written in a language that compiles to HTML, like Markdown.
Finally we have extract, which lets you customize the logic that Tailwind uses to detect class names in specific file types:
// tailwind.config.js
module.exports = {
purge: {
content: ['./src/**/*.{html,md}'],
extract: {
pug: (content) => {
return /[^<>"'`\s]*/.match(content)
},
},
},
// ...
}
This is an advanced feature and most users won’t need it. The default extraction logic in Tailwind works extremely well for almost all projects.
For more information on these features, check out our optimizing for production documentation.
Changes and deprecations
This release introduces a few small changes to the JIT engine that might impact you, and one deprecation:
- New dependency tracking system for Just-in-Time mode
- Transforms and filters don't need to be "enabled" in Just-in-Time mode
matchUtilitiesAPI changes- Deprecate
@tailwind screensfor@tailwind variantsin Just-in-Time mode
It also introduces two minor deprecations for both engines, which are non-breaking for now but will become breaking changes in v3.0 so you are encouraged to account for:
- Deprecate
lightBlueforskyin the extended color palette - Deprecate
blur-0forblur-nonein the default theme
New dependency tracking system for Just-in-Time mode
In Tailwind CSS v2.1, we tracked changes to your template files in just-in-time mode using our own separate watch process because most build tools were missing the APIs we needed to rebuild your CSS when template files changed using the watch system built-in to the build tool.
We've worked hard to make improvements to popular build tools over the past few months and change this, because using our own watch process makes builds prone to race conditions and very hard to debug problems.
So as of Tailwind CSS v2.2, the JIT engine relies on native dependency tracking in build tools by default, with an option to opt-in to the old system if your build tool doesn't support the APIs we need.
If you've followed along closely on GitHub or reported issues with watch mode, you may have seen us suggest using the TAILWIND_DISABLE_TOUCH=true flag — that mode is the default now in v2.2.
This new dependency tracking system is compatible with at least the following tools:
- Next.js (>= v10.2.2)
- Vite (>= v2.3.8)
- webpack 4 (using latest
postcss-loader@^4) - webpack 5 (using latest
postcss-loader@^5) - Rollup
- Snowpack
Tools with known incompatibilities include:
If you discover your build tool isn't yet compatible with the new dependency tracking system, you have two options:
-
Compile your CSS separately using the new Tailwind CLI. You can use packages like
npm-run-allorconcurrentlyto compile your CSS alongside your usual development command by adding some scripts to your project like this:// package.json { // ... "scripts": { "dev": "npm-run-all --parallel dev:*", "dev:server": "vite", "dev:css": "tailwindcss -o src/tailwind.css -w", "build": "tailwindcss -o src/tailwind.css && vite build", "serve": "vite preview" }, } -
Set
TAILWIND_MODE=watchto opt-in to the old dependency tracking system. If the previous default was working for you, this will let you just keep using that system until the build tool you're using has been updated to support the new system.// package.json { // ... scripts: { // Set TAILWIND_MODE=watch when starting your dev server "dev": "TAILWIND_MODE=watch vite", // Do not set TAILWIND_MODE for one-off builds "build": "vite build", // ... }, // ... }Note that setting
TAILWIND_MODE=watchwill start a long-running watch process in the background, so if you set that environment variable when trying to do a one-off build, it will look like the build is hanging. You should only setTAILWIND_MODE=watchwhen you are actually running a dev server/watch process.
Transforms and filters don't need to be "enabled" in Just-in-Time mode
The transform, filter, and backdrop-filter classes aren't necessary for "enabling" those features when using the JIT engine:
- <div class="transform scale-50 filter grayscale backdrop-filter backdrop-blur-sm">
+ <div class="scale-50 grayscale backdrop-blur-sm">
This means you can no longer expect transforms and filters to be dormant by default, and conditionally activated by adding transform, filter, or backdrop-filter.
Instead, you will want put any variants on the sub-utilities themselves:
- <div class="scale-105 -translate-y-1 hover:transform">
+ <div class="hover:scale-105 hover:-translate-y-1">
matchUtilities API changes
The matchUtilities function that is used to register on-demand utilities in the JIT engine has changed significantly.
We consider this private API still which is why we haven't documented it, but I know a few sneaky people out there are playing with it anyways.
To understand how the API works in v2.2, read the pull request that explains the changes.
Deprecate @tailwind screens for @tailwind variants in Just-in-Time mode
In the classic engine, all utility variants are injected as part of the @tailwind utilities directive.
In the JIT engine, variants like hover and focus are injected in the same place as your responsive variants, which has traditionally been the very end of the stylesheet, or at @tailwind screens if you've included it explicitly.
As of v2.2, the @tailwind screens directive has been renamed to @tailwind variants, since it is now the injection point for all variants, not just responsive variants.
This directive is optional (just like @tailwind screens always has been) and is only useful if you want explicit control over where utility variants are injected. By default, they are always injected at the very end of your stylesheet.
If you were using @tailwind screens before, you should update your code to use @tailwind variants:
@tailwind base;
@tailwind components;
@tailwind utilities;
- @tailwind screens;
+ @tailwind variants;
/* Some custom CSS... */
The @tailwind variants feature is considered an advanced escape hatch and we recommend omitting it by default. You should only use it if your project won't work properly without it, which is only ever really true if you are introducing Tailwind to a legacy system with a very fragile existing CSS codebase that has styles that absolutely need to be at the very end of the stylesheet for things to work.
Deprecate lightBlue for sky in the extended color palette
The lightBlue color in the extended color palette has been renamed to sky. It was the only oddball color in the list without a fancy name (like emerald or rose) and we just couldn't stomach it anymore.
Using lightBlue will still work until v3.0, but you'll see a warning in the console suggesting you use the new name.
Note that it's totally okay to start using sky without actually updating your HTML, it's only at the place of import that the name matters:
// tailwind.config.js
let colors = require('tailwindcss/colors')
module.exports = {
theme: {
colors: {
// ...
- 'light-blue': colors.lightBlue,
+ 'light-blue': colors.sky,
}
}
}
Deprecate blur-0 for blur-none in the default theme
For some unknown reason when I released Tailwind CSS v2.1 I thought blur-0 was a better name than blur-none, even though every other utility that uses a named size scale (like rounded-md and shadow-lg) use none, not 0.
In v2.2, we've added blur-none and stopped documenting blur-0. It still works, but it'll be removed from the default theme configuration in v3.0.
- <div class="blur-0">
+ <div class="blur-none">
Fixes and improvements
Alongside the new features this release introduces, we've also fixed a bunch of little things that might have been bugging you.
Here's a list of the fixes and improvements we've made since the last release, with links to the relevant pull requests to learn more:
- JIT: Support applying important utility variants (#4260)
- JIT: Improve support for Svelte class bindings (#4187)
- JIT: Improve support for
calcandvarin arbitrary values (#4147) - Convert
hslcolors tohslawhen transforming for opacity support instead ofrgba(#3850) - Fix
backdropBlurvariants not being generated (#4188) - Improve animation value parsing (#4250)
- Ignore unknown object types when hashing config (82f4eaa)
- Ensure variants are grouped properly for plugins with order-dependent utilities (#4273)
- Resolve purge paths relative to
tailwind.config.jsinstead of the current working directory (#4214) - JIT: Fix temp file storage when node temp directories are kept on a different drive than the project itself (#4044)
- Support border-opacity utilities alongside default
borderutility (#4277) - JIT: Fix source maps for expanded
@tailwinddirectives (2f15411) - JIT: Ignore whitespace when collapsing adjacent rules (15642fb)
- JIT: Generate group parent classes correctly when using custom separator (#4508)
- JIT: Fix incorrect stacking of multiple
groupvariants (#4551) - JIT: Fix memory leak due to holding on to unused contexts (#4571)
If you read this whole thing well damn, well done. Thanks as always for being part of the community and I hope you have fun with the new goodies!
Fixed
- Register PurgeCSS paths as PostCSS dependencies to guarantee proper cache-busting in webpack 5 (#4530)
Fixed
- Fix issue where JIT engine would fail to compile when a source path isn't provided by the build runner for the current input file (#3978)
Tailwind CSS v2.1.0
The first new feature update since Tailwind CSS v2.0 is here and loaded with lots of cool stuff!
New features
JIT engine in core (#3905)
The brand-new JIT engine we announced in March has now been merged into core, and is available as an opt-in feature using a new mode option in your tailwind.config.js file:
// tailwind.config.js
module.exports = {
mode: 'jit',
purge: [
// ...
],
// ...
}
This feature is still in preview which means some details may change as we iron out the kinks, and it's not subject to semantic versioning.
If you were using @tailwindcss/jit before, you can now migrate to Tailwind CSS v2.1 instead, as that's where all new development on the engine will happen.
New filter and backdrop-filter utilities (#3923)
This is a huge one — we've finally added first-class support for CSS filters!
They work a lot like our transform utilities, where you use filter to enable filters, and combine it with utilities like grayscale, blur-lg, or saturate-200 to compose filters on the fly.
Here's what filter looks like:
<div class="filter blur-md grayscale invert ...">
<!-- ... -->
</div>
...and here's what backdrop-filter looks like:
<div class="backdrop-filter backdrop-blur backdrop-brightness-50 ...">
<!-- ... -->
</div>
Check out the filter and backdrop-filter to learn more. We'll add a bunch of helpful visual examples there soon!
New blending mode utilities (#3920)
We've added brand new utilities for mix-blend-mode and background-blend-mode:
<div class="mix-blend-multiply ...">
<!-- ... -->
</div>
Check out the documentation to learn more.
New isolation utilities (#3914)
We've added new isolate and isolation-auto utilities for working with the isolation property:
<div class="isolate ...">
<!-- ... -->
</div>
This can be really helpful for scoping blending mode features or z-index adjustments and is super powerful. Check out the documentation to learn more.
I also highly recommend this great article by Josh Comeau to see it in action.
New box-decoration-break utilities (#3911)
We've added brand new utilities for the box-decoration-break property:
<div class="mix-blend-multiply ...">
<!-- ... -->
</div>
It's a bit of an obscure one but it can be really useful alongside text gradients. Learn more in our documentation and in the MDN article.
New inline-table and list-item display utilities (#3563, #3929)
We've added a couple display utilities we were missing:
<div class="inline-table ...">
<!-- ... -->
</div>
<div class="list-item ...">
<!-- ... -->
</div>
Maybe not quite as exciting as the rest but a welcome addition nonetheless.
Fixed
- Pass full
var(--bg-opacity)value asopacityValuewhen defining colors as functions (https://github.com/tailwindlabs/tailwindcss/commit/d98f2f829d2bca83e0d14a9e2680d6859f8f4d65)
Fixed
- Ensure sourcemap input is deterministic when using
@applyin Vue components (#3356) - Ensure placeholder opacity is consistent across browsers (#3308)
- Fix issue where
theme()didn't work with colors defined as functions (#2919) - Enable
darkvariants by default for color opacity utilities (#2975)
Added
- Nothing, just the only thing I could do when I found out npm won't let me publish the same version under two tags.
Tailwind CSS v2.0, woohoo!
Read the blog post for more details.
Added
- Add redesigned color palette (#2623, 700866c, #2633)
- Add dark mode support (#2279, #2631)
- Add
overflow-ellipsisandoverflow-cliputilities (#1289) - Add
transform-gputo force hardware acceleration on transforms when desired (#1380) - Extend default spacing scale (#2630, 7f05204)
- Add spacing scale to
insetplugin (#2630) - Add percentage sizes to
translate,inset, andheightplugins (#2630, 5259560) - Extend default font size scale (#2609, #2619)
- Support using
@applywith complex classes, including variants likelg:hover:bg-blue-500(#2159) - Add new
2xlbreakpoint at 1536px by default (#2609) - Add default line-height values for font-size utilities (#2609)
- Support defining theme values using arrays for CSS properties that support comma separated values (e13f083c4)
- Enable
group-hoverfor color plugins,boxShadow, andtextDecorationby default (28985b6, f6923b1) - Enable
focusfor z-index utilities by default (ae5b3d3) - Support
extendinvariantsconfiguration (#2651) - Add
max-w-proseclass by default (#2574) - Support flattening deeply nested color objects (#2148)
- Support defining presets as functions (#2680)
- Support deep merging of objects under
extend(#2679, #2700) - Enable
focus-withinfor all plugins that havefocusenabled by default (1a21f072, f6923b1) - Added new
ringutilities for creating outline/focus rings using box shadows (#2747, 879f088, e0788ef) - Added
5and95to opacity scale (#2747) - Add support for default duration and timing function values whenever enabling transitions (#2755)
Changed
- Completely redesign color palette (#2623, 700866c, #2633)
- Drop support for Node 8 and 10 (#2582)
- Removed
targetfeature and dropped any compatibility with IE 11 (#2571) - Upgrade to PostCSS 8 (but include PostCSS 7 compatibility build) (729b400, 1d8679d, c238ed1)
- Removed
shadow-outline,shadow-solid, andshadow-xsby default in favor of newringAPI (#2747) - Switch
normalize.csstomodern-normalize(#2572) - Rename
whitespace-no-wraptowhitespace-nowrap(#2664) - Rename
flex-no-wraptoflex-nowrap(#2676) - Remove
clearfixutility, recommendflow-rootinstead (#2766) - Disable
hoverandfocusforfontWeightutilities by default (f6923b1) - Remove
grid-gapfallbacks needed for old versions of Safari (5ec45fa) - Change special use of 'default' in config to 'DEFAULT' (#2580)
- New
@applyimplementation, slight backwards incompatibilities with previous behavior (#2159) - Make
themeretrieve the expected resolved value when theme value is complex (e13f083c4) - Move
truncateclass totextOverflowcore plugin (#2562) - Remove
scrolling-touchandscrolling-autoutilities (#2573) - Modernize default system font stacks (#1711)
- Upgrade to PurgeCSS 3.0 (8e4e0a0)
- Change default
text-6xlfont-size to 3.75rem instead of 4rem (#2619) - Ignore
[hidden]elements withinspaceanddivideutilities instead oftemplateelements (#2642) - Automatically prefix keyframes and animation names when a prefix is configured (#2621, #2641)
- Merge
extendobjects deeply by default (#2679) - Respect
preserveHtmlElementsoption even when using custom PurgeCSS extractor (#2704) - Namespace all internal custom properties under
tw-to avoid collisions with end-user custom properties (#2771)
Changed
-
The
presetsfeature had unexpected behavior where a preset config without its ownpresetskey would not extend the default config. (#2662)If you were depending on this unexpected behavior, just add
presets: []to your own preset to exclude the default configuration.
Fixed
- Fix issue where using
themewith default line-heights did not resolve correctly (#2308)
Fixed
- Fix issue changing plugins defined using the
withOptionsAPI would not trigger rebuilds in watch processes
- Fix issue where
tailwindcss init --fullscaffolded a corrupt config file (https://github.com/tailwindlabs/tailwindcss/issues/2556) - Remove console warnings about upcoming breaking changes (see note below)
I've opted to remove the console notices about upcoming breaking changes (that encouraged users to opt-in to future features using the future option in their config file.)
While I had good intentions for this approach originally, I'm realizing now that it just ends up creating more confusion and a sloppier documentation story. Any breaking changes can't really be documented easily because the documentation needs to show the stable version of any given feature, since we can't assume someone has opted in to the new stuff.
This means that when someone does opt in, they are basically opting in to being out of sync with the documentation, which is a crappy experience for them, especially if they can't upgrade to Tailwind 2.0 in the near future because they need to support IE11.
For this reason I've decided to stop warning about the upcoming breaking changes so that we don't force users to opt-in to an essentially undocumented version of the framework. Instead we will continue to maintain the "upcoming changes" page in the docs, and continue to ship new ideas behind flags for people to test but without the nudge to upgrade. Folks who are comfortable opting-in to the new stuff early can do so, and folks that aren't can comfortably keep using things the way they are (along with complete documentation) and upgrade to the next version all at once, like people have done traditionally with most dependencies.
I will always strive to make breaking changes as painless and minimal as possible, so spending an hour to do the upgrade in one sitting is never going to be too bad. I highly value backwards compatibility and will never make needlessly breaking changes. An improvement is only worth making if it improves things enough to make up for the upgrade cost, and that's usually pretty rare. For example lh-5 might be a nicer class name than leading-5 but it is absolutely not worth breaking everyone's muscle memory and forcing them to replace hundreds of instances of classes in their projects. We'll only make breaking changes if they unlock meaningful new possibilities or fix fundamental problems that are holding people back.
Fixed
- Merge plugins when merging config with preset (#2561
- Use
word-wrapandoverflow-wraptogether, not one or the other sinceword-wrapis IE-only
Fixed
- Don't import
corePluginsinresolveConfigto avoid bundling browser-incompatible code (#2548)
Tailwind CSS v1.9 is now available with a new presets feature, some new utilities, and a few accessibility improvements. Check it out!
New features
- Add new
presetsconfig option (#2474) - Scaffold new
tailwind.config.jsfiles with availablefutureflags commented out (#2379) - Add
col-span-fullandrow-span-full(#2471) - Make
outlineconfigurable,outline-nonemore accessible by default, and addoutline-blackandoutline-white(#2460) - Add additional small
rotateandskewvalues (#2528) - Add
xl,2xl, and3xlborder radius values (#2529) - Add new utilities for
grid-auto-columnsandgrid-auto-rows(#2531) - Promote
defaultLineHeightsandstandardFontWeightsfrom experimental to future
Fixed
- Don't escape keyframe values (#2432)
- Use
word-wrapinstead ofoverflow-wrapinie11target mode (#2391)
Experimental
Fixed
- Support defining colors as closures even when opacity variables are not supported (#2536)
- Make
tailwindcss.pluginwork in ESM environments for reasons
Fixed
- Prevent new
darkexperiment from causing third-partydarkvariants to inherit stacking behavior (#2382)
Fixed
- Fix issue where classes in escaped strings (like
class=\"block\") weren't extracted properly for purging (#2364)
Fixed
- Fix issue where
resolveConfigdidn't take into account configs added by feature flags (#2347)
Fixed
- Fix issue where inserting extra PurgeCSS control comments could break integrated PurgeCSS support
- Fix issue where dark variant in 'class' mode was incompatible with 'group-hover' variant (#2337)
- Support basic nesting structure with
@applywhen using theapplyComplexClassesexperiment (#2271)
Changed
- Rename
font-hairlineandfont-thintofont-thinandfont-extralightbehindstandardFontWeightsflag (experimental until v1.9.0) (#2333)
- Fix bug where dark mode variants would cause an error if you had a
pluginsarray in your config (#2322)
- Fix bug in the new font-variant-numeric utilities which broke the whole rule
- Fix bug while purging
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 font-variant-numeric utilities (#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:
<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:
<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.
New grid alignment utilities (#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.
New preserveHtmlElements option for purge (#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.
// 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.
New layers mode for purge (#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:
// 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:
// 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:
// tailwind.config.js
module.exports = {
future: {
purgeLayersByDefault: true,
},
// ...
}
Support configuring variants as functions (#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:
// tailwind.config.js
module.exports = {
variants: {
opacity: ({ before }) => before(['group-hover'], 'hover'),
},
}
Read the pull request for all of the details.
Dark mode (experimental) (#2279)
Oh yeah I almost forgot, we added dark mode.
<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:
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:
// 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!
Changes
@layer rules are now grouped together (#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:
@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:
@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.
Deprecations
conservative purge mode deprecated in favor of layers (#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:
// tailwind.config.js
module.exports = {
purge: {
mode: 'layers',
layers: ['utilities'],
content: [
// Paths...
],
},
}
- Fix bug where the new experimental
@applyimplementation broke when applying a variant class with theimportantoption globally enabled
- Update lodash to latest to silence security warnings
- Fix bug where the new
applyComplexClassesexperiment didn't behave as expected with rules with multiple selectors, like.foo, .bar { color: red } - Make
@applyinsensitive to whitespace in the newapplyComplexClassesexperiment - Add new
-pflag to CLI to quickly scaffold a postcss.config.js file
- Fix bug that prevented defining colors as closures when the gradientColorStops plugin was enabled
- Log feature flag notices to stderr instead of stdout to preserve compatibility with pipe-based build systems
- Add missing
bg-noneutility for disabling background images
- Reuse generated CSS as much as possible in long-running processes instead of needlessly recalculating
- Don't issue duplicate flag notices in long-running build processes
Tailwind v1.7.0
Another new Tailwind release is here! This one sort of came out of nowhere and is loaded with exciting stuff (especially down in the experiments section...)
Let's dig in!
New features
Gradients
https://github.com/tailwindlabs/tailwindcss/pull/2176
The big one for this release — Tailwind now ships with built-in support for background gradients!
Gradients are designed with a highly composable API that lets you specify up to three color stops in one of 8 directions by default:
<div class="bg-gradient-to-r from-orange-400 via-red-500 to-pink-500">
<!-- ... -->
</div>

This is made possible by a new backgroundImage core plugin (which you can use for any background images you like!) and a new gradientColorStops core plugin.
The default configuration for these plugins looks like this:
// tailwind.config.js
module.exports = {
theme: {
backgroundImage: {
'gradient-to-t': 'linear-gradient(to top, var(--gradient-color-stops))',
'gradient-to-tr': 'linear-gradient(to top right, var(--gradient-color-stops))',
'gradient-to-r': 'linear-gradient(to right, var(--gradient-color-stops))',
'gradient-to-br': 'linear-gradient(to bottom right, var(--gradient-color-stops))',
'gradient-to-b': 'linear-gradient(to bottom, var(--gradient-color-stops))',
'gradient-to-bl': 'linear-gradient(to bottom left, var(--gradient-color-stops))',
'gradient-to-l': 'linear-gradient(to left, var(--gradient-color-stops))',
'gradient-to-tl': 'linear-gradient(to top left, var(--gradient-color-stops))',
},
gradientColorStops: (theme) => theme('colors'),
},
variants: {
backgroundImage: ['responsive'],
gradientColorStops: ['responsive', 'hover', 'focus'],
},
}
Learn more the original pull request.
New background-clip utilities
https://github.com/tailwindlabs/tailwindcss/pull/2168
We've also added a new backgroundClip core plugin that you can use to control how background are rendered within an element.
It includes 4 new utilities:
| Class | CSS |
|---|---|
bg-clip-border | background-clip: border-box |
bg-clip-padding | background-clip: padding-box |
bg-clip-content | background-clip: content-box |
bg-clip-text | background-clip: text |
Combined with the new gradient features, you can use this to do cool gradient text stuff like this:
<h1 class="text-6xl font-bold">
<span class="bg-clip-text text-transparent bg-gradient-to-r from-teal-400 to-blue-500">
Greetings from Tailwind v1.7.
</span>
</h1>

Only responsive variants are enabled for the backgroundClip plugin by default:
// tailwind.config.js
module.exports = {
variants: {
backgroundClip: ['responsive'],
},
}
New gap utility aliases
https://github.com/tailwindlabs/tailwindcss/pull/2137
For some dumb reason I named the column-gap and row-gap utilities col-gap-{n} and row-gap-{n} respectively, which isn't terrible but it's not consistent with how other things in Tailwind are named.
I was finding myself getting them wrong all the time — is row-gap the gaps in a row, or the gap between rows?
Tailwind v1.7 introduces new gap-x-{n} and gap-y-{n} utilities that do the exact same thing but have names that don't suck. They make way more sense than the actual CSS names now that gap for flexbox is starting to roll out too, since flexbox has no "columns".
These utilities will replace the old ones in v2.0, but for now they both exist together.
We recommend migrating to the new names now, and disabling the old names using this feature flag:
// tailwind.config.js
module.exports = {
future: {
removeDeprecatedGapUtilities: true,
},
// ...
}
Tailwind will issue a warning in the console to remind you that you are including deprecated classes in your build until you enable this flag.
New contents display utility
https://github.com/tailwindlabs/tailwindcss/pull/2023
We've added a new contents class for the recent display: contents CSS feature.
<div class="flex">
<div><!-- ... --></div>
<!-- This container will act as a phantom container, and its children will be treated as part of the parent flex container -->
<div class="contents">
<div><!-- ... --></div>
<div><!-- ... --></div>
</div>
<div><!-- ... --></div>
</div>
Learn more about it in this great article by Rachel Andrew.
Default letter-spacing per font-size
https://github.com/tailwindlabs/tailwindcss/pull/1915
You can now configure a default letter-spacing value for each font-size in your tailwind.config.js theme, using a tuple syntax:
// tailwind.config.js
module.exports = {
theme: {
fontSize: {
2xl: ['24px', {
letterSpacing: '-0.01em',
}],
// Or with a default line-height as well
3xl: ['32px', {
letterSpacing: '-0.02em',
lineHeight: '40px',
}],
}
}
}
This new syntax is supported in addition to the simpler [{fontSize}, {lineHeight}] syntax that was recently introduced.
Divide border styles
https://github.com/tailwindlabs/tailwindcss/pull/1965
We've added utilities for setting the border style on the divide utilities:
<div class="divide-y divide-dashed">
<div><!-- ... --></div>
<div><!-- ... --></div>
<div><!-- ... --></div>
<div><!-- ... --></div>
</div>
These utilities include responsive variants by default:
// tailwind.config.js
module.exports = {
variants: {
divideStyle: ['responsive'],
},
}
Access entire config object from plugins
https://github.com/tailwindlabs/tailwindcss/pull/1583
The config function passed to the plugin API now returns the entire config option when invoked with no arguments:
tailwind.plugin(function ({ config, addUtilities, /* ... */ })) {
// Returns entire config object
config()
})
Define colors as closures
https://github.com/tailwindlabs/tailwindcss/pull/1676
You can now define your colors as callbacks, which receive a bag of parameters you can use to generate your color value.
This is particularly useful when trying to make your custom colors work with the backgroundOpacity, textOpacity, etc. utilities
// tailwind.config.js
module.exports = {
theme: {
colors: {
primary: ({ opacityVariable }) => `rgba(var(--color-primary), var(${variable}, 1))`,
},
},
}
Currently the only thing passed through is an opacityVariable property, which contains the name of the current opacity variable (--background-opacity, --text-opacity, etc.) depending on which plugin is using the color.
Deprecations
Tailwind v1.7 introduces a new feature flagging and deprecation system designed to make upgrades as painless as possible.
Any time we deprecate functionality or introduce new (stable) breaking changes, they will be available in Tailwind v1.x under a future property in your tailwind.config.js file.
Whenever there are deprecations or breaking changes available, Tailwind will warn you in the console on every build until you adopt the new changes and enable the flag in your config file:
risk - There are upcoming breaking changes: removeDeprecatedGapUtilities
risk - We highly recommend opting-in to these changes now to simplify upgrading Tailwind in the future.
risk - https://tailwindcss.com/docs/upcoming-changes
You can opt-in to a breaking change by setting that flag to true in your tailwind.config.js file:
// tailwind.config.js
module.exports = {
future: {
removeDeprecatedGapUtilities: true,
},
}
If you'd prefer not to opt-in but would like to silence the warning, explicitly set the flag to false:
// tailwind.config.js
module.exports = {
future: {
removeDeprecatedGapUtilities: false,
},
}
We do not recommend this, as it will make upgrading to Tailwind v2.0 more difficult.
Deprecated gap utilities
As mentioned previously, Tailwind v1.7.0 introduces new gap-x-{n} and gap-y-{n} utilities to replace the current col-gap-{n} and row-gap-{n} utilities.
By default both classes will exist, but the old utilities will be removed in Tailwind v2.0.
To migrate to the new class names, simply replace any existing usage of the old names with the new names:
- <div class="col-gap-4 row-gap-2 ...">
+ <div class="gap-x-4 gap-y-2 ...">
To opt-in to the new names now, enable the removeDeprecatedGapUtilities flag in your tailwind.config.js file:
// tailwind.config.js
module.exports = {
future: {
removeDeprecatedGapUtilities: true,
},
}
Experimental features
Tailwind v1.7.0 introduces a new experimental feature system that allows you to opt-in to new functionality that is coming to Tailwind soon but isn't quite stable yet.
It's important to note that experimental features may introduce breaking changes, do not follow semver, and can change at any time.
If you like to live on the wild side though, you can enable all of them like so:
// tailwind.config.js
module.exports = {
experimental: 'all',
}
With that out of the way, here is some of the fun stuff we're working on that we're pumped you can finally play with...
Use @apply with variants and other complex classes
https://github.com/tailwindlabs/tailwindcss/pull/2159
This is a huge one — you can finally use @apply with responsive variants, pseudo-class variants, and other complex classes!
.btn {
@apply bg-indigo hover:bg-indigo-700 sm:text-lg;
}
There are a lot of details to understand with this one, so I recommend reading the pull request to learn about how it all works.
This introduces breaking changes to how @apply worked before, so be sure to read all of the details before just flipping the switch.
To enable this feature, use the applyComplexClasses flag:
// tailwind.config.js
module.exports = {
experimental: {
applyComplexClasses: true,
},
}
New color palette
https://github.com/tailwindlabs/tailwindcss/pull/2132
We've added a teaser of the new Tailwind 2.0 color palette that you can start playing with today using the uniformColorPalette flag:
// tailwind.config.js
module.exports = {
experimental: {
uniformColorPalette: true,
},
}
The idea behind the new palette is that every color at every shade has a similar perceived brightness. So you can swap indigo-600 with blue-600 and expect the same color contrast.
We do expect these colors to continue to change a lot as we iterate on them, so use these at your own risk.
Extended spacing scale
https://github.com/tailwindlabs/tailwindcss/pull/2141
We've added a much bigger spacing scale that includes new micro values like 0.5, 1.5, 2.5, and 3.5, as well as new large values like 72, 80, and 96, and added percentage based fractional values to the whole spacing scale (1/2, 5/6, 7/12, etc.)
You can enable the extended spacing scale using the extendedSpacingScale flag:
// tailwind.config.js
module.exports = {
experimental: {
extendedSpacingScale: true,
},
}
This is pretty stable, I would be surprised if we change this.
Default line-heights per font-size by default
https://github.com/tailwindlabs/tailwindcss/pull/2143
We've added recommended default line-heights to every built-in font-size, which can be enabled using the defaultLineHeights flag:
// tailwind.config.js
module.exports = {
experimental: {
defaultLineHeights: true,
},
}
This is a breaking change and will impact your designs, as previously all font sizes had a default line-height of 1.5.
Extended font size scale
https://github.com/tailwindlabs/tailwindcss/pull/2145
We've added three new font sizes (7xl, 8xl, and 9xl) to keep up with the latest huge-as-hell-hero-text trends. They include default line-heights as well.
You can enable them under the extendedFontSizeScale flag:
// tailwind.config.js
module.exports = {
experimental: {
extendedFontSizeScale: true,
},
}
- Fixes issue where
motion-safeandmotion-reducevariants didn't stack correctly withgroup-hovervariants
- Fixes issue where
@keyframesrespecting theimportantoption would break animations in Chrome
- Fixes an issue where animation keyframes weren't included in the build without
@tailwind base(#2108)
Tailwind CSS v1.6.0
It's like Tailwind CSS v1.5 except now there's animation support, overscroll utilities, and more! 🥳
There aren't supposed to be any breaking changes here, but I thought that last time too. If I did break something, first person to report it gets a Tailwind shirt 😘
New Features
- Animation support
- New
prefers-reduced-motionvariants - New
overscroll-behaviorutilities - Generate your CSS without an input file
Animation support (#2068)
Tailwind CSS v1.6 adds a brand new animation core plugin, with 4 general purpose animations included out of the box:
animate-spinanimate-pinganimate-pulseanimate-bounce
<button type="button" class="bg-indigo-600 ..." disabled>
<svg class="animate-spin h-5 w-5 mr-3 ..." viewBox="0 0 24 24">
<!-- ... -->
</svg>
Processing
</button>
These are completely customizable as always, using the animation and keyframes sections of your tailwind.config.js theme:
// tailwind.config.js
module.exports = {
theme: {
extend: {
animation: {
wiggle: 'wiggle 1s ease-in-out infinite',
},
keyframes: {
wiggle: {
'0%, 100%': { transform: 'rotate(-3deg)' },
'50%': { transform: 'rotate(3deg)' },
},
},
},
},
}
For more information and a live demo, read the new animation documentation. For behind the scenes details about the design rationale, check out the pull request.
New prefers-reduced-motion variants (#2071)
To go along with the new animation features, we've also added new motion-safe and motion-reduce variants that allow you to conditionally apply CSS based on the prefers-reduced-motion media feature.
These can be useful in conjunction with transition and animation utilities to disable problematic motion for users who are sensitive to it:
<div class="... transition duration-150 ease-in-out motion-reduce:transition-none ..."></div>
...or to explicitly opt-in to motion to make sure it's only being shown to users who haven't opted out:
<div class="... motion-safe:transition duration-150 ease-in-out ..."></div>
These can be combined with responsive variants and pseudo-class variants as well:
<!-- With responsive variants -->
<div class="sm:motion-reduce:translate-y-0"></div>
<!-- With pseudo-class variants -->
<div class="motion-reduce:hover:translate-y-0"></div>
<!-- With responsive and pseudo-class variants -->
<div class="sm:motion-reduce:hover:translate-y-0"></div>
These are currently not enabled for any utilities by default, but you can enabled them as needed in the variants section of your tailwind.config.js file:
// tailwind.config.js
module.exports = {
// ...
variants: {
translate: ['responsive', 'hover', 'focus', 'motion-safe', 'motion-reduce'],
},
}
For more details, check out the updated variants documentation.
New overscroll-behavior utilities (#2075)
We've also added new utilities for the overscroll-behavior property.
You can use these utilities to control how "scroll chaining" works in your sites, and avoid scrolling the whole page when you reach the top or bottom of an embedded scrollable area.
<div class="overscroll-y-contain ...">
<!-- ... -->
</button>
Note that this is currently not supported in Safari, but in my opinion it's not a huge deal to treat this as a progressive enhancement anyways, since it falls back fairly gracefully.
This plugin can be configured in your tailwind.config.js file as overscrollBehavior:
// tailwind.config.js
module.exports = {
// ...
// Disabling the plugin
corePlugins: {
overscrollBehavior: false,
},
// Customizing the enabled variants
variants: {
overscrollBehavior: ['responsive', 'hover'],
},
}
Generate your CSS without an input file (#1861)
If you never write any custom CSS and you're sick of creating this file all the time...
@tailwind base;
@tailwind components;
@tailwind utilities;
...then I've got news for you baby — if you're using our tailwindcss CLI tool you can start depositing those 58 characters into your savings account instead of wasting them on a pointless CSS file.
The input file argument is now optional in the CLI tool, so if you don't actually need a custom CSS file, you can just write this:
npx tailwindcss build -o compiled.css
Your kids are going to be so grateful for the extra time you get to spend together ❤️
- Fixes issue where you could no longer use
@applywith unprefixed class names if you had configured a prefix
- Fixes accidental breaking change where adding component variants using the old manual syntax (as recommended in the docs) stopped working
Tailwind CSS v1.5.0
I was hoping to save v1.5.0 for something really exciting (🌘) but we needed a new feature to support the new @tailwindcss/typography plugin so h*ck it, we're dropping some new stuff on you early. Enjoy! 🥳
No breaking changes, this is a minor release and we are professionals you silly goose. One accidental breaking change, fixed in v1.5.1. I take back everything I said about being professionals. I am the one who is the silly goose.
New Features
- Component
variantssupport - Responsive
containervariants - New
focus-visiblevariant - New
checkedvariant
Component variants support (#2031)
Until Tailwind CSS v1.5.0, only "utility" classes were really intended to be used with variants (like "responsive", "hover", "focus", etc.)
While these are still much more useful for utilities than any other type of class, we now support generating variants for component classes as well, like the prose classes in the new @tailwindcss/typography plugin:
<article class="prose md:prose-lg">
<!-- Content -->
</article>
You can take advantage of this feature in your own component classes by using the new variants option in the second argumant of the addComponents plugin API:
plugin(function ({ addComponents })) {
addComponents({
'.card': {
// ...
}
}, {
variants: ['responsive']
})
})
...or using the array shorthand you might be familiar with from the addUtilities API:
plugin(function ({ addComponents })) {
addComponents({
'.card': {
// ...
}
}, ['responsive'])
})
To take advantage of these feature in your custom CSS (rather than using the plugin API), you can use a new @layer directive to explicitly tell Tailwind that your styles belong to the "components" bucket:
@layer components {
@responsive {
.card {
/* ... */
}
}
}
This helps Tailwind purge your unused CSS correctly, ensuring it doesn't remove any responsive component variants when using the default "conservative" purge mode.
Responsive container variants (#2032)
Piggy-backing off of the new component variants support, the container class now supports variants!
<!-- Only lock the width at `md` sizes and above -->
<div class="md:container">
<!-- ... -->
</div>
We've enabled responsive variants by default, but if you are sick in the head you can also manually enable other variants like focus, group-hover, whatever:
// tailwind.config.js
module.exports = {
// ...
variants: {
container: ['responsive', 'focus', 'group-hover'],
},
}
New focus-visible variant (#1824)
We've added support for the :focus-visible pseudo-class using a new focus-visible variant.
This is super useful for adding focus styles that only appear to keyboard users, and are ignored for mouse users:
<button class="focus-visible:outline-none focus-visible:shadow-outline ...">
Click me
</button>
It's not enabled for anything by default, but you can enable it in the variants section of your config file:
// tailwind.config.js
module.exports = {
// ...
variants: {
backgroundColor: ['responsive', 'hover', 'focus', 'focus-visible'],
},
}
Browser support is still pretty weak on this but getting better. In the mean time, check out the polyfill and corresponding PostCSS plugin if you'd like to use this in all browsers right away.
New checked variant (#1285)
We've added a new checked variant you can use to conditionally style things like checkboxes and radio buttons:
<input type="checkbox" class="bg-white checked:bg-blue-500" />
It's not enabled for anything by default, but you can enable it in the variants section of your config file:
// tailwind.config.js
module.exports = {
// ...
variants: {
backgroundColor: ['responsive', 'hover', 'focus', 'checked'],
},
}
- Explicitly error when using a class as the
importantconfig option instead of just generating the wrong CSS (https://github.com/tailwindcss/tailwindcss/commit/ad850ac49128dfcc292f0025c8c42f26bc26c735)
- Fix bug where the
divideColorplugin was using the wrongvariantsin IE11 target mode
- Fix bug where
target: 'browserslist'didn't work, onlytarget: ['browserslist', {...}]did (https://github.com/tailwindcss/tailwindcss/commit/f5c0e301a55a189f642699ecaddc952c0487e3e8)
- Don't generate unnecessary CSS in color plugins when color opacity utilities are disabled (#1680)
- Fix issue where
purge: { enabled: false }was ignored, addpurge: falseshorthand
- Improve built-in PurgeCSS extractor to better support Haml and Slim templates (https://github.com/tailwindcss/tailwindcss/commit/cdef9c8d4db32e494366cbf19f73f21dbdb7142c, https://github.com/tailwindcss/tailwindcss/commit/9032ff33edba1a7fc85b78e7772acccc9346340c)
Tailwind CSS v1.4.0
Another new minor version so soon? Merry Coronavirus 🎄😷🎄
New Features
- New color opacity utilities
- Built-in PurgeCSS
- IE 11 target mode (experimental)
New color opacity utilities (#1627)
Tailwind v1.4 adds a new set of utilities for controlling just the alpha channel of colors:
bg-opacity-{value}text-opacity-{value}border-opacity-{value}divide-opacity-{value}placeholder-opacity-{value}
These utilities compose with the existing color utilities like this:
<div class="bg-red-500 bg-opacity-25">
<!-- ... -->
</div>
All of these new utilities inherit their values from the opacity config by default but can be configured independently under the following theme keys:
backgroundOpacitytextOpacityborderOpacityplaceholderOpacitydivideOpacity
Learn more in the pull request.
Built-in PurgeCSS (#1639)
Tailwind v1.4 adds a new purge option to the config for removing unused CSS without the need for configuring another tool:
// tailwind.config.js
module.exports = {
purge: [
'./src/**/*.html',
'./src/**/*.vue',
'./src/**/*.jsx',
],
theme: {},
variants: {},
plugins: [],
}
Learn more in the pull request and the updated "Controlling File Size" documentation.
IE 11 target mode (#1635)
This feature is experimental and may change outside of normal semantic versioning policies.
Recently we've been adding a lot of new features to Tailwind that aren't IE 11 compatible, and if you need to support IE 11 in your projects you have to be careful not to rely on these features by mistake.
To make this easier, we've added a new target option to the config that lets you opt-in to a new ie11 mode that disables any features that are not compatible with IE 11:
// tailwind.config.js
module.exports = {
target: 'ie11',
theme: {},
variants: {},
plugins: [],
}
Learn more in the pull request.
- Fix missing unit in calc bug in space plugin (
space-x-0didn't work for example) - Drop
fs-extradependency to^8.0.0to preserve Node 8 compatibility until Tailwind 2.0
- Fix bug where
divide-{x/y}-0utilities didn't work due to missing unit incalccall
- Fix bug where the
divide-xutilities were not being applied correctly due to referencing--divide-y-reverseinstead of--divide-x-reverse
- Add forgotten
responsivevariants forspace,divideWidth, anddivideColorutilities
- Fix bug where the
space-xutilities were not being applied correctly due to referencing--space-y-reverseinstead of--space-x-reverse
Tailwind CSS v1.3.0
Holy crap a new Tailwind CSS release! We've got a few new goodies in this one, and I've made sure to put the most exciting ones at the top 🚀
New Features
- New
spaceanddividelayout utilities - New
transition-delayutilities - New
group-focusvariant - Support for specifying a default line-height for each font-size utility
- Support for breakpoint-specific padding for
containerclass - Added
currentto the default color palette - New
inline-gridutility - New
flow-rootdisplay utility - New
clear-noneutility
New space and divide layout utilities (#1584, #1594)
Prior to Tailwind v1.3, if you wanted to add some space or a border between elements, you had to manually add the necessary margin/border to all but one of the children:
<!-- Before -->
<ul>
<li>One</li>
<li class="mt-4">Two</li>
<li class="mt-4">Three</li>
</ul>
Tailwind v1.3 introduces new space-{x/y}-{n}, divide-{x/y}-{n}, and divide-{color} utilities for controlling this at the parent level instead, simplifying this common pattern into something concise and declarative that doesn't require all of that annoying duplication:
<!-- After -->
<ul class="space-y-4">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
The space-x-{n} utilities add a left margin to all but the first element, and the space-y-{n} utilities add a top margin to all but the first element:
<!-- Horizontal stack with 8px of space between each item -->
<ul class="flex space-x-2">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
<!-- Vertical stack with 16px of space between each item -->
<ul class="space-y-4">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
The space utilities inherit their configuration from the global spacing configuration by default, and include negative variations like -space-x-2 to create overlapping effects.
The divide-x-{n} utilities add a left border to all but the first element, and the divide-y-{n} utilities add a top border to all but the first element:
<!-- Horizontal list with 1px border between each item -->
<ul class="flex divide-x">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
<!-- Vertical list with 1px border between each item -->
<ul class="divide-y">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
The divide utilities inherit their configuration from the borderWidth configuration, and support the default keyword (set to 1px out of the box, like with borderWidth) so you can use divide-y instead of divide-y-1.
The divide-{color} utilities are used to set the color of the dividing borders:
<!-- Vertical list with 1px blue border between each item -->
<ul class="divide-y divide-blue-500">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
We've also included space-{x/y}-reverse and divide-{x/y}-reverse utilities which can be useful if you are reversing the direction of items in a container using either flex-row-reverse or flex-col-reverse. These utilities swap left margins for right margins, top margins for bottom margins, left borders for right borders, and top borders for bottom borders to account for the items being in reverse order:
<!-- Reversed horizontal list with 8px space between each item -->
<ul class="flex flex-row-reverse space-x-2 space-x-reverse">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
There are a couple limitations of our implementation that are worth pointing out:
- They break down if your items wrap, you'll want to do something complicated with negative margins if you need to handle this
- They break down if you start manually changing the order of things using the
orderproperty
Despite these limitations, I think you'll still find these incredibly useful. Eventually gap will have universal support in flexbox layouts and we can all rejoice.
All of these utilities include responsive variants by default, and their values and variants can be customized using the space, divideWidth, and divideColor configuration keys respectively.
New transition-delay utilities (#1462)
Tailwind v1.3 introduces new delay-{amount} utilities for the transition-delay property:
<div class="transition ease-in-out duration-500 delay-1000">
<!-- ... -->
</div>
We include the same values we do for the duration-{amount} utilities and generate responsive variants by default:
// tailwind.config.js
module.exports = {
theme: {
// ...
transitionDelay: {
'75': '75ms',
'100': '100ms',
'150': '150ms',
'200': '200ms',
'300': '300ms',
'500': '500ms',
'700': '700ms',
'1000': '1000ms',
},
},
variants: {
// ...
transitionDelay: ['responsive'],
},
// ...
}
New group-focus variant (#1577)
We've added a new group-focus variant that works just like the existing group-hover variant, but for focus states.
This is useful when you want to add custom focus style to a button or link that has some nested child you want to style in a specific way, for example, changing the color of an icon inside of a button when the button is focused:
<button class="group text-gray-600 focus:bg-gray-100 focus:text-gray-700">
<svg class="h-6 w-6 text-gray-400 group-focus:text-gray-500">
<!-- ... -->
</svg>
Submit
</button>
This variant not enabled for any utilities by default, but can be enabled in the variants section of your config file.
Support for specifying a default line-height for each font-size utility (#1532)
A common pattern we've run into in our own Tailwind projects is repeatedly pairing a font-size utility with a particular line-height utility, for example always using text-sm with leading-5.
Tailwind v1.3 now lets you specify a default line-height for each font-size utility in your config file, using a tuple of the form [fontSize, lineHeight]:
// tailwind.config.js
module.exports = {
theme: {
fontSize: {
// Will embed no line-height value
sm: '12px',
// Will use `font-size: 16px` and `line-height: 24px`
md: ['16px', '24px'],
},
},
}
.text-sm {
font-size: 12px;
}
.text-md {
font-size: 16px;
line-height: 24px;
}
The font-size utilities are generated before the line-height utilities in the final CSS, so you can still override the line-height for a particular font-size by simply adding a leading-{size} utility:
<!-- Will still be `line-height: 1`, even though the default line-height for `text-md` is `24px` (as per the example config above) -->
<div class="text-md leading-none"></div>
We haven't changed the default config to include default line-heights as that would be a breaking change, but this is a feature we will likely take advantage of in Tailwind 2.0 sometime in the future.
Support for breakpoint-specific padding for container class (#1398)
Prior to v1.3, you could configure the container class to have built-in horizontal padding like so:
// tailwind.config.js
module.exports = {
theme: {
container: {
padding: '2rem',
},
},
}
Tailwind v1.3 enhances this functionality to allow you to specify a different amount of padding for each breakpoint:
// tailwind.config.js
module.exports = {
theme: {
container: {
padding: {
default: '1rem',
sm: '2rem',
lg: '4rem',
xl: '5rem',
},
},
},
}
Added current to the default color palette (#1438)
The default color palette now includes current for currentColor, which simplifies some situations like creating buttons where the border color should match the text color:
<!-- Before -->
<button
class="text-gray-500 hover:text-gray-700 focus:text-gray-700 border border-gray-500 hover:border-gray-700 focus:border-gray-700"
>
<!-- ... -->
</button>
<!-- Now -->
<button class="text-gray-500 hover:text-gray-700 focus:text-gray-700 border border-current">
<!-- ... -->
</button>
Since this color has been added to the default color palette, it is available for textColor, borderColor, backgroundColor, and placeholderColor utilities automatically.
New inline-grid utility (#1375)
We've added an inline-grid utility for setting display: inline-grid. This probably should've been included in v1.2 and somehow got missed, but it's here now baby.
<span class="inline-grid grid-cols-3 col-gap-4">
<!-- ... -->
</span>
Will you ever use this? I never have, but it should still be there dammit.
New flow-root display utility (#1247)
We've added a new flow-root utility for display: flow-root. Never heard of it? Me neither until it was PR'd.
It behaves exactly like display: block with one magical difference: it prevents collapsing margins!
<div class="flow-root">
<!-- ... -->
</div>
You'll start to find all sorts of useful use-cases for this if you pay attention, like completely obsoleting clearfix hacks.
New clear-none utility (#1413)
This has been in the documentation for months but didn't actually exist in the framework — whoops.
It sets clear: none, which is mostly useful for resetting the clear property at different breakpoints.
<p class="clear-left md:clear-none">
<!-- ... -->
</p>
Only two people noticed it was documented but missing, so odds are you don't even care that we added this.
Tailwind CSS v1.2.0
This is probably the most exciting feature release in the history of Tailwind, so put on your seat belts.
New Features
- CSS Transition support
- CSS Transform support
- CSS Grid support
- Added max-w-{screen} utilities
- Added max-w-none utility
- Added
rounded-mdutility - Added
shadow-smutility - Added
shadow-xsutility - Added stroke-width utilities
- Added fixed line-height utilities
- Added additional display utilities for table elements
- Added box-sizing utilities
- Added clear utilities
- Config file dependencies are now watchable
- Allow plugins to extend the user's config
- Added new
pluginandplugin.withOptionsAPIs
CSS Transition support (#1273)
Tailwind now includes utilities for setting the transition-property, transition-duration, and transition-timing-function properties.
<button class="opacity-50 hover:opacity-100 transition-opacity duration-100 ease-out">...</button>
Expand to see the default values for these utilities
// tailwind.config.js
module.exports = {
theme: {
// .transition-{property}
transitionProperty: {
none: 'none',
all: 'all',
default: 'background-color, border-color, color, fill, stroke, opacity, box-shadow, transform',
colors: 'background-color, border-color, color, fill, stroke',
opacity: 'opacity',
shadow: 'box-shadow',
transform: 'transform',
},
// .ease-{timingFunction}
transitionTimingFunction: {
linear: 'linear',
in: 'cubic-bezier(0.4, 0, 1, 1)',
out: 'cubic-bezier(0, 0, 0.2, 1)',
'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)',
},
// .duration-{duration}
transitionDuration: {
'75': '75ms',
'100': '100ms',
'150': '150ms',
'200': '200ms',
'300': '300ms',
'500': '500ms',
'700': '700ms',
'1000': '1000ms',
},
}
}
For more information, check out the documentation.
CSS Transform support (#1272)
Tailwind now includes utilities for scaling, rotating, translating, and skewing elements.
<span class="transform scale-150 rotate-45 translate-x-full origin-center"></span>
Expand to see the default values for these utilities
// tailwind.config.js
module.exports = {
theme: {
// .origin-{origin}
transformOrigin: {
center: 'center',
top: 'top',
'top-right': 'top right',
right: 'right',
'bottom-right': 'bottom right',
bottom: 'bottom',
'bottom-left': 'bottom left',
left: 'left',
'top-left': 'top left',
},
// .scale-{scale}
// .scale-x-{scale}
// .scale-y-{scale}
scale: {
'0': '0',
'50': '.5',
'75': '.75',
'90': '.9',
'95': '.95',
'100': '1',
'105': '1.05',
'110': '1.1',
'125': '1.25',
'150': '1.5',
},
// .rotate-{angle}
rotate: {
'-180': '-180deg',
'-90': '-90deg',
'-45': '-45deg',
'0': '0',
'45': '45deg',
'90': '90deg',
'180': '180deg',
},
// .translate-x-{distance}
// .translate-y-{distance}
// .-translate-x-{distance}
// .-translate-y-{distance}
translate: (theme, { negative }) => ({
...theme('spacing'),
...negative(theme('spacing')),
'-full': '-100%',
'-1/2': '-50%',
'1/2': '50%',
full: '100%',
}),
// .skew-x-{amount}
// .skew-y-{amount}
skew: {
'-12': '-12deg',
'-6': '-6deg',
'-3': '-3deg',
'0': '0',
'3': '3deg',
'6': '6deg',
'12': '12deg',
},
}
}
One notable difference in how this works vs. other utilities in Tailwind is that the transform utility acts sort of like a "toggle" — you need to add that class to "enable" transforms on an element but on its own it doesn't actually apply any transforms.
You apply the actual transforms by stacking additional utilities for the types of transforms you'd like to apply, like scale-150 to scale an element to 150% of its size, or rotate-45 to rotate it 45 degrees.
To make it possible to compose multiple transforms like this, we've implemented this feature using CSS custom properties, which means transforms in Tailwind are not supported in IE11. If you need to support IE11 and would like to use transforms in your project, you'll need to write custom CSS as you would have in earlier versions of Tailwind.
For more information, check out the documentation.
CSS Grid utilities (#1274)
Tailwind now includes utilities for CSS Grid Layout.
<div class="grid grid-cols-2 lg:grid-cols-8 gap-6">
<div class="col-span-1 lg:col-span-3"></div>
<div class="col-span-1 lg:col-span-3"></div>
<div class="col-start-1 col-end-3 lg:col-start-4 lg:col-end-8"></div>
<div class="col-span-1 col-start-1 lg:col-span-4 lg:col-start-2"></div>
<div class="col-span-1 col-end-3 lg:col-span-6 lg:col-end-9"></div>
</div>
Expand to see the default values for these utilities
// tailwind.config.js
module.exports = {
theme: {
// .gap-{spacing}, .row-gap-{spacing}, .col-gap-{spacing}
gap: theme => theme('spacing'),
// .grid-cols-{cols}
gridTemplateColumns: {
none: 'none',
'1': 'repeat(1, minmax(0, 1fr))',
'2': 'repeat(2, minmax(0, 1fr))',
'3': 'repeat(3, minmax(0, 1fr))',
'4': 'repeat(4, minmax(0, 1fr))',
'5': 'repeat(5, minmax(0, 1fr))',
'6': 'repeat(6, minmax(0, 1fr))',
'7': 'repeat(7, minmax(0, 1fr))',
'8': 'repeat(8, minmax(0, 1fr))',
'9': 'repeat(9, minmax(0, 1fr))',
'10': 'repeat(10, minmax(0, 1fr))',
'11': 'repeat(11, minmax(0, 1fr))',
'12': 'repeat(12, minmax(0, 1fr))',
},
// .col-{value}
gridColumn: {
auto: 'auto',
'span-1': 'span 1 / span 1',
'span-2': 'span 2 / span 2',
'span-3': 'span 3 / span 3',
'span-4': 'span 4 / span 4',
'span-5': 'span 5 / span 5',
'span-6': 'span 6 / span 6',
'span-7': 'span 7 / span 7',
'span-8': 'span 8 / span 8',
'span-9': 'span 9 / span 9',
'span-10': 'span 10 / span 10',
'span-11': 'span 11 / span 11',
'span-12': 'span 12 / span 12',
},
// .col-start-{value}
gridColumnStart: {
auto: 'auto',
'1': '1',
'2': '2',
'3': '3',
'4': '4',
'5': '5',
'6': '6',
'7': '7',
'8': '8',
'9': '9',
'10': '10',
'11': '11',
'12': '12',
'13': '13',
},
// .col-end-{value}
gridColumnEnd: {
auto: 'auto',
'1': '1',
'2': '2',
'3': '3',
'4': '4',
'5': '5',
'6': '6',
'7': '7',
'8': '8',
'9': '9',
'10': '10',
'11': '11',
'12': '12',
'13': '13',
},
// .grid-rows-{rows}
gridTemplateRows: {
none: 'none',
'1': 'repeat(1, minmax(0, 1fr))',
'2': 'repeat(2, minmax(0, 1fr))',
'3': 'repeat(3, minmax(0, 1fr))',
'4': 'repeat(4, minmax(0, 1fr))',
'5': 'repeat(5, minmax(0, 1fr))',
'6': 'repeat(6, minmax(0, 1fr))',
},
// .row-{value}
gridRow: {
auto: 'auto',
'span-1': 'span 1 / span 1',
'span-2': 'span 2 / span 2',
'span-3': 'span 3 / span 3',
'span-4': 'span 4 / span 4',
'span-5': 'span 5 / span 5',
'span-6': 'span 6 / span 6',
},
// .row-start-{value}
gridRowStart: {
auto: 'auto',
'1': '1',
'2': '2',
'3': '3',
'4': '4',
'5': '5',
'6': '6',
'7': '7',
},
// .row-end-{value}
gridRowEnd: {
auto: 'auto',
'1': '1',
'2': '2',
'3': '3',
'4': '4',
'5': '5',
'6': '6',
'7': '7',
},
}
}
By default we ship the necessary utilities to construct grids with 1–12 explicit columns and 1-6 explicit rows and place elements anywhere in that grid.
Note that the approach we've taken to supporting CSS Grid is not compatible with IE11. For building grid layouts in older browsers, we recommend using Flexbox instead of CSS Grid.
For more information, check out the documentation.
Added max-w-{screen} utilities (#1284)
Tailwind's default max-width scale now includes values to match your breakpoints, taking the form max-w-screen-{breakpointName}.
<div class="max-w-screen-lg">...</div>
These are useful when you need behavior similar to the container class but only for certain sizes.
Added max-w-none utility (#1283)
Tailwind's default max-width scale now includes a none value for removing any max-width constraint an element might have.
<div class="max-w-md lg:max-w-none">...</div>
Added rounded-md utility (#1281)
Tailwind's default border-radius scale now includes an md value for giving an element a 6px border radius.
<div class="rounded-md"></div>
Added shadow-sm utility (#1280)
Tailwind's default box-shadow scale now includes an sm value for giving an element a very subtle small shadow — great for giving buttons or inputs a bit of depth without being super in-your-face.
<div class="shadow-sm"></div>
For more information, check out the pull request.
Added shadow-xs utility (#1333)
Tailwind's default box-shadow scale now includes an xs value for giving an element a very subtle outline shadow, very useful for stacking with other shadows when you need a tiny bit of extra distinction from the background.
<div class="shadow-md rounded-md">
<div class="shadow-xs rounded-md">
<!-- ... -->
</div>
</div>
For more information, check out the pull request.
Added stroke-width utilities (#1094)
Tailwind now includes utilities for controlling the stroke-width property of SVG elements.
<svg class="stroke-2">...</svg>
Expand to see the default values for these utilities
// tailwind.config.js
module.exports = {
theme: {
// .stroke-{width}
strokeWidth: {
'0': '0',
'1': '1',
'2': '2',
}
}
}
For more information, check out the documentation.
Added fixed line-height utilities (#1362)
Tailwind now includes a sensible set of fixed-value line-height utilities in addition to the existing relative line-height utilities.
<svg class="leading-5">...</svg>
Expand to see the default values for these utilities
// tailwind.config.js
module.exports = {
theme: {
// .leading-{size}
lineHeight: {
none: '1',
tight: '1.25',
snug: '1.375',
normal: '1.5',
relaxed: '1.625',
loose: '2',
'3': '.75rem',
'4': '1rem',
'5': '1.25rem',
'6': '1.5rem',
'7': '1.75rem',
'8': '2rem',
'9': '2.25rem',
'10': '2.5rem',
}
}
}
For more information, check out the documentation.
Added additional display utilities for table elements (#954)
Tailwind now includes a complete set of display utilities for table elements.
<div class="table-header-group">...</div>
We've added table-caption, table-column, table-column-group, table-footer-group, table-header-group, and table-row-group.
Added box-sizing utilities (#1031)
Tailwind now includes box-border and box-content utilities for setting the box-sizing property of an element.
<div class="box-content">...</div>
These can be useful when working with third party libraries that rely on the default browser value of box-sizing: content-box, which we override in our base styles.
For more information, check out the documentation.
Added clear utilities (#1051)
Tailwind now includes clear-left, clear-right, and clear-both utilities for clearing floats using the clear property.
<div class="clear-left">...</div>
For more information, check out the documentation.
Config file dependencies are now watchable (#1072)
If you are require-ing other modules inside your tailwind.config.js file, those files will now be automatically watched for changes when running a webpack/PostCSS watcher.
Previously, you'd have to restart your watcher any time you changed those files. Now those changes will be noticed automatically and your CSS will just rebuild as expected — hurray!
For more information, check out the pull request.
Added new plugin and plugin.withOptions APIs (#1268)
In prior versions of Tailwind, plugins were just simple anonymous functions:
// my-plugin.js
module.exports = function ({ addUtilities, variants, theme }) {
// ...
}
While this approach still works great and is 100% supported, Tailwind v1.2 adds two new official APIs for creating plugins that allow us to support some helpful new features.
The new tailwindcss/plugin module exports a function that you can use to create a plugin like so:
// my-plugin.js
const plugin = require('tailwindcss/plugin')
module.exports = plugin(function ({ addUtilities, variants, theme }) {
// ...
})
You can also use plugin.withOptions to create a plugin that accepts some additional user configuration right in the plugins section of your config:
// my-plugin.js
const plugin = require('tailwindcss/plugin')
module.exports = plugin.withOptions(function (options) {
return function ({ addUtilities, variants, theme }) {
// ...
}
})
Previously if you designed a plugin this way, users would have to make sure to invoke your plugin in their config, even if they had no custom configuration to provide:
// tailwind.config.js
module.exports = {
plugins: [
require('plugin-with-no-options'),
require('plugin-that-has-options')(),
]
}
Now Tailwind is smart enough to invoke the function on the user's behalf, so if they don't want to provide any options, they can just require the plugin:
// tailwind.config.js
module.exports = {
plugins: [
require('plugin-with-no-options'),
require('plugin-that-has-options'),
]
}
Allow plugins to extend the user's config (#1162)
Plugins can now extend the user's config file by providing their own configuration object as a second argument to the new plugin API:
// my-plugin.js
const plugin = require('tailwindcss/plugin')
module.exports = plugin(function ({ addUtilities, variants, theme }) {
// ...
}, {
theme: {
myPluginName: {...},
},
variants: {
myPluginName: ['responsive'],
}
})
This also works using the plugin.withOptions API, just pass a function that accepts your options and returns your config:
// my-plugin.js
const plugin = require('tailwindcss/plugin')
module.exports = plugin.withOptions(function (options) {
return function ({ addUtilities, variants, theme }) {
// ...
}
}, function (options) {
return {
theme: {
myPluginName: {...},
},
variants: {
myPluginName: ['responsive'],
}
}
})
By providing your default theme values/variants this way, users can use Tailwind's extend feature to extend your defaults just like they can with core plugins.
-
Fixes a bug where the
.groupclass was not receiving the user's configured prefix when using theprefixoption (#1216).Note: Although this is a bugfix it could affect your site if you were working around the bug in your own code by not prefixing the
.groupclass. I'm sorry 😞
- Fixes an issue where in some cases function properties in the user's
themeconfig didn't receive the second utils argument (#1180)
- Fixes a bug with horizontal rules where they were displayed with a 2px border instead of a 1px border (#1079)
- Fixes a bug with horizontal rules where they were rendered with default top/bottom margin (#1079)
- Fixes issue where values like
autowould fail to make it through the default negative margin config (#1070)
Tailwind CSS v1.1
The first new feature release since v1.0 has arrived! Tailwind v1.1 includes a bunch of new stuff, but I think the things you'll probably be most excited about are:
- New screenreader visibility utilities
- New utilities for setting the placeholder color on form elements
- New variants for
first-child,last-child,nth-child(odd), andnth-child(even)
Important note — although this is a minor release, it includes two bug fixes that may have a superficial impact on how your site looks if you are using horizontal rules in your site or are relying on the default placeholder color defined in Tailwind's base styles.
Be sure to read through the fixes section before upgrading to understand the impact.
Changes
- New features
- Added utilities for screenreader visibility
- Added utilities for placeholder color
- First, last, even, and odd child variants
- Disabled variant
- Visited variant
- Increase utility specificity using a scope instead of
!important - Add hover/focus variants for opacity by default
- Added
border-doubleutility - Support negative prefix for boxShadow and letterSpacing plugins
- Support passing config path via object
- Fixes
New features
Added utilities for screenreader visibility (#964)
Tailwind now includes a new accessibility core plugin that adds sr-only and not-sr-only utilities for controlling whether an element is visually hidden but still accessible to screen readers.
Use sr-only to hide an element visually without hiding it from screen readers:
<a href="#">
<svg><!-- ... --></svg>
<span class="sr-only">Settings</span>
</a>
Use not-sr-only to undo sr-only, making an element visible to sighted users as well as screen readers. This can be useful when you want to visually hide something on small screens but show it on larger screens for example:
<a href="#">
<svg><!-- ... --></svg>
<span class="sr-only sm:not-sr-only">Settings</span>
</a>
By default, responsive and focus variants are generated for these utilities. You can use focus:not-sr-only to make an element visually hidden by default but visible when the user tabs to it — useful for "skip to content" links:
<a href="#" class="sr-only focus:not-sr-only">
Skip to content
</a>
You can customize which variants are generated by adding an accessibility key to the variants section of your config file:
// tailwind.config.js
module.exports = {
// ...
variants: {
accessibility: ['responsive', 'hover', 'focus', 'active']
}
}
Added utilities for placeholder color (#1063)
Tailwind now includes placeholder-{color} utilities for setting the placeholder color of form elements:
<input class="text-gray-900 placeholder-gray-500 ...">
By default, responsive and focus variants are generated for these utilities. You can customize which variants are generated by adding a placeholderColor key to the variants section of your config file:
// tailwind.config.js
module.exports = {
// ...
variants: {
placeholderColor: ['responsive', 'hover', 'focus', 'active']
}
}
First, last, even, and odd child variants (#1024, #1027)
Tailwind now includes variants for targeting the first-child, last-child, nth-child(odd), and nth-child(even) pseudo-classes.
These allow you to apply a utility to an element only when it is the first, last, odd, or even child of its parent. Very useful for things like "put a border between all of these items that are generated in a loop" for example:
<ul>
<li v-for="item in items" class="border-t first:border-t-0">{{ item }}</li>
</ul>
...or to add zebra striping to a table:
<table>
<tr v-for="row in rows">
<td class="odd:bg-white even:bg-gray-200">...</td>
<td class="odd:bg-white even:bg-gray-200">...</td>
</tr>
</table>
The pseudo-classes map to variants as follows:
| Pseudo-class | Variant |
|---|---|
:first-child | first:{utility} |
:last-child | last:{utility} |
:nth-child(odd) | odd:{utility} |
:nth-child(even) | even:{utility} |
Something worth emphasizing is that these variants apply to the child element itself, not to the children of the element with the utility. This is consistent with how other pseudo-class variants in Tailwind work, and how the :first/last-child pseudo selectors work in CSS.
Said again in code:
<!-- This is *not* how these variants are meant to be used -->
<ul class="first:border-t-0">
<li v-for="item in items" class="border-t">{{ item }}</li>
</ul>
<!-- The utilities should be used on the child itself, not the parent -->
<ul>
<li v-for="item in items" class="border-t first:border-t-0">{{ item }}</li>
</ul>
These variants are disabled by default for all utilities, but can be enabled for each core plugin in the variants section of your config file:
// tailwind.config.js
module.exports = {
// ...
variants: {
- backgroundColor: ['responsive', 'hover', 'focus']
+ backgroundColor: ['responsive', 'first', 'last', 'even', 'odd', 'hover', 'focus']
}
}
Disabled variant (#732)
Tailwind now includes a disabled variant for styling elements when they are disabled:
<input class="disabled:opacity-50 ...">
This variant is disabled by default for all utilities, but can be enabled for each core plugin in the variants section of your config file:
// tailwind.config.js
module.exports = {
// ...
variants: {
- opacity: ['responsive', 'hover', 'focus']
+ opacity: ['responsive', 'hover', 'focus', 'disabled']
}
}
Visited variant (#976)
Tailwind now includes a visited variant for styling visited links:
<a href="#" class="text-blue-500 visited:text-purple-500 ...">
This variant is disabled by default for all utilities, but can be enabled for each core plugin in the variants section of your config file:
// tailwind.config.js
module.exports = {
// ...
variants: {
- textColor: ['responsive', 'hover', 'focus']
+ textColor: ['responsive', 'hover', 'focus', 'visited']
}
}
Increase utility specificity using a scope instead of !important (#1020)
Prior to Tailwind v1.1, you may have used the important option to make sure that no matter what, your utilities always took precedence over any other styles applied to an element:
// tailwind.config.js
module.exports = {
important: true,
// ...
}
This is a totally reasonable thing to do but it can introduce some issues when incorporating third-party JS libraries that add inline styles to your elements, because Tailwind's important utilities would defeat the inline styles. This is really common with animation libraries for example.
Tailwind v1.1 adds the ability to make utilities "important" in a less aggressive manner by providing a selector instead of a boolean to the important option:
// tailwind.config.js
module.exports = {
important: '#app',
// ...
}
What this will do is prefix all of your utilities with that selector, increasing their specificity without actually making them !important.
By using an ID for this selector and adding that ID to the root element of your site, all of Tailwind's utilities will have a high enough specificity to defeat all other classes used in your project without interfering with inline styles:
<html>
<!-- ... -->
<style>
.high-specificity .nested .selector {
color: blue;
}
</style>
<body id="app">
<!-- Will be #bada55 -->
<div class="high-specificity">
<div class="nested">
<!-- Will be red-500 -->
<div class="selector text-red-500"><!-- ... --></div>
</div>
</div>
<!-- Will be #bada55 -->
<div class="text-red-500" style="color: #bada55;"><!-- ... --></div>
</body>
</html>
If this seems weird or complicated to you, chances are you haven't run into this situation before and can just ignore this feature. If you've been bitten by this problem in the past though, you'll understand exactly why this feature was added.
Add hover/focus variants for opacity by default (#1065)
Opacity utilities now have hover and focus variants enabled by default:
<div class="opacity-50 hover:opacity-100"><!-- ... --></div>
You can disable these if needed by overriding the default opacity variants in the variants section of your config file:
// tailwind.config.js
module.exports = {
// ...
variants: {
+ opacity: ['responsive']
}
}
Added border-double utility (#1040)
Tailwind now includes a border-double utility for, well, giving elements a double border.
<div class="border border-double"><!-- ... --></div>
Support negative prefix for boxShadow and letterSpacing plugins (#992)
The boxShadow and letterSpacing plugins now support the negative modifier prefix like zIndex, margin, and inset utilities do:
// tailwind.config.js
module.exports = {
theme: {
letterSpacing: {
'-1': '-.05em',
},
boxShadow: {
'-sm': 'inset 0 2px 4px rgba(0,0,0.1)',
},
}
}
This would generate classes like -tracking-1 and -shadow-sm, rather than tracking--1 and shadow--sm like you might expect.
Support passing config path via object (#1062)
When adding Tailwind to your PostCSS config, you can now specify the config file path using an object syntax instead of only a string:
// postcss.config.js
module.exports = {
plugins: [
// Existing syntax:
require('tailwindcss')('custom-config.js'),
// Added syntax:
require('tailwindcss')({ config: 'custom-config.js' }),
]
}
This makes Tailwind compatible with PostCSS's object configuration syntax, which wasn't previously possible:
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: { config: 'custom-config.js' },
}
}
See the pull request for all of the details on how this works.
Fixes
Placeholders no longer have a default opacity (#1064)
Prior to v1.1, Tailwind included the following base styles for form elements:
input::placeholder, textarea::placeholder {
color: inherit;
opacity: 0.5;
}
Due to a bug in IE11, this mistakenly caused the input and textarea elements themselves to be rendered at 50% opacity, not just the placeholders.
We've fixed this in v1.1 by changing the base styles to this:
input::placeholder, textarea::placeholder {
color: #a0aec0;
}
This sets the default placeholder to Tailwind's gray-500 color instead of inheriting the current color and changing the opacity.
This means that if you weren't assigning a custom placeholder color to your form elements, they will now look a bit different than they did before.
This will be most apparent in situations where you have changed the text color of an input and were relying on the inherit behavior — for example an input with red text where you also want the placeholder to be red.
Now that Tailwind includes placeholder color utilities, you can correct these superficial visual differences by adding a placeholder utility:
<input class="text-red-500 placeholder-red-300">
Make horizontal rules visible by default (#991)
Prior to v1.1, horizontal rules were mistakenly invisible in Tailwind because they had no border-width assigned.
Now hr elements have a default border-width of 1px so they actually show up when you create one.
This is technically a very minor breaking change in the event that you were actually depending on hr elements not having a default border. You can remove the border by adding border-0:
<hr class="border-0">
Generate correct negative margins when using calc (#1058)
Negative margin values were calculated fairly naively in previous versions of Tailwind by simply prefixing the positive value with a -. This of course didn't work if you were using more complex values like calc(100vw - 10rem) or var(--spacing-sm).
Tailwind v1.1 fixes this issue by using calc and the reduce-css-calc package to calculate the correct value to use.
Read more about it in the pull request.
- Fixes issue where modifiers would mutate nested rules (https://github.com/tailwindcss/tailwindcss/pull/1053)
- Support built-in variants for utilities that include pseudo-elements (#970)
- Update several dependencies, including postcss-js which fixes an issue with using
!importantdirectly in Tailwind utility plugins
- Increase precision of percentage width values to avoid 1px rounding issues in grid layouts (#961)
- Throws an error when someone tries to use
@tailwind preflightinstead of@tailwind base, this is the source of many support requests
- Fixes a bug where
@screenrules weren't bubbled properly when nested in plugins (#941)
- Fixes a bug where global variants weren't properly merged (#911)
- Update our PostCSS related dependencies (#618)
- Fix bug where class names containing a
.character had the responsive prefix added in the wrong place (#613)
- Update Normalize to v8.0.1 (#588)
- Add
--no-autoprefixeroption to CLIbuildcommand (#584)
- Update autoprefixer dependency (fixes #583)
New Features
Registering new variants from plugins (#505)
(Introduced as an experiment in v0.6.2, now promoted to an official feature)
Plugins can now add their own variants (like hover, focus, group-hover, etc.) to Tailwind.
To get started, destructure the new addVariant function from the object passed to your plugin, and call it with the name of the variant you'd like to add and a callback that can be used to manipulate the PostCSS nodes where the variant is being applied:
module.exports = {
plugins: [
function({ addVariant }) {
addVariant('important', ({ container }) => {
container.walkRules(rule => {
rule.selector = `.\\!${rule.selector.slice(1)}`
rule.walkDecls(decl => {
decl.important = true
})
})
})
}
]
}
Documentation is coming soon, but for now learn more in the pull request.
Variant order can be customized per module (#505)
(Introduced as an experiment in v0.6.2, now promoted to an official feature)
Variants are now generated in the order that they are specified in the modules section of your config file, rather than in a hard-coded static order like in previous versions of Tailwind.
That means that if you want focus variants to defeat hover variants for background colors, but you want the opposite behavior for border colors, you can actually do that now by specifying the order in your config:
modules.exports = {
// ...
modules: {
// ...
backgroundColors: ['responsive', 'hover', 'focus'],
// ...
borderColors: ['responsive', 'focus', 'hover'],
// ...
}
}
Note that this doesn't affect responsive variants — those are a special case since responsive versions are also generated for other variants, and we group responsive declarations to optimize the resulting CSS.
Added focus-within variant (#463)
Tailwind now includes a focus-within variant that you can use to change how an element is styled if an element inside of it has focus.
<div class="focus-within:shadow-lg">
<label>
<span>Email</span>
<input type="email">
</label>
</div>
Learn about the :focus-within pseudo-class on MDN
By default we don't generate focus-within variants for any utilities, but you can change this in the modules section your Tailwind configuration file:
modules.exports = {
// ...
modules: {
// ...
- backgroundColors: ['responsive', 'hover', 'focus'],
+ backgroundColors: ['responsive', 'focus-within', 'hover', focus'],
// ...
}
}
Fancy CLI updates (#554)
Tailwind 0.7.0 includes a completely rewritten CLI tool with nicer output and a better user experience.
All of the existing functionality is still there with the same API, it just looks better.
Option to generate config without comments (#558)
You can now use the --no-comments option when running tailwind init to generate a config file that excludes all of the inline documentation comments.
This is a great way to make your config file easier to skim if you're an experienced Tailwind user who doesn't need the comments.
Make configured prefix optional when using @apply (#553)
If you're prefixing your generated utilities, including that prefix when using @apply is now optional.
/* Before */
.my-component {
@apply tw-bg-blue tw-text-white tw-font-bold;
}
/* Now */
.my-component {
@apply bg-blue text-white font-bold;
}
You can continue to use the prefix if you like, or drop it if you prefer a terser syntax.
Improve Flexbox behavior in IE 10/11 (#550)
IE 10 and 11 interpret the shorthand flex property differently than other browsers.
Tailwind now specifies explicit grow, shrink, and basis values for the flex-1, flex-auto, and flex-initial utilities for a more consistent cross-browser experience.
Learn more at the flexbugs repo (bugs #4 and #6 specifically)
Changes
Variant order in modules config is now significant (#505)
Impact: Low, Effort: Low
Prior to 0.7.0, variants were always generated in the same order, regardless of the order specified in the modules section of your config file.
Now, variants are generated in the they are specified. That means that if your config file currently lists variants in a different order than the <=0.6.6 default variant order, those variants will appear in a different order in your CSS.
To preserve the <=0.6.6 behavior, simply edit the modules section of your config file to make sure your variants are listed in the following order:
modules.exports = {
// ...
modules: {
// ...
[anyModule]: ['group-hover', 'hover', 'focus-within', 'focus', 'active']
// ...
}
}
Normalize.css updated to v8.0.0 (#537)
Impact: Low, Effort: Low
We've updated our dependency on Normalize.css from 7.0.0 to 8.0.0.
This drops support for very old browsers like IE9, Android 4.3, Safari 8, and iOS Safari 7-8.
If you still need to support those browsers, remove @tailwind preflight from your CSS, add Normalize.css 7.0.0 to your project, and manually add our additional preflight base styles.
Removed CSS fix for Chrome 62 button border radius change (#579)
Impact: Low, Effort: Low
When Chrome 62 was released, it introduced a user agent stylesheet change that added a default border radius to all buttons.
This messed up styles for like half of the internet (including sites like GitHub itself), so Chrome reverted the change in Chrome 63.
We included a fix for this in Tailwind with the intention to remove it when Chrome 62 was no longer in common use. Now that usage has dropped to 0.09%, we've removed our fix.
If this is a problem for you (it isn't), you can add the removed styles back to your project right after @tailwind preflight.
- Promote
shadowLookupfrom experiment to official feature
- Fixes an issue where units were stripped from zero value properties (#533)
- Fixes an issue where changes to your configuration file were ignored when using
webpack --watch(#520)
- Fixes an issue where
@tailwind utilitiesgenerated no output (#518)
New Features
Added table layout utilities for styling tables (#504)
Tailwind now includes .table-auto and .table-fixed utilities for controlling the table-layout property.
By default we only generate responsive variants for these utilities but you can change this through the tableLayout module your Tailwind configuration file.
We've also updated Preflight to set border-collapse: collapse by default on all tables.
Configuration can now be passed as an object (#508)
Normally you pass your configuration to Tailwind by giving it a path:
// .postcssrc.js or similar
module.exports = {
// ...
plugins: [
// ...
require('tailwindcss')('./tailwind.js'),
]
}
Now you can also pass an object directly:
// .postcssrc.js or similar
const tailwindConfig = {
// ...
}
module.exports = {
// ...
plugins: [
// ...
require('tailwindcss')(tailwindConfig),
]
}
Note that we still recommend passing a path instead of an object, because Tailwind can't rebuild when the config changes if it doesn't have a config file to watch.
Changes
Default config file changes
Impact: Low, Effort: Low
The default config file now includes a new tableLayout entry in the modules section.
Simply add this to your config file to sync it with this change, or leave it out if you just want to inherit the default configuration for the new module:
module.exports = {
// ...
modules: {
// ...
svgStroke: [],
+ tableLayout: ['responsive'],
textAlign: ['responsive'],
// ...
}
}
Experiments
Tailwind 0.6.2 includes two new major features that are disabled by default behind flags.
These features may be changed or removed at any time without any regard for semantic versioning, so please do not depend on them in production just yet.
Registering new variants from plugins (#505)
Plugins can now add their own variants (like hover, focus, group-hover, etc.) to Tailwind.
To get started, destructure the new addVariant function from the object passed to your plugin, and call it with the name of the variant you'd like to add and a callback that can be used to manipulate the PostCSS nodes where the variant is being applied:
module.exports = {
plugins: [
function({ addVariant }) {
addVariant('important', ({ container }) => {
container.walkRules(rule => {
rule.selector = `.\\!${rule.selector.slice(1)}`
rule.walkDecls(decl => {
decl.important = true
})
})
})
}
]
}
Proper documentation will be provided when this feature is stable and official, but in the mean time you can learn more by reading this comment from the pull request.
To enable this experiment, add pluginVariants: true under an experiments key in your Tailwind config:
module.exports = {
// ...
experiments: {
pluginVariants: true
}
}
Allow @apply-ing classes that aren't defined but would be generated (#516)
You can now use @apply to apply classes that aren't defined but would exist if @tailwind utilities was included in the same CSS file. This is mostly useful on projects that are setup to process multiple styles independently, for example a Vue.js project where you are using the <style> block of your single file components.
To enable this experiment, add shadowLookup: true under an experiments key in your Tailwind config:
module.exports = {
// ...
experiments: {
shadowLookup: true
}
}
-
Fix incorrect box-shadow syntax for the
.shadow-outlineutility 🤦♂️ : #503If you generated a config file using v0.6.0, you'll want to make this same change in your own config file.
- New Features
- Added border collapse utilities for styling tables
- Added more axis-specific overflow utilities
- Added
.outline-noneutility for suppressing focus styles - Added
.shadow-outlineutility as an alternative to default browser focus styles - Extended default padding, margin, negative margin, width, and height scales
- Enable focus and hover variants for more modules by default
- Changes
New Features
Added border collapse utilities for styling tables (#489)
Tailwind now includes .border-collapse and .border-separate utilities for controlling the border-collapse property.
By default we don't generate any variants for these utilities (not even responsive variants) but you can change this through the borderCollapse module your Tailwind configuration file.
We've also updated Preflight to set border-collapse: collapse by default on all tables.
Added more axis-specific overflow utilities (#445)
In addition to .overflow-hidden and .overflow-visible, Tailwind now includes .overflow-x-hidden, .overflow-y-hidden, .overflow-x-visible and .overflow-y-visible for controlling overflow along a specific axis.
Added .outline-none utility for suppressing focus styles (#491)
Tailwind now includes a .outline-none utility for setting outline: 0 on an element to prevent the default browser focus ring.
By default, we also generate a focus variant (focus:outline-none) but no responsive variants.
Added .shadow-outline utility as an alternative to default browser focus styles (#491)
Outlines don't follow an element's border radius in most browsers, so a common practice is disable the browser's default focus outline and use a colored box-shadow to highlight focused elements.
Tailwind now includes a blue .shadow-outline utility that can be used for this purpose.
We've also enabled focus variants for box shadows by default, so you can add an outline shadow on focus by doing something like this:
<button class="focus:outline-none focus:shadow-outline ..."></button>
Extended default padding, margin, negative margin, width, and height scales (#499)
Tailwind's default configuration now includes more padding, margin, and negative margin sizes:
padding/margin/negativeMargin: {
'px': '1px',
'0': '0',
'1': '0.25rem',
'2': '0.5rem',
'3': '0.75rem',
'4': '1rem',
+ '5': '1.25rem',
'6': '1.5rem',
'8': '2rem',
+ '10': '2.5rem',
+ '12': '3rem',
+ '16': '4rem',
+ '20': '5rem',
+ '24': '6rem',
+ '32': '8rem',
}
We've also added 5 to the height and width scales to avoid any holes when compared with the spacing scales:
width/height: {
'auto': 'auto',
'px': '1px',
'1': '0.25rem',
'2': '0.5rem',
'3': '0.75rem',
'4': '1rem',
+ '5': '1.25rem',
'6': '1.5rem',
'8': '2rem',
'10': '2.5rem',
'12': '3rem',
'16': '4rem',
'24': '6rem',
'32': '8rem',
'48': '12rem',
'64': '16rem',
// ...
}
Enable focus and hover variants for more modules by default (#498)
Tailwind now includes focus and hover variants for more utilities out of the box.
We've added:
- Focus variants for background colors
- Focus variants for border colors
- Focus variants for font weight
- Hover and focus variants for box shadows
- Focus variants for text colors
- Focus variants for text style (underline, capitalization, etc.)
That means you do things like style an input differently based on whether it currently has focus:
<input class="border border-transparent bg-grey-lighter focus:bg-white focus:border-blue-light">
This was always possible if you had focus variants enabled in your own configuration, but Tailwind 0.6.0 sets these up for you out of the box so you don't need to make this common configuration change yourself. It also makes our CDN builds a little more powerful.
Changes
Removed default outline: none !important styles from focusable but keyboard-inaccessible elements (#491)
Impact: Low, Effort: Low
Prior to 0.6.0, our Preflight base styles included this rule (borrowed from suitcss/base):
/**
* Suppress the focus outline on elements that cannot be accessed via keyboard.
* This prevents an unwanted focus outline from appearing around elements that
* might still respond to pointer events.
*/
[tabindex="-1"]:focus {
outline: none !important;
}
This is a useful default for many projects, but in the odd case that it's problematic for you it is really annoying to work around.
With the addition of the .outline-none helper, we think it makes sense to remove this default style and encourage people to simply add focus:outline-none to any focusable but keyboard-inaccessible elements:
- <div tabindex="-1" class="...">...</div>
+ <div tabindex="-1" class="focus:outline-none ...">...</div>
Of course, you can also reintroduce this rule into your own base styles after Preflight:
@tailwind preflight;
+ [tabindex="-1"]:focus {
+ outline: none !important;
+ }
@tailwind components;
@tailwind utilities;
Moved screen prefix for responsive group-hover variants (#497)
Impact: Low, Effort: Medium
Prior to 0.6.0, if you had responsive and group-hover variants enabled for a module, the resulting CSS rule for a responsive group-hover variant would look something like this:
.sm\:group .group-hover\:bg-red { ... }
This was just a consequence of the responsive variants implementation and wasn't something we intentionally designed. It allowed you to do stuff like this:
<!-- Parent only behaves like a group on large screens and up, so the child -->
<!-- remains blue on small screens even when the parent is hovered. -->
<div class="lg:group">
<div class="bg-blue group-hover:bg-red">...</div>
</div>
This is not very useful in practice, and actually prevented you from changing how an element itself responded to group-hover on different screen sizes:
<div class="group">
<!-- Element was always red, even on small screens and up -->
<div class="group-hover:bg-red sm:group-hover:bg-blue">...</div>
</div>
In 0.6.0, the group-hover part of the selector adopts the screen prefix instead of the group part, so the code snippet from above will now work.
I would bet $100 that zero Tailwind users were depending on the pre-0.6.0 behavior, but if you were, the best solution is to write your own CSS for those parts of your project.
Default config file changes
Impact: Low, Effort: Low
The default config file now includes more padding, margin, negative margin, height, and width sizes; a new borderCollapse entry in the modules section; and enables more variants for more modules by default.
All the changes are purely additive, so you don't actually have to change any existing config files — all of your existing projects will work the same in 0.6.0 aside from the two breaking changes mentioned earlier in this changelog.
If you'd like to upgrade your config file to match the current default config file, you can view a diff of the changes here.
- Improve sourcemaps for replaced styles like
preflight - Fix bug where informational messages were being logged to stdout during build, preventing the ability to use Tailwind's output in Unix pipelines
- Fixes an issue with a dependency that had a security vulnerability: #438
-
Reverts a change that renamed the
.romanclass to.not-italicdue to the fact that it breaks compatibility with cssnext: https://github.com/postcss/postcss-selector-not/issues/10We'll stick with
.romanfor now with a plan to switch to.not-italicin another breaking version should that issue get resolved inpostcss-selector-not.
New Features
Plugin system
Tailwind now includes a feature-rich plugin system that allows people to create reusable third-party packages that can hook into Tailwind's compilation process to add new styles.
// ...
module.exports = {
// ...
plugins: [
function({ addUtilities, addComponents, config, prefix, e }) {
addComponents(
{
['.btn-blue']: {
backgroundColor: 'blue',
},
},
{ respectPrefix: true }
)
},
],
// ...
}
Documentation is coming very shortly, but in the mean time you can learn more through these two pull requests:
Update: Documentation is now available: https://tailwindcss.com/docs/plugins
Added .sticky position utility
Tailwind now includes a .sticky utility for setting an element to position: sticky. This isn't supported by IE 11, but falls back fairly gracefully with no effort so we decided to include it out of the box.
Learn more about sticky positioning at MDN
Added .cursor-wait and .cursor-move utilities
In addition to .cursor-auto, .cursor-default, .cursor-pointer, and .cursor-not-allowed, Tailwind now includes .cursor-wait to indicate when the application is busy, and .cursor-move to indicate that an element can be moved.
Added .bg-auto background size utility
To allow resetting an element's background size at other breakpoints, Tailwind now includes a .bg-auto utility:
<div class="bg-cover md:bg-auto">...</div>
Background sizes are now customizable
If you'd like to customize the available background size utilities in your project, you can now do so by adding a backgroundSize key to your Tailwind config:
module.exports = {
// ...
backgroundSize: {
'auto': 'auto',
'cover': 'cover',
'contain': 'contain',
},
}
Support for active variants
In addition to hover, focus, and group-hover, Tailwind now includes support for active variants of each utility:
module.exports = {
// ...
modules: {
// ...
backgroundColors: ['hover', 'active'],
// ...
}
}
Better postcss-import support
If you're using postcss-import to inline your imports, you can't use @tailwind preflight or @tailwind utilities directly in a file that contains other imports, due to postcss-import staying strict to the CSS spec for import statements.
Previously, the workaround for this was to create a new file just for @tailwind preflight and another new file just for @tailwind utilities, and then @import those files into your main stylesheet.
It turns out postcss-import can import files from node_modules, so as of v0.5.0, you can now import these files directly from Tailwind itself:
@import "tailwindcss/preflight";
@import "tailwindcss/utilities";
Configuration options for the .container component
Now that the .container component is provided as a built-in plugin, it exposes optional configuration for centering the container by default as well as adding default horizontal padding:
// ...
module.exports = {
// ...
plugins: [
require('tailwindcss/plugins/container')({
center: true,
padding: '2rem',
}),
],
}
Containers are still not centered with no padding by default, and the configuration object is not required:
// ...
module.exports = {
// ...
plugins: [
require('tailwindcss/plugins/container')(),
],
}
You can also disable the container component entirely now by removing the plugin from the plugins list:
// ...
module.exports = {
// ...
plugins: [
- require('tailwindcss/plugins/container')(),
],
}
Changes
The .container component is now a built-in plugin
Impact: Large, Effort: Low
The .container component has long been a bit of an oddball in the Tailwind codebase; it's the only set of styles that can't be used with state variants and apply different styles at different breakpoints.
With the addition of the new plugin system, it made sense to move the container component out of same bucket of code that holds all of our utility classes and into its own plugin with its own options.
If you are using the container in your projects, you will need to add the following section to your existing Tailwind config file:
// ...
module.exports = {
// ...
+ plugins: [
+ require('tailwindcss/plugins/container')(),
+ ],
}
You'll also need to add the new @tailwind components directive to your CSS:
@tailwind preflight;
+ @tailwind components;
@tailwind utilities;
State variant precedence changes
Impact: Small, Effort: High
Prior to 0.5.0, state variants had the following precedence (lowest to highest):
- Focus
- Hover
- Group Hover
That means that if an element had both focus:bg-blue and hover:bg-green applied, when the element was both focused and hovered, the hover styles would take precedence, so the element would be green.
It also meant that if an element had group-hover:bg-blue and hover:bg-green applied, hovering the element would make it blue because the group styles would take precedence over the individual element styles.
In 0.5.0, state variants have the following precedence (lowest to highest):
- Group Hover
- Hover
- Focus
- Active
Now hover styles will defeat group-hover styles, and focus styles will defeat hover styles.
If this sounds counter-intuitive, see #417 for more information on the motivation behind this change.
It is extremely unlikely that this change affects you; the odds that you were changing the same property on both hover and focus is extremely low, and if you were, I'm willing to bet it was on an input field where the new behavior would actually feel like an improvement.
If this change does break the expected behavior in your project, the best solution is to create your own component classes for the places where you were doing complex interaction like this so you can control the precedence manually.
New config file keys
Impact: Small, Effort: Low
New plugins key
If you'd like to use the new plugin system in an existing project, you'll need to add the plugins key to your config, and include the container component plugin if you need it:
// ...
module.exports = {
// ...
+ plugins: [
+ require('tailwindcss/plugins/container')(),
+ ],
}
This is optional, your project will build fine without this change and will just fall back to the plugins configuration from the default config file.
New backgroundSize key
If you'd like to customize the available background size utilities, add the backgroundSize key to your config
module.exports = {
// ...
+ backgroundSize: {
+ 'auto': 'auto',
+ 'cover': 'cover',
+ 'contain': 'contain',
+ },
}
This is optional, your project will build fine without this change and will just fall back to the backgroundSize configuration from the default config file.
.overflow-x/y-scroll now set overflow: scroll instead of overflow: auto
Impact: Large, Effort: Medium
The .overflow-x-scroll and .overflow-y-scroll utilities now set overflow to scroll instead of auto.
New .overflow-x-auto and .overflow-y-auto utilities have been added to get the auto behavior with more consistent naming.
This change won't break any sites but will cause scrollbars to appear on Windows in places where they might not be actually needed, so if you don't want them visible you should switch instances of .overflow-x/y-scroll to .overflow-x/y-auto.
We've also removed the -ms-overflow-style: -ms-autohiding-scrollbar styles from the overflow utilities, which means scrollbars will now render with their default styling in IE/Edge instead of being forced to render as autohiding, which is not the browsers normal behavior.
.roman renamed to .not-italic
.roman renamed to .not-italicImpact: Large, Effort: Medium
The .roman utility for undoing italic font styles has been renamed to .not-italic since .roman is a terrible name.
This was immediately reverted in v0.5.1 because it breaks compatibility with cssnext; ignore this change.
Hoping to change this in a future breaking release if/once the issue with postcss-selector-not is resolved.
- Use
global.Objectto avoid issues with polyfills when importing the Tailwind config into other JS (#402)
- Fix an issue where borders couldn't be applied to
imgtags without specifying a border style (#362, #363) - Add support for using a function to define class prefixes in addition to a simple string (#367)
- Improve the performance of
@applyby using a lookup table instead of searching (#401)
- Make default sans-serif font stack more future proof and safe to use with CSS
fontshorthand (https://github.com/tailwindcss/tailwindcss/pull/353) - Replace stylefmt with Perfectionist to avoid weird stylelint conflicts (https://github.com/tailwindcss/tailwindcss/pull/358, https://github.com/tailwindcss/tailwindcss/issues/322)
New Features
@apply'd classes can now be made !important explicitly
If you need to @apply a class and make it's declarations !important, you can now add !important to the @apply declaration itself. This will make the applied declarations !important even if they aren't marked as important in the class being applied:
// Input:
.bar {
@apply .foo !important;
}
.foo {
color: blue;
}
// Output:
.bar {
color: blue !important;
}
.foo {
color: blue;
}
Changes
@apply now strips !important from any mixed in classes
Impact: Low
Prior to 0.4, if you had a class that contained !important declarations and you @apply'd that class to another class, the declarations would preserve their !important value:
// Input:
.bar {
@apply .foo;
}
.foo {
color: blue !important;
}
// Output:
.bar {
color: blue !important;
}
.foo {
color: blue !important;
}
This turned out to be problematic if you have Tailwind configured to make utilities !important by default, and you wanted to compose components from those utilities that contained descendant selectors, for example:
// Input:
.custom-table td {
@apply .text-grey-dark;
}
// Output:
.custom-table td {
color: #8795a1 !important;
}
The problem was that rules like this would have a higher specificity than the utilities themselves due to the compound selector, so you couldn't override those styles with utilities:
<table class="custom-table">
<tr>
<td class="text-red">Will still be grey</td>
</tr>
</table>
In 0.4, @apply will always strip !important to avoid specificity issues like this:
// Input:
.bar {
@apply .foo;
}
.foo {
color: blue !important;
}
// Output:
.bar {
color: blue;
}
.foo {
color: blue !important;
}
Odds of this affecting your existing codebase is quite low; if anything this will let you clean up code you might have had to write to work around this annoying behavior.
Default color palette tweaks
Impact: Low
Some of the values in the default color palette have been tweaked with the aim of making it more useful in more situations.
-
The dark end of the grey scale has been spread out more, making
greycloser togrey-lightthan it was previously. See the PR. -
The darker/darkest variants of most colors have been desaturated slightly so they work better as background colors. See the PR.
These changes will only affect you if you are dynamically referencing the default color palette in your own config file. If you'd like to keep using the old colors, they can be found here:
New Features
Enable/disable modules and control which variants are generated for each
The Tailwind config file now contains a new modules key where you can control which modules should be responsive, or have hover or focus variants generated:
// ...
module.exports = {
// ...
modules: {
// Generate base appearance utilities + responsive versions
appearance: ['responsive'],
// Generate base, responsive, hover, and focus versions
backgroundAttachment: ['responsive', 'hover', 'focus'],
// Only generate base utilities
backgroundPosition: [],
// ...
},
// ...
}
If you don't need a certain module at all, you can disable it by setting it to false:
// ...
module.exports = {
// ...
modules: {
// ...
flexbox: false,
// ...
},
// ...
}
This gives you better control over the generated file size and also lets you add hover/focus variants to utilities that don't have them by default, like shadows for example.
If you're a PurgeCSS user who doesn't care about the pre-PurgeCSS file size, you can even set modules to all to generate every variant for every utility :feelsgood:
// ...
module.exports = {
// ...
modules: 'all',
// ...
}
Learn more about in the configuration modules documentation.
Focus variants
As alluded to earlier, Tailwind now lets you generate focus: variants of each utility that are only active on focus.
Focus variants are currently not enabled on any modules by default, but you can enable them for a specific module in your own project by adding 'focus' to the variants list in the modules section of your config file:
// ...
module.exports = {
// ...
modules: {
// ...
backgroundColors: ['responsive', 'hover', 'focus'],
// ...
},
// ...
}
Focus variants work just like the hover variants that you're used to:
<input class="bg-grey-light focus:bg-white border border-grey">
Group hover variants
Sometimes you need to change the style of an element when some parent element is hovered rather than the element itself.
To handle these situations, Tailwind 0.3 adds a new group-hover variant.
Group hover variants are currently not enabled on any modules by default, but you can enable them for a specific module in your own project by adding 'group-hover' to the variants list in the modules section of your config file:
// ...
module.exports = {
// ...
modules: {
// ...
textColors: ['responsive', 'hover', 'group-hover'],
// ...
},
// ...
}
To use a group-hover: utility variant, you need to mark the target parent element with the .group class:
<div class="group ...">
<svg class="text-grey-light group-hover:text-grey-dark"><!-- ... --></svg>
<a class="text-blue group-hover:underline" href="#">Click me</a>
</div>
Check out this CodePen to see it in action.
New @variants at-rule
To make it easy to generate hover, focus, and group-hover versions of your own utilities, Tailwind 0.3 adds a new @variants at-rule that lets you specify which variants to generate for a given list of classes:
@variants hover, focus {
.banana { color: yellow; }
.chocolate { color: brown; }
}
This will generate the following CSS:
.banana { color: yellow; }
.chocolate { color: brown; }
.focus\:banana:focus { color: yellow; }
.focus\:chocolate:focus { color: brown; }
.hover\:banana:hover { color: yellow; }
.hover\:chocolate:hover { color: brown; }
The @variants at-rule supports all of the values that are supported in the modules section of your config file:
responsivehoverfocusgroup-hover
Note: In previous versions, Tailwind included undocumented @hoverable and @focusable directives. These were fundamentally flawed in how they worked, and have been removed in favor of the new @variants directive.
The @responsive directive however has not been removed, and we fully intend to continue to support it as a shortcut for @variants responsive {}.
Customize the separator character
By default, Tailwind uses a colon (:) as a separator between variants and utility names:
<div class="hover:bg-blue">...</div>
Some templating languages (like Pug) don't play nicely with this, so Tailwind 0.3 adds a new configuration option that lets you change this if needed:
// ...
module.exports = {
// ...
options: {
// ...
separator: '_',
},
}
Missing config keys now fallback to their default values
Prior to Tailwind 0.3, excluding a key (like backgroundColors) from your config file was undefined behavior.
To make upgrades smooth as new options are added to the config file, missing keys now fallback to their default values.
This has the added benefit of allowing you to completely omit keys from your config file if you don't intend to change the default values.
The exact behavior is as follows:
- Top level keys fallback to their default values only if missing. The contents of top level keys are not merged, except for the two cases noted below.
- The
moduleskey is merged with the default modules key. This means that if you exclude a module from your config, it will be generated using the default settings. It will not be disabled unless you include the key and set it tofalse. - The
optionskey is merged with the default options key. This means if you only want to change one option, you only need to provide that one key.
New utilities
.pin-nonehas been added to undo existing.pin-{side}utilities at different breakpoints.resize-bothhas been added to allow resizing an element both horizontally and vertically- A completely new background attachment module has been added
- A completely new background repeat module has been added
- Completely new SVG fill and SVG stroke modules have been added
Upgrade Guide / Breaking Changes
Lists now have no margins by default
Impact: Medium
Until 0.3, Tailwind's Preflight base styles left ul and ol elements generally untouched, relying on the list-reset utility to remove default browser styling if you wanted to use a list for navigation or similar.
In 0.3, Tailwind still doesn't change list-style-type or padding on lists in our base styles, but we do remove margins:
ul, ol {
margin: 0;
}
Tailwind already did this for all headings, block quotes, paragraph tags, etc., so removing margins on lists feels much more consistent.
It's unlikely this will impact your project as you were most likely overriding the browser's default margins with existing margin utilities.
If you were relying on the browser's default list margins, simply add margin utilities to your lists to make up for the now missing default margin.
.pin no longer sets width and height to 100%
Impact: Low
In an effort to make .pin{-side?} utilities easier to undo at different breakpoints, the all-sides .pin utility no longer sets width and height to 100%.
This will only affect you if you were using .pin on iframe, textarea, input, or button elements, and is easily remedied by adding the w-full and h-full utilities to those elements.
SVG fill no longer defaults to currentColor
Prior to 0.3, Tailwind's Preflight styles set all SVG fills to currentColor:
svg {
fill: currentColor;
}
This made it harder to use icon sets like Feather that are drawn entirely with strokes with Tailwind, because they'd now be filled with the current text color by default instead of having no fill.
Tailwind 0.3 removes this base style entirely, and adds the fill-current class to make up for it, allowing you to be explicit when you want an SVG element to be filled with the current text color.
There's two ways you can update your project for this change:
- Simply re-add the base styles above to your own CSS.
- Add the
fill-currentclass to any SVG elements that should be filled with the current text color.
- Fix issue with dist files not being published due to bug in latest npm
- Fix overly specific border-radius reset for Chrome 62 button styles: https://github.com/tailwindcss/tailwindcss/pull/216
- New Features
- Upgrade Guide / Breaking Changes
autois no longer a hard-coded margin value- The
defaultConfigfunction is now a separate module - Rounded utilities now combine position and radius size
- Border width utilities no longer affect border color/style
@applyis now very strict about what classes can be applied- Add
optionskey to your config - Spacing, radius, and border width utility declaration order changes
New Features
Add a custom prefix to all utilities
One of the most common questions we've received since releasing v0.1.0 is "can I use Tailwind with {my existing CSS|another CSS framework}?"
While there was nothing stopping you from layering Tailwind on top of existing CSS, Tailwind has a lot of class names in common with other frameworks (.container, .mb-2, etc.) so you could run into problematic naming collisions if you weren't careful.
To fix this, you can now specify a custom prefix for all of the classes Tailwind generates under the new options key in your Tailwind config file:
{
// ...
options: {
prefix: 'tw-',
// ...
},
}
Now all of Tailwind's utilities will include that prefix:
<!-- This... -->
<div class="bg-white hover:bg-blue md:bg-red"></div>
<!-- ... becomes this: -->
<div class="tw-bg-white hover:tw-bg-blue md:tw-bg-red"></div>
To learn more, read the full documentation.
Optionally make all utilities !important
Another common obstacle when trying to use Tailwind with existing CSS is dealing with specificity.
By default, Tailwind utilities are not marked as !important, which means that if your existing CSS has high specificity selectors, trying to override what those selectors are doing with a Tailwind utility just won't work.
To fix this, we've added another option to the options section of the Tailwind config file:
{
// ...
options: {
// ...
important: true,
// ...
},
}
If you set important to true, all of Tailwind's declarations will get marked as !important, so they can easily be used to override existing CSS.
To learn more, read the full documentation.
Round element corners independently
Up until now, you could only apply a border radius to pairs of corners, like the top two corners, left two corners, etc.
Now you can round corners independently too:
<!-- Round the top left corner: -->
<div class="rounded-tl"></div>
<!-- Round the top right corner: -->
<div class="rounded-tr"></div>
<!-- Round the bottom right corner: -->
<div class="rounded-br"></div>
<!-- Round the bottom left corner: -->
<div class="rounded-bl"></div>
See more examples in the border radius documentation.
Cascading border colors and styles
In v0.1.x, our border width utilities used the border shorthand property, which meant that setting a border width also set a style and color:
.border-2 {
border: 2px solid config('colors.grey-lighter');
}
This meant that if you wanted to change the border style or color of an element and then change the border width at a larger breakpoint, you'd have to re-specify the style/color:
<div class="border-2 border-red border-dashed md:border-4 md:border-red md:border-dashed"></div>
Now our border width utilities only specify the width, so any color or style modifications will properly cascade to larger breakpoints without having to be re-specified:
<div class="border-2 border-red border-dashed md:border-4"></div>
This is technically a breaking change, so check out the relevant section in the upgrade guide to understand how this might affect your site.
Upgrade Guide / Breaking Changes
auto is no longer a hard-coded margin value
Impact: Low
Instead of hard-coding mx-auto, ml-auto, etc. into Tailwind itself, we've moved those values into the customizable margin scale in the config file.
So if you're using a custom config file, add auto to your margin scale:
{
// ...
margin: {
+ 'auto': 'auto',
'px': '1px',
'0': '0',
'1': '0.25rem',
'2': '0.5rem',
'3': '0.75rem',
'4': '1rem',
'6': '1.5rem',
'8': '2rem',
},
}
The defaultConfig function is now a separate module
Impact: Low
In the generated Tailwind config file, we include a line of code showing you how to reference Tailwind's default config values in case you'd like to reference them in your own config file.
For technical reasons, the way this works has changed:
// The old way:
var defaultConfig = require('tailwindcss').defaultConfig()
// The new way:
var defaultConfig = require('tailwindcss/defaultConfig')()
The good news is that this change makes it possible for you to import your custom config file into your front-end JavaScript if you'd like; making it easy to re-use the same color palette with libraries like D3.js or Chart.js for example.
Rounded utilities now combine position and radius size
Impact: High
Previously, border radius position and radius size were specified with two utilities. Now, size and position are combined into the same utility:
<!-- The old way: -->
<div class="rounded-lg rounded-t"></div>
<!-- The new way: -->
<div class="rounded-t-lg"></div>
We made this change because it makes working with border radius generally more predictable and much more flexible.
For example, previously, if you wanted to round 3 corners of an element, you could try this, but it wouldn't work:
<!-- Doesn't work: -->
<div class="rounded-lg rounded-t rounded-l"></div>
Instead, you'd see that only the left side was rounded. This is because the previous implementation of rounded-l worked by unrounding the right-side corners.
Now you can round 3 corners of an element two ways:
<!-- Option 1: Round two sides -->
<div class="rounded-t-lg rounded-l-lg"></div>
<!-- Option 3: Round the corners separately -->
<div class="rounded-tl-lg rounded-tr-lg rounded-bl-lg"></div>
Upgrade steps
-
If you have a custom config file, make sure your
0value border radius utility appears first in your border radius scale:{ // ... borderRadius: { + 'none': '0', 'sm': '.125rem', default: '.25rem', 'lg': '.5rem', 'full': '9999px', - 'none': '0', }, }This is important if you ever need to reset the border radius of a side at a breakpoint and add a border radius to another side that shares a corner.
-
Look for any time you round one side of an element in your codebase and collapse the separate position and size utilities into the new corresponding compound utility:
<!-- Change this: --> <div class="rounded-lg rounded-t"></div> <!-- To this: --> <div class="rounded-t-lg"></div> <!-- Change this: --> <div class="rounded rounded-l"></div> <!-- To this: --> <div class="rounded-l"></div> -
If you were changing which side of an element was rounded responsively, now you'll need to explicitly unround one side when you round the other:
<!-- Change this: --> <div class="rounded-lg rounded-t lg:rounded-lg lg:rounded-l"></div> <!-- To this: --> <div class="rounded-t-lg lg:rounded-t-none lg:rounded-l-lg"></div>
Border width utilities no longer affect border color/style
Impact: Medium
Previously, applying a border width utility like .border-2 would not only set the border width; it would also override the border color and border style.
This is no longer the case, so if you were ever depending on that behavior (for example when overriding things responsively), you'll need to update your code to explicitly change the color and style:
<!-- Change this: -->
<div class="border border-dashed border-red md:border-2"></div>
<!-- To this: -->
<div class="border border-dashed border-red md:border-2 md:border-solid md:border-grey-lighter"></div>
It's very unlikely that you were depending on this behavior so chances are you won't need to make this sort of change.
Instead, you'll probably notice this change from the opposite side, where you had to define your border color twice if you changed the size responsively.
Now you only need to define the color or style once, so although you don't have to remove the double definitions, they are now redundant and safe to remove:
<!-- Change this: -->
<div class="border border-dashed border-red md:border-2 md:border-dashed md:border-red"></div>
<!-- To this: -->
<div class="border border-dashed border-red md:border-2"></div>
@apply is now very strict about what classes can be applied
Impact: Low
Previously, @apply would only fail if it couldn't find a matching class to mixin. This led to unexpected behavior for a lot of people when trying to @apply complex classes.
So now instead of silently applying a class in a way that results in unexpected behavior, @apply behaves much more strictly and will throw an explicit error if trying to @apply something other than simple, un-nested, single definition classes.
Here are the rules @apply now enforces:
-
You cannot
@applya class that is part of any ruleset which is nested within an at-rule.This means you can't
@applyclasses that are nested within media queries:@media (min-width: 300px) { .a { color: blue; } } .b { /* This will throw an error */ @apply .a; }This never worked before anyways, but now you'll get an error instead of wondering why your class didn't inherit the responsive behavior of the class you tried to apply.
-
You cannot
@applya class that contains a pseudo-selector..a:hover { color: red; } .b { /* This will throw an error */ @apply .a; }This never worked before either, but now the error message you get will be more helpful.
-
You cannot
@applya class that is included in multiple rulesets..a { color: red; } .b { /* This will throw an error */ @apply .a; } .a { color: blue; }This is what caused the confusion in #112. While supporting this wouldn't have negative consequences 95% of the time, it can be really confusing when it does cause problems.
@applyis meant for single stand-alone rulesets, so we don't see a reason to support this. If a class appears in multiple rulesets, it's a sign that something complex is happening, and@applyis not intended to be used to inherit complex behavior.
If your build fails because of @apply in v0.2.0 but built successfully in v0.1.0, it's very likely something on your site wasn't actually working the way you expect.
Add options key to your config
Impact: Low
If you'd like to use the new prefix or important options, you'll want to add the options key to the bottom of your config file.
Here's what it looks like with the default values:
{
// ...
options: {
prefix: '',
important: false,
},
}
This key is optional, so nothing will break if you don't add it.
Spacing, radius, and border width utility declaration order changes
Impact: Low
Previously, these utilities were declared purely based on the order in your scale, and with more specific declarations declared first.
For example, padding looked something like this:
.pt-0 { /* ... */ }
.pr-0 { /* ... */ }
.pb-0 { /* ... */ }
.pl-0 { /* ... */ }
.px-0 { /* ... */ }
.py-0 { /* ... */ }
.p-0 { /* ... */ }
.pt-1 { /* ... */ }
.pr-1 { /* ... */ }
.pb-1 { /* ... */ }
.pl-1 { /* ... */ }
.px-1 { /* ... */ }
.py-1 { /* ... */ }
.p-1 { /* ... */ }
.pt-2 { /* ... */ }
.pr-2 { /* ... */ }
.pb-2 { /* ... */ }
.pl-2 { /* ... */ }
.px-2 { /* ... */ }
.py-2 { /* ... */ }
.p-2 { /* ... */ }
This meant that more general utilities like p-2 would override side-specific utilities like pl-1 if the scale value in the general utility was higher:
<!-- This markup: -->
<div id="padded" class="p-4 px-2 pl-1"></div>
<!-- ...is equivalent to this CSS: -->
<style>
#padded {
padding-top: config('padding.4');
padding-bottom: config('padding.4');
padding-right: config('padding.4');
padding-left: config('padding.4');
}
</style>
Now, spacing, radius, and border width utilities are declared from most general to most specific, sorted by position first, then by the scale:
.p-0 { /* ... */ }
.p-1 { /* ... */ }
.p-2 { /* ... */ }
.py-0 { /* ... */ }
.px-0 { /* ... */ }
.py-1 { /* ... */ }
.px-1 { /* ... */ }
.py-2 { /* ... */ }
.px-2 { /* ... */ }
.pt-0 { /* ... */ }
.pr-0 { /* ... */ }
.pb-0 { /* ... */ }
.pl-0 { /* ... */ }
.pt-1 { /* ... */ }
.pr-1 { /* ... */ }
.pb-1 { /* ... */ }
.pl-1 { /* ... */ }
.pt-2 { /* ... */ }
.pr-2 { /* ... */ }
.pb-2 { /* ... */ }
.pl-2 { /* ... */ }
This means that setting a left padding will override an x padding which will override an "all sides" padding:
<!-- This markup: -->
<div id="padded" class="p-4 px-2 pl-1"></div>
<!-- ...is equivalent to this CSS: -->
<style>
#padded {
padding-top: config('padding.4');
padding-bottom: config('padding.4');
padding-right: config('padding.2');
padding-left: config('padding.1');
}
</style>
It's very unlikely that this change will break your layout; it's more likely that you were working around this annoying behavior:
<!-- What you've probably written: -->
<div class="pt-4 pr-4 pb-4 pl-2"></div>
<!-- What you can write now: -->
<div class="p-4 pl-2"></div>
- Fix CDN files not being published to npm
- If using Webpack, it will now watch your config file changes
- Autoprefix
distassets for quick hacking and prototyping - Move list utilities earlier in stylesheet to allow overriding with spacing utilities (bug fix)
- Add
my-auto,mt-auto, andmb-automargin utilities - Add
sans-serifto end of defaultsansfont stack - When running
tailwind init [filename], automatically append.jsto filename if not present - Support default fallback value in
config(...)function, ie.config('colors.blue', #0000ff) - Don't output empty media queries if Tailwind processes a file that doesn't use Tailwind
- Add new
.scrolling-touchand.scrolling-autoutilities for controlling inertial scroll behavior on WebKit touch devices - Generate separate dist files for preflight, utilities, and tailwind for CDN usage
- Fix issue with config option not being respected in
tailwind build - Target Node 6.9.0 explicitly (instead of 8.6 implicitly) to support more users
- Fix
tailwind buildCLI command not writing output files