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

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions