Skip to content

CSS: true silently deletes @media (width>=...) range-syntax blocks, breaking all Tailwind v4 responsive breakpoints #640

Description

@brumleygap

Description

With CSS: true, this integration's CSS minification (csso 5.0.5) silently deletes every @media block that uses the modern CSS Media Queries Level 4 range syntax (@media (width>=40rem) { ... }) instead of erroring or leaving it alone. It doesn't just fail to minify the block — the entire block is removed from the output.

This matters a lot for Tailwind CSS v4 users on Astro 7: Tailwind's @tailwindcss/vite plugin now emits its default responsive breakpoints (sm:, md:, lg:, xl:, 2xl:) using exactly this range syntax rather than the older min-width syntax. The practical effect is that every responsive utility class in the whole site silently stops working the moment this integration's CSS compression is enabled — no build error, no warning, just missing styles in production.

I hit this upgrading a real site from Astro 6 to Astro 7 and initially suspected @tailwindcss/vite/Vite 8 itself (there's a related-looking closed thread at tailwindlabs/tailwindcss#19792 about LightningCSS+Vite 8). That turned out to be a red herring — a from-scratch Astro 7 + @tailwindcss/vite project with no other integrations renders breakpoints fine. Adding astro-compress with CSS: true on top is what breaks it. This might be the same underlying csso limitation as #400 (CSS nesting syntax also silently dropped), just a different modern-CSS-syntax trigger.

Reproduction

mkdir repro && cd repro
npm init -y
npm install astro tailwindcss @tailwindcss/vite astro-compress

astro.config.mjs:

import { defineConfig } from 'astro/config';
import tailwindcss from '@tailwindcss/vite';
import compress from 'astro-compress';

export default defineConfig({
  integrations: [compress({ CSS: true, HTML: false, Image: false, JavaScript: false, SVG: false })],
  vite: { plugins: [tailwindcss()] },
});

src/styles/global.css:

@import 'tailwindcss';

src/pages/index.astro:

---
import '../styles/global.css';
---
<html lang="en">
  <head><meta charset="UTF-8" /><title>repro</title></head>
  <body>
    <section class="px-6 sm:px-6 py-12 sm:py-16 lg:py-20 mx-auto max-w-xl">
      <h1 class="text-4xl font-bold">Hello</h1>
    </section>
  </body>
</html>
npx astro build
grep -oE '@media[^{]*\{' dist/_astro/*.css | sort -u

Expected: five @media blocks (width>=40rem, 48rem, 64rem, 80rem, 96rem — Tailwind's default sm/md/lg/xl/2xl breakpoints), and .sm\:px-6, .lg\:py-20, etc. present in the output.

Actual: zero @media blocks referencing any breakpoint, and none of the sm:/md:/lg:/xl:/2xl:-prefixed classes appear anywhere in the compressed CSS. Setting CSS: false (or removing the integration) restores all of them immediately — confirmed on the exact same input.

Environment

  • astro: 7.1.3
  • vite: 8.1.5
  • tailwindcss: 4.3.3
  • @tailwindcss/vite: 4.3.3
  • astro-compress: 2.4.1
  • csso (as installed by astro-compress): 5.0.5
  • node: v26.5.0
  • OS: macOS (Darwin 25.5.0)

Workaround

Set CSS: false in the compress() config. Vite/LightningCSS already emits fully minified CSS on its own (single-line, no whitespace) even without this integration's CSS step, so for Tailwind v4 projects this option currently trades a mostly-redundant minification pass for silent, total loss of responsive styling.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions