How to Migrate from Sass/LESS to Tailwind CSS
How do I migrate from Sass/LESS to Tailwind CSS?
TL;DR
- Bottom line: Migrate incrementally — replace Sass/LESS variables with Tailwind's
@themeCSS custom properties, convert mixins to utility classes or@applyrules, replace nesting with CSS-native nesting, then remove the preprocessor once no references remain. - Key tool/command:
npx @tailwindcss/upgrade(automates ~90% of Tailwind v3-to-v4 migration including class renames, config-to-CSS conversion, and template updates; Sass files require manual conversion) - Watch out for: Tailwind CSS v4 is not compatible with Sass/LESS — you cannot use
@import "tailwindcss"inside.scssor.lessfiles. The Oxide engine (Lightning CSS) cannot parse preprocessor syntax. Preprocessor code must be converted to plain CSS first. [src4] - Works with: Tailwind CSS v4.1+, Node.js 20+, any framework (React, Vue, Angular, Svelte, plain HTML). Sass 1.x, LESS 4.x as starting points.
Constraints
- Tailwind CSS v4 is a complete CSS build tool that replaces preprocessors — think of Tailwind itself as your preprocessor. Sass, LESS, and Stylus cannot be used alongside it in the same file. [src4]
- The
@tailwindcss/upgradetool only processes.cssfiles. It will skip or error on.scss/.lessfiles. You must manually convert preprocessor code to plain CSS before or after running the tool. [src1, src5] - Tailwind v4 requires Chrome 111+, Safari 16.4+, Firefox 128+. If your project must support older browsers, stay on Tailwind v3.4 (the last version supporting Sass coexistence). [src4]
- Never let Tailwind's
@import "tailwindcss"appear in a.scssfile — Lightning CSS will crash with parse errors on Sass syntax. Keep Tailwind directives in.cssfiles only. [src6] - CSS
color-mix()(the replacement for Sassdarken()/lighten()) requires Safari 16.4+, Chrome 111+, Firefox 113+. For wider browser support, pre-define all color shades in@theme. [src3] - Node.js 20+ is required for the Tailwind v4 CLI and upgrade tool. [src1]
Quick Reference
| Sass/LESS Pattern | Tailwind Equivalent | Example |
|---|---|---|
$primary: #3B82F6; / @primary: #3B82F6; | @theme { --color-primary: #3B82F6; } | class="text-primary bg-primary/10" |
@mixin button($bg) { ... } | Utility classes or @apply | class="px-4 py-2 rounded bg-blue-500" |
@include respond-to('md') { ... } | Responsive prefix | class="p-4 md:p-8 lg:p-12" |
darken($color, 10%) / lighten() | Opacity modifier or color-mix() | class="bg-blue-500/90" or color-mix(in oklch, ...) |
&:hover { color: red; } | State variant prefix | class="hover:text-red-500" |
@extend .btn-base; | Component extraction with @apply | .btn { @apply px-4 py-2 rounded; } |
.card { .title { ... } } nesting | CSS-native nesting or flat utilities | .card { & .title { @apply text-lg font-bold; } } |
@for $i from 1 through 12 { ... } | Grid/spacing scale utilities | class="grid-cols-1 md:grid-cols-6 lg:grid-cols-12" |
@import 'variables'; @import 'mixins'; | @import "tailwindcss"; | Single import replaces all partials |
map-get($colors, 'primary') | CSS variable reference | var(--color-primary) or theme(colors.primary) |
@each $name, $color in $colors { ... } | @theme block generates all utilities | @theme { --color-brand: #38bdf8; } auto-generates utilities |
$spacing-unit: 8px; padding: $spacing-unit * 2; | Spacing scale | class="p-4" (= 1rem = 16px) |
@media (min-width: $breakpoint-md) { ... } | Responsive prefix | class="md:flex md:gap-4" |
%placeholder { ... } silent extends | @utility directive (v4) | @utility glass { backdrop-filter: blur(12px); } |
!default variable flags | @theme with CSS custom property fallbacks | --color-accent: var(--color-brand, #3B82F6); |
Decision Tree
START
├── Is the project currently on Tailwind v3 with Sass alongside?
│ ├── YES → First upgrade to Tailwind v4 (run npx @tailwindcss/upgrade), then remove Sass
│ └── NO ↓
├── Is the project pure Sass/LESS with no Tailwind at all?
│ ├── YES → Install Tailwind v4, run both systems in parallel, migrate file-by-file
│ └── NO ↓
├── Does the Sass/LESS codebase use complex mixins with parameters?
│ ├── YES → Extract to component classes with @apply, or convert to CSS custom properties + calc()
│ └── NO ↓
├── Does the project use Sass maps or LESS maps for design tokens?
│ ├── YES → Convert to @theme block with CSS custom properties (auto-generates utility classes)
│ └── NO ↓
├── Are there many @extend / placeholder selectors?
│ ├── YES → Replace with @apply or direct utility classes in markup
│ └── NO ↓
├── Does the project use Sass color functions (darken, lighten, mix)?
│ ├── YES → Replace with Tailwind opacity modifiers, color-mix(), or pre-defined shades in @theme
│ └── NO ↓
└── DEFAULT → Replace Sass/LESS features one-by-one: variables → @theme, nesting → CSS nesting,
imports → @import "tailwindcss", then delete .scss/.less files
Step-by-Step Guide
1. Audit the Sass/LESS surface area
Quantify what needs migrating: count variables, mixins, extends, nested rules, and custom functions. This tells you migration complexity and timeline. [src5]
# For Sass/SCSS projects
find . -name '*.scss' -o -name '*.sass' | xargs wc -l | tail -1
grep -rn '\$' --include='*.scss' | grep -v node_modules | wc -l # variables
grep -rn '@mixin' --include='*.scss' | wc -l # mixins
grep -rn '@include' --include='*.scss' | wc -l # mixin usages
grep -rn '@extend' --include='*.scss' | wc -l # extends
Verify: Small project: <500 lines, <20 variables. Medium: 500–5000 lines. Large: >5000 lines. Estimate 1–2 hours per 500 lines.
2. Install Tailwind CSS v4 alongside the existing preprocessor
Run both systems in parallel during migration. Tailwind processes .css files; Sass processes .scss files. They do not conflict if kept in separate files. [src1]
# Install Tailwind v4 (requires Node.js 20+)
npm install tailwindcss @tailwindcss/postcss
# For Vite projects (recommended — fastest builds)
npm install @tailwindcss/vite
# For CLI-only usage
npm install @tailwindcss/cli
Create your Tailwind entry point as a .css file (NOT .scss):
/* src/tailwind.css */
@import "tailwindcss";
Verify: npx @tailwindcss/cli -i src/tailwind.css -o dist/output.css compiles without errors.
3. Convert Sass/LESS variables to Tailwind @theme
Move design tokens from $variables or @variables to Tailwind's @theme block. Each CSS custom property automatically generates utility classes. Variables defined outside @theme (e.g., in :root) do NOT generate utilities. [src3, src7]
/* BEFORE: _variables.scss */
/* $primary: #3B82F6; $secondary: #10B981; $font-sans: 'Inter', sans-serif; */
/* AFTER: tailwind.css */
@import "tailwindcss";
@theme {
--color-primary: #3B82F6;
--color-secondary: #10B981;
--font-sans: 'Inter', sans-serif;
}
Verify: class="text-primary bg-secondary" renders correct colors in the browser.
4. Replace mixins with utility classes or @apply rules
Sass mixins that output simple property groups become utility classes in HTML. Complex mixins with parameters become custom CSS with @apply or CSS custom properties. In v4, use the @utility directive instead of @layer utilities. [src2, src6]
// BEFORE: Sass mixin
@mixin card-style($padding: 16px, $radius: 8px) {
padding: $padding;
border-radius: $radius;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
background: white;
}
<!-- AFTER: Tailwind utility classes -->
<div class="p-4 rounded-lg shadow-sm bg-white">...</div>
For truly reusable patterns, use @utility in CSS (v4 replacement for @layer utilities):
@utility card {
@apply p-4 rounded-lg shadow-sm bg-white;
}
Verify: Visual diff shows identical rendering before and after mixin removal.
5. Convert nesting and media queries to Tailwind patterns
Replace Sass nesting with CSS-native nesting (supported in v4 via Lightning CSS) or flat utility classes. Replace @media queries with responsive prefixes. [src1]
// BEFORE: Sass nesting + media queries
.sidebar {
width: 100%;
padding: 1rem;
@media (min-width: 768px) { width: 250px; padding: 2rem; }
.nav-item { color: gray; &:hover { color: blue; } }
}
<!-- AFTER: Tailwind utility classes -->
<aside class="w-full p-4 md:w-[250px] md:p-8">
<a class="text-gray-500 hover:text-blue-500">...</a>
</aside>
Verify: Resize browser window — responsive behavior matches original breakpoints.
6. Remove @extend and @import partials
Replace Sass partials with Tailwind's single @import "tailwindcss". Replace @extend with direct utility classes or @apply. Tailwind v4 automatically bundles imported CSS files without separate preprocessing. [src1, src2, src4]
/* AFTER: Tailwind CSS with @utility */
@import "tailwindcss";
@utility btn-primary {
@apply inline-flex items-center px-4 py-2 rounded-md bg-primary text-white;
}
@utility btn-secondary {
@apply inline-flex items-center px-4 py-2 rounded-md bg-secondary text-white;
}
Verify: grep -rn '@import\|@extend' --include='*.scss' returns zero results after migration.
7. Handle Vue/Svelte/Astro component styles
In Tailwind v4, @apply inside component <style> blocks requires a @reference directive pointing to your main CSS file. Alternatively, use utility classes directly in markup (recommended). [src1, src4]
<!-- Vue/Svelte: If you must use @apply in scoped styles -->
<style scoped>
@reference "../../app.css";
.card-title { @apply text-xl font-bold text-gray-900; }
</style>
Verify: Component renders correctly with @apply styles applied.
8. Delete Sass/LESS dependencies and config
Once all .scss / .less files are converted, remove the preprocessor toolchain. [src5]
# Remove Sass
npm uninstall sass sass-loader node-sass
# Remove LESS
npm uninstall less less-loader
# Delete all .scss / .less files
find . -name '*.scss' -o -name '*.less' | grep -v node_modules | xargs rm
Verify: npm ls sass less shows no preprocessor packages. App builds and runs correctly.
Code Examples
CSS/PostCSS: Tailwind v4 configuration replacing Sass variables and mixins
/* Input: A Sass-based design system with variables, mixins, and custom breakpoints
Output: Equivalent Tailwind v4 CSS-first configuration */
@import "tailwindcss";
/* Design tokens — replaces $variables in _variables.scss */
@theme {
--color-brand-50: oklch(0.97 0.01 250);
--color-brand-500: oklch(0.55 0.2 250);
--color-brand-900: oklch(0.25 0.1 250);
--color-surface: #ffffff;
--color-surface-dark: #1a1a2e;
--font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
--breakpoint-xs: 30rem; /* 480px */
--breakpoint-3xl: 120rem; /* 1920px */
--radius-pill: 9999px;
--shadow-card: 0 1px 3px oklch(0 0 0 / 0.08), 0 1px 2px oklch(0 0 0 / 0.06);
}
/* Component classes — replaces @mixin card-style, @mixin button-base */
@utility card {
@apply rounded-lg bg-surface p-6 shadow-card;
}
@utility btn {
@apply inline-flex items-center justify-center gap-2 rounded-md px-4 py-2
font-medium transition-colors duration-150
focus:outline-2 focus:outline-offset-2 focus:outline-brand-500;
}
@utility btn-primary {
@apply btn bg-brand-500 text-white hover:bg-brand-900;
}
/* Dark mode — replaces Sass if/else theme switching */
@variant dark (&:where(.dark, .dark *));
TypeScript/React: Component refactored from Sass modules to Tailwind
// Input: React component using CSS Modules with Sass (.module.scss)
// Output: Same component using Tailwind utility classes
// BEFORE: Button.module.scss + import styles from './Button.module.scss'
// .button { @include button-base; &--primary { background: $primary; } }
// AFTER: Button.tsx with Tailwind (no separate stylesheet)
import { type ButtonHTMLAttributes } from 'react';
const variants = {
primary: 'bg-brand-500 text-white hover:bg-brand-900 focus:ring-brand-500',
secondary: 'bg-secondary text-white hover:bg-secondary/80 focus:ring-secondary',
ghost: 'bg-transparent text-brand-500 hover:bg-brand-50 focus:ring-brand-500',
} as const;
type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
variant?: keyof typeof variants;
};
export function Button({ variant = 'primary', className = '', disabled, children, ...props }: ButtonProps) {
return (
<button
className={`inline-flex items-center justify-center gap-2 rounded-md px-4 py-2
font-medium transition-colors duration-150
focus:outline-2 focus:outline-offset-2
${variants[variant]}
${disabled ? 'opacity-50 cursor-not-allowed' : ''}
${className}`}
disabled={disabled}
{...props}
>
{children}
</button>
);
}
Vue SFC: Migrating scoped Sass styles to Tailwind v4
<!-- Input: Vue component using <style lang="scss" scoped>
Output: Same component using Tailwind utilities + @reference -->
<!-- BEFORE: Vue with scoped Sass -->
<!-- <style lang="scss" scoped>
@import '@/styles/variables';
.alert { padding: $spacing-md; border-radius: $radius-md; border: 1px solid;
&--success { border-color: $success; background: lighten($success, 40%); }
&--error { border-color: $danger; background: lighten($danger, 40%); } }
</style> -->
<!-- AFTER: Vue with Tailwind v4 -->
<template>
<div :class="[
'rounded-md border p-4',
variant === 'success' && 'border-green-500 bg-green-50',
variant === 'error' && 'border-red-500 bg-red-50',
]" role="alert">
<h3 class="mb-1 font-semibold">{{ title }}</h3>
<p class="text-sm"><slot /></p>
</div>
</template>
<script setup lang="ts">
defineProps<{ variant: 'success' | 'error'; title: string }>();
</script>
<!-- If you still need custom CSS, use @reference for @apply -->
<style scoped>
@reference "../../app.css";
h3 { @apply text-lg font-bold; }
</style>
Anti-Patterns
Wrong: Using Sass inside Tailwind v4 CSS files
/* BAD — Sass syntax in a file processed by Tailwind v4 */
@import "tailwindcss";
$primary: #3B82F6; /* Sass variable — will not compile */
.btn {
background: $primary;
@include responsive-padding; /* Sass mixin — will fail */
}
Correct: Use @theme and CSS custom properties
/* GOOD — Pure CSS with Tailwind v4 @theme */
@import "tailwindcss";
@theme {
--color-primary: #3B82F6;
}
.btn {
background: var(--color-primary);
@apply px-4 py-2 md:px-6 md:py-3;
}
Wrong: Converting every Sass class to @apply
/* BAD — Re-creating Sass abstractions with @apply defeats the purpose */
.container { @apply mx-auto max-w-7xl px-4; }
.heading-1 { @apply text-4xl font-bold text-gray-900; }
.heading-2 { @apply text-3xl font-semibold text-gray-800; }
.heading-3 { @apply text-2xl font-medium text-gray-700; }
.paragraph { @apply text-base text-gray-600 leading-relaxed; }
.link { @apply text-blue-500 underline hover:text-blue-700; }
/* 200 more classes... You just rebuilt Sass with extra steps */
Correct: Use utility classes directly in markup
<!-- GOOD — Utility classes in HTML; extract only truly reusable components -->
<h1 class="text-4xl font-bold text-gray-900">Title</h1>
<p class="text-base text-gray-600 leading-relaxed">Content</p>
<!-- Only extract with @utility when repeated in 3+ places -->
Wrong: Running the Tailwind upgrade tool on .scss files
# BAD — The upgrade tool does not recognize .scss files
npx @tailwindcss/upgrade
# "Cannot find any CSS files that reference Tailwind CSS"
Correct: Create a temporary .css file, upgrade, then apply changes
# GOOD — Extract Tailwind directives to a temp .css file first
echo '@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";' > tailwind.tmp.css
npx @tailwindcss/upgrade --force
git diff tailwind.tmp.css # Review, apply to real styles
rm tailwind.tmp.css
Wrong: Keeping Sass just for nesting alongside Tailwind v4
// BAD — Running Sass just for nesting when CSS nesting is native
// sass-loader + Tailwind = two build steps, potential conflicts
.card {
.title { font-size: 1.25rem; font-weight: bold; }
.body { padding: 1rem; }
}
Correct: Use CSS-native nesting (supported in all modern browsers)
/* GOOD — CSS nesting works natively in Tailwind v4 */
.card {
& .title { @apply text-xl font-bold; }
& .body { @apply p-4; }
}
Wrong: Defining design tokens in :root instead of @theme
/* BAD — Variables in :root do not generate Tailwind utilities */
:root {
--color-brand: #3B82F6;
--color-accent: #10B981;
}
/* class="text-brand" will NOT work */
Correct: Use @theme for any token that needs utility classes
/* GOOD — @theme variables auto-generate utilities */
@theme {
--color-brand: #3B82F6;
--color-accent: #10B981;
}
/* class="text-brand bg-accent/50" now works */
Common Pitfalls
- Tailwind v4 crashes on
.scss/.lessfiles: Tailwind's Oxide engine (built on Lightning CSS) cannot parse Sass or LESS syntax. Fix: Keep Tailwind directives in.cssfiles only. Run preprocessor and Tailwind as separate build steps during migration. [src1, src6] theme()function unavailable in Sass: Since Sass compiles before PostCSS/Tailwind, Tailwind'stheme()function cannot be used inside.scssfiles. Fix: Use CSS custom properties (var(--color-primary)) instead. [src2]@applywith!importantfails in Sass: Sass misinterprets the!importantflag. Fix: Use interpolation syntax:@apply bg-red-500 #{!important};. Better yet, migrate to plain.css. [src2]- Overusing @apply creates "Sass with extra steps": Converting every Sass class to an
@applyrule negates Tailwind's benefits. Fix: Apply utilities directly in HTML markup. Reserve@apply/@utilityfor patterns repeated in 3+ places. [src1] - Sass color functions have no direct Tailwind equivalent:
darken(),lighten(),mix()are compile-time Sass functions. Fix: Use Tailwind opacity modifiers (bg-blue-500/80), CSScolor-mix(), or define color shades in@theme. [src3] - Missing
@referencein Vue/Svelte scoped styles: In Tailwind v4,@applyin component<style>blocks requires a@referencedirective. Fix: Add@reference "../../app.css";at the top of the<style>block. [src1, src4] - Design tokens not generating utility classes: Variables defined outside
@themedo not generate Tailwind utilities. Fix: All design tokens that need utility classes must be inside@theme { }, not in plain:root { }. [src3, src7] - Sass
@for/@eachloops for grid classes: Tailwind's JIT engine already generates these on-demand. Fix: Delete Sass loops and use Tailwind's built-ingrid-cols-*,gap-*, and arbitrary value syntax. [src7] - LESS variable syntax collides with CSS at-rules: LESS variables (
@variable) look identical to CSS at-rules (@media,@import,@theme). Fix: Convert LESS variables to CSS custom properties (--variable) early in the migration. [src4]
Diagnostic Commands
# Count remaining Sass/LESS files
find . -name '*.scss' -o -name '*.sass' -o -name '*.less' | grep -v node_modules | wc -l
# Count Sass variable references still in use
grep -rn '\$[a-zA-Z]' --include='*.scss' --include='*.vue' --include='*.svelte' | grep -v node_modules | wc -l
# Count LESS variable references
grep -rn '@[a-zA-Z]' --include='*.less' | grep -v node_modules | grep -v '@media\|@import\|@charset\|@keyframes\|@font-face' | wc -l
# Check for Sass dependencies in package.json
node -e "const p=require('./package.json'); const deps={...p.dependencies,...p.devDependencies}; const sass=Object.keys(deps).filter(k=>k.match(/sass|less|stylus/i)); console.log(sass.length?'Still installed: '+sass.join(', '):'Clean');"
# Verify Tailwind v4 is working
npx @tailwindcss/cli -i src/app.css -o /dev/null 2>&1 && echo "OK" || echo "Failed"
# Check generated CSS size
npx @tailwindcss/cli -i src/app.css -o dist/output.css && wc -c dist/output.css
# Find remaining @import of Sass partials
grep -rn "@import '.*'" --include='*.scss' --include='*.css' | grep -v node_modules | grep -v tailwindcss
# Verify Node.js version meets minimum requirement
node -v # Must be v20.0.0 or higher for Tailwind v4
Version History & Compatibility
| Version | Status | Breaking Changes | Migration Notes |
|---|---|---|---|
| Tailwind v4.3 (May 2026) | Current | First-party scrollbar utilities (scrollbar-thin, scrollbar-thumb-*, scrollbar-gutter-stable), @container-size block-size container queries, zoom-* + tab-*, stacked @variant support, default-value functional utilities | No breaking changes; no Sass-specific changes. Replace Sass scrollbar mixins with native scrollbar-* utilities. [src9] |
| Tailwind v4.2 (Feb 2026) | Current | Four new color palettes (mauve, olive, mist, taupe), official @tailwindcss/webpack plugin (2.17× faster), full logical-property utilities (pbs-*, pbe-*, mbs-*, mbe-*, inline-*, block-*), font-features-*. start-* / end-* deprecated in favor of inline-s-* / inline-e-* | Rename any start-* / end-* usages after upgrade. Webpack-based Sass projects can drop PostCSS for the official plugin. [src10] |
| Tailwind v4.1 (Apr 2025) | Maintenance | Text shadows, masks, @source not/inline(), improved browser fallbacks | Minor patch on v4.0 — no Sass-specific changes |
| Tailwind v4.0 (Jan 2025) | Maintenance | Oxide engine (Lightning CSS), @import "tailwindcss" replaces @tailwind, CSS-first @theme config, no Sass/LESS support | postcss-import and autoprefixer no longer needed; Sass files must be converted to CSS |
| Tailwind v3.4 (Dec 2023) | LTS | Last version supporting Sass/LESS coexistence | Stay here if you cannot remove Sass yet |
| Tailwind v3.0 (Dec 2021) | Maintenance | JIT engine default | Content paths required in tailwind.config.js |
| Sass 1.x (Dart Sass) | Current | @import deprecated for @use/@forward | Convert Sass @import to @use before migrating to Tailwind |
| LESS 4.x | Current | — | LESS @var conflicts with CSS at-rules; rename before converting |
When to Use / When Not to Use
| Use When | Don't Use When | Use Instead |
|---|---|---|
| Starting a new project or major redesign | Sass codebase is stable and team is productive | Keep Sass, add Tailwind incrementally |
| Design system is defined in design tokens | Heavy use of Sass programmatic features (functions, control flow) | Keep Sass for complex theming, use Tailwind for layout |
| Team wants utility-first workflow and faster prototyping | Project has <500 lines of CSS and no complexity | Vanilla CSS or CSS Modules |
| Bundle size is a concern (Tailwind purges unused CSS) | Need to support IE11 or Safari <16.4 | Stay on Tailwind v3 + Sass, or PostCSS alone |
| Want to eliminate Sass build step overhead | Library/design system consumed by multiple apps with varying build setups | CSS custom properties + vanilla CSS |
Important Caveats
- Tailwind v4 requires modern browsers: Safari 16.4+, Chrome 111+, Firefox 128+. If your audience needs older browsers, stay on Tailwind v3.4 which supports Sass coexistence.
- The automated
@tailwindcss/upgradetool does not process.scssor.lessfiles. You must manually convert preprocessor code to plain CSS before or after running the tool. @applyis still supported in v4 but is considered an escape hatch. Tailwind Labs recommends using utility classes directly in markup, and@utilityfor truly reusable component patterns.- LESS variable syntax (
@variable) collides with CSS at-rules (@media,@import,@theme). During migration, this can cause confusing parser errors. Convert LESS variables to CSS custom properties early. - CSS
color-mix()(the replacement for Sassdarken()/lighten()) requires Safari 16.4+, Chrome 111+, Firefox 113+. For wider support, pre-define color shades in@theme. - Tailwind v4 builds are up to 5x faster for full builds and 100x faster for incremental builds compared to v3, thanks to the Rust-based Oxide engine. This speed improvement alone can justify removing the Sass build step.
- In v4.1,
@source notcan exclude legacy Sass directories from Tailwind's class detection scanning, speeding up builds during incremental migration. [src8] - v4.2 (Feb 2026) deprecated
start-*andend-*utilities in favor ofinline-s-*/inline-e-*. If your Sass codebase used logical-direction mixins, map them straight to the new names rather than the deprecated ones. [src10] - v4.3 (May 2026) added first-party scrollbar utilities —
scrollbar-thin,scrollbar-thumb-*,scrollbar-track-*,scrollbar-gutter-stable. Sass projects that ship custom::-webkit-scrollbarselectors can replace them with these utilities and drop the Sass file entirely. [src9] - v4.3
@container-sizeenables block-direction container queries — useful when migrating Sass@include respond-to($height)macros that previously required JavaScript hacks. [src9] - Webpack users: v4.2 introduced the official
@tailwindcss/webpackplugin (~2.17× faster than PostCSS). After Sass removal, switch frompostcss-loader + @tailwindcss/postcssto the dedicated webpack loader for a free build speedup. [src10]