Tailwind CSS v4 browser support requirements
Tailwind CSS v4.0 is designed for and tested on Chrome 111 (released March 2023), Safari 16.4 (released March 2023), and Firefox 128 (released July 2024). These are the minimum browser versions the core functionality depends on.
Modern CSS features with limited browser support in Tailwind v4
Tailwind v4 includes support for bleeding-edge platform features like field-sizing: content, @starting-style, and text-wrap: balance that have limited browser support. Users can choose not to use these utilities and variants if their target browsers don't support them.
Tailwind CSS v4 is not compatible with CSS preprocessors
Tailwind CSS v4.0 is a full-featured CSS build tool and is not designed to be used with CSS preprocessors like Sass, Less, or Stylus. Tailwind itself acts as the preprocessor, handling features like nesting, variables, bundling imports, and adding vendor prefixes.
Native CSS variables supported in Tailwind v4
Tailwind v4 relies on native CSS variables (custom properties) heavily internally. All modern browsers support native CSS variables without any preprocessor, so users can use CSS variables directly in Tailwind projects.
CSS modules compatibility with Tailwind v4
Tailwind is compatible with CSS modules and can co-exist with them, but using CSS modules and Tailwind together is not recommended if it can be avoided. CSS modules are designed to solve scoping problems that don't exist when composing utility classes in HTML with Tailwind.
CSS modules build performance impact with Tailwind v4
When using CSS modules with Tailwind, build tools like Vite, Parcel, and Turbopack process each CSS module separately, causing Tailwind to run separately for each module. This results in much slower build times and worse developer experience compared to processing CSS once.
CSS variables alternative to @apply in modules
Instead of using @apply in CSS modules, you can use CSS variables like background: var(--color-blue-500);. This approach allows Tailwind to skip processing those files entirely and improves build performance.
Vue, Svelte, and Astro style blocks have CSS modules drawbacks
Vue, Svelte, and Astro support <style> blocks in component files that behave like CSS modules, each processed separately with the same performance drawbacks. When using Tailwind with these tools, avoid <style> blocks in components and style with utility classes directly in markup instead.
Using @apply in Vue/Svelte/Astro component style blocks
If using <style> blocks in Vue, Svelte, or Astro components with Tailwind, import your global styles as reference with @reference "../app.css"; to ensure theme variables are defined and @apply works as expected.
CSS variables in Vue/Svelte/Astro component styles
Instead of using @apply in component <style> blocks, use globally defined CSS variables like background-color: var(--color-blue-500);. This approach doesn't require Tailwind to process the component CSS at all.
Tailwind CSS uses custom CSS syntax @theme @variant @source
Tailwind CSS uses custom CSS syntax like @theme, @variant, and @source. In some editors, these custom at-rules may trigger warnings or errors because they are not recognized as standard CSS.
VS Code Tailwind CSS IntelliSense supports custom at-rules
The official Tailwind CSS IntelliSense extension for VS Code includes a dedicated Tailwind CSS language mode that provides support for all custom at-rules and functions that Tailwind uses, eliminating syntax warnings and errors.
May need to disable CSS linting for Tailwind custom syntax
In some cases, you may need to disable native CSS linting and validations if your editor is very strict about the syntax it expects in CSS files, as Tailwind uses custom at-rules that standard CSS validators may not recognize.
@config directive for legacy JavaScript configuration
Use the @config directive to load a legacy JavaScript-based configuration file. Example: @config "../../tailwind.config.js"; The corePlugins, safelist, and separator options from JavaScript-based config are not supported in v4.0. To safelist utilities in v4 use @source inline().
@plugin directive for legacy JavaScript plugins
Use the @plugin directive to load a legacy JavaScript-based plugin. Example: @plugin "@tailwindcss/typography"; The @plugin directive accepts either a package name or a local path.
theme() function is deprecated in v4
The theme() function is deprecated in Tailwind v4 for accessing theme values using dot notation. The recommended approach is to use CSS theme variables instead.
@config and @plugin can coexist with CSS-driven features
The @config and @plugin directives may be used in conjunction with @theme, @utility, and other CSS-driven features. This allows incremental migration of theme, custom configuration, utilities, variants, and presets to CSS. Things defined in CSS will be merged where possible and take precedence over those defined in configs, presets, and plugins.
Upgrade tool command
The npx @tailwindcss/upgrade command automates most of the migration from v3 to v4, including updating dependencies, migrating configuration to CSS, and handling template file changes. The upgrade tool requires Node.js 20 or higher. It is recommended to run the tool in a new branch and carefully review the diff and test the project in the browser before merging.
Browser support requirements
Tailwind CSS v4.0 requires Safari 16.4 or higher, Chrome 111 or higher, and Firefox 128 or higher. It depends on modern CSS features like @property and color-mix(). If you need to support older browsers, stick with v3.4.
PostCSS plugin migration to @tailwindcss/postcss
In v4, the tailwindcss PostCSS plugin has moved to a dedicated @tailwindcss/postcss package. You should also remove postcss-import and autoprefixer from your plugins config as v4 handles imports and vendor prefixing automatically.
Vite plugin migration to @tailwindcss/vite
For Vite projects, migrate from the PostCSS plugin to the dedicated @tailwindcss/vite plugin for improved performance. Import it as: import tailwindcss from "@tailwindcss/vite"; and add tailwindcss() to the plugins array.
Tailwind CLI moved to @tailwindcss/cli
In v4, the Tailwind CLI has moved to a dedicated @tailwindcss/cli package. Update build commands from 'npx tailwindcss' to 'npx @tailwindcss/cli'.
Removed opacity utilities
In v4, the following deprecated opacity utilities have been removed: bg-opacity-*, text-opacity-*, border-opacity-*, divide-opacity-*, ring-opacity-*, placeholder-opacity-*. Replace them with opacity modifiers on the color utilities (e.g., bg-black/50 instead of bg-opacity-50).
Renamed flex and overflow utilities
In v4: flex-shrink-* → shrink-*, flex-grow-* → grow-*, overflow-ellipsis → text-ellipsis.
Renamed decoration utilities
In v4: decoration-slice → box-decoration-slice, decoration-clone → box-decoration-clone.
Drop-shadow scale renamed
In v4, drop-shadow utilities have been renamed: drop-shadow-sm → drop-shadow-xs, drop-shadow → drop-shadow-sm.
Blur scale renamed
In v4, blur utilities have been renamed: blur-sm → blur-xs, blur → blur-sm.
outline-none renamed to outline-hidden
In v4, outline-none has been renamed to outline-hidden. The new outline-none utility actually sets outline-style: none, whereas the old outline-none set an invisible outline for accessibility in forced colors mode.
Ring utility renamed
In v4, the bare ring utility has been renamed to ring-3. The ring utility now sets outline-width: 1px by default (instead of 3px) to be more consistent with border and ring utilities.
Outline utility defaults to 1px
In v4, the outline utility now sets outline-width: 1px by default. All outline-<number> utilities default outline-style to solid, so you no longer need to combine them with a separate outline utility.
Space-between selector changed
In v4, the space-x-* and space-y-* utilities changed from using '.space-y-4 > :not([hidden]) ~ :not([hidden])' to '.space-y-4 > :not(:last-child)' to improve performance on large pages. This may cause visual changes if you used these utilities with inline elements or added custom margins to child elements. Migration recommendation is to use flex/grid with gap instead.
Divide selector changed
In v4, the divide-x-* and divide-y-* utilities changed from using '.divide-y-4 > :not([hidden]) ~ :not([hidden])' to '.divide-y-4 > :not(:last-child)' to improve performance. This may affect projects using these utilities with inline elements or custom margins/padding on children.
Gradient variant behavior changed
In v4, overriding part of a gradient with a variant now preserves the entire gradient instead of resetting it. For example, dark:from-blue-500 on a gradient will preserve the to-* color in dark mode. Use via-none explicitly if you need to unset a three-stop gradient back to two-stop in a specific state.
Container utility configuration removed
In v4, the container utility no longer supports configuration options like center and padding. To customize the container utility, use the @utility directive instead.
Default ring color changed to currentColor
In v4, the ring utility default color changed from blue-500 to currentColor. The ring width also changed from 3px to 1px. Replace bare ring usage with ring-3 and add ring-blue-500 where the blue color was depended upon. Optionally, set --default-ring-color: var(--color-blue-500) and --default-ring-width: 3px in @theme to preserve v3 behavior (not idiomatic).
Placeholder color changed
In v4, placeholder text now uses the current text color at 50% opacity instead of gray-400. To preserve v3 behavior, add base styles that set input::placeholder and textarea::placeholder color to var(--color-gray-400).
Button cursor changed to default
In v4, buttons now use cursor: default instead of cursor: pointer by default. To preserve v3 behavior, add base styles that set cursor: pointer on button:not(:disabled) and [role="button"]:not(:disabled).
Dialog margins removed
In v4, Preflight resets margins on <dialog> elements. If you want dialogs to be centered by default, add base styles with dialog { margin: auto; }.
Hidden attribute priority
In v4, the hidden attribute takes priority over display utilities like block or flex. Remove the hidden attribute to make an element visible. Note: this does not apply to hidden="until-found".
Important modifier moved to end
In v4, the ! important modifier should be placed at the very end of the class name instead of at the beginning. Old syntax (flex! bg-red-500!) is deprecated but still supported. New syntax: flex! bg-red-500! hover:bg-red-600/50!.
Variant stacking order changed left-to-right
In v4, stacked variants apply left to right instead of right to left. For example, change first:*:pt-0 last:*:pb-0 to *:first:pt-0 *:last:pb-0. This only affects order-sensitive stacked variants.
Hover variant requires hover-capable device
In v4, the hover variant only applies when the primary input device supports hover, using @media (hover: hover). This can be problematic for touch devices that relied on triggering hover on tap. Override with @custom-variant hover (&:hover) if needed, but best practice is to treat hover as an enhancement.
Transition now includes outline-color
In v4, the transition and transition-colors utilities now include the outline-color property. If you add an outline with a custom color on focus, it will transition from the default color. To avoid this, set the outline color unconditionally or explicitly for both states.
Transform properties now individual
In v4, rotate-*, scale-*, and translate-* utilities are based on individual CSS properties (rotate, scale, translate) instead of the transform shorthand. You can no longer use transform-none to reset these; you must reset the individual properties instead (e.g., scale-none).
Custom transitions with transform property
In v4, if you customize transitioned properties and include 'transform', those utilities will no longer transition. Include the individual properties instead (e.g., transition-[opacity,scale] instead of transition-[opacity,transform]).
corePlugins option removed
In v4, the corePlugins option to disable certain utilities is no longer supported.
resolveConfig function removed
In v4, the resolveConfig function has been removed. Use the CSS variables generated by Tailwind directly in JavaScript instead. For example, use getComputedStyle(document.documentElement).getPropertyValue("--shadow-xl") to access a theme variable value.
Sass, Less, and Stylus not supported
In v4, Tailwind CSS is not designed to be used with CSS preprocessors like Sass, Less, or Stylus. Think of Tailwind as your preprocessor instead. You cannot use these languages for your stylesheets or <style> blocks in Vue, Svelte, Astro, etc.
overscroll-behavior Safari support
The overscroll-behavior utilities added in Tailwind v1.6 are not supported in Safari browsers.
v3.1 First-party TypeScript types for config
Tailwind CSS v3.1 introduced first-party TypeScript types for the tailwind.config.js file. To use them, add a JSDoc type annotation at the top of the config file: /** @type {import('tailwindcss').Config} */ before the module.exports statement.
Play CDN in v3.0
Tailwind CSS v3.0 introduced a Play CDN script tag (https://cdn.tailwindcss.com/) that can be added to any HTML document to use every Tailwind feature directly in the browser via JavaScript. This is intended for development and prototyping purposes only.
Browser compatibility improvements in v4.1
Tailwind CSS v4.1 includes framework-specific fallbacks for older browsers. Colors defined in oklab now render in older Safari versions. Features using @property custom properties now work in older Safari and Firefox. Colors using opacity modifiers include inlined fallbacks. Gradients with explicit interpolation methods fall back to browser defaults. Tailwind v4 is designed for modern browsers like Safari 16.4+, but v4.1 improves degradation in older browsers.