tailwindcss icon indicating copy to clipboard operation
tailwindcss copied to clipboard

Media queries nested inside selector is correctly processed in build mode, but not dev mode

Open hugentobler opened this issue 1 year ago • 10 comments

What version of Tailwind CSS are you using?

v4.0.6

What browser are you using?

This is a Safari issue.

I am working with svelte files. I had implemented media queries nested inside of selectors which were working just fine in Chrome. However when I was testing in Safari, I realised that nesting media queries inside of selectors is technically invalid syntax, even though Chrome is able to render it.

So looking into it, I realised that postcss processes the styles into valid markup in build mode, but not in dev mode. So Safari renders it correctly in build mode but not dev mode.

I'm wondering what is the suggested way to use media queries in svelte files then. (I know this is not the preferred utilities-based tailwind syntax, but I have this use-case where I don't want to inline these styles). And also wondering if there is a postcss issue on dev or the aforementioned behaviour is expected.

<style lang="postcss">
  @reference "../../app.css";

  article {
    columns: auto;

    @media (width >= theme(--breakpoint-lg)) {
      --visible-columns: 2;
      columns: calc(min(65ch, (100cqw - var(--x-spacer) * 2) / var(--visible-columns)));
    }

    @media (width >= theme(--breakpoint-2xl)) {
      --visible-columns: 3;
    }

    @media (width >= theme(--breakpoint-3xl)) {
      --visible-columns: 4;
    }
</style>
Dev Build

/*! tailwindcss v4.0.0 | MIT License | https://tailwindcss.com */
article.s-SR93p9P2y7Or {
  columns: auto;
  @media (width >= 64rem) {
    --visible-columns: 2;
    columns: calc(min(65ch, (100cqw - var(--x-spacer) * 2
) / var(--visible-columns)));
  }
  @media (width >= 96rem) {
    --visible-columns: 3;
  }
  @media (width >= 120rem) {
    --visible-columns: 4;
  }
}
      

article.svelte-1fsglyr {
    columns: auto;
}

@media (width > =64rem) { article.svelte-1fsglyr { --visible-columns: 2; columns: min(65ch,(100cqw - var(--x-spacer) * 2) /var(--visible-columns)); column-gap: 0; } }

@media (width > =96rem) { article.svelte-1fsglyr { --visible-columns:3 } }

@media (width > =120rem) { article.svelte-1fsglyr { --visible-columns:4 } }

hugentobler avatar Feb 11 '25 16:02 hugentobler

Hey @hugentobler. Do you mind attaching a small reproduction for this that we can run locally? I'm curious which post-processing step adds the space between the >= sign - That's definitly not Tailwind CSS! 😅

Maybe a work-around would be to use min-width: and max-width: media queries instead?

philipp-spiess avatar Feb 11 '25 16:02 philipp-spiess

Hi @philipp-spiess sorry the space between >= is just a typo when I was copy pasting. I'm pretty certain that all the browsers support range-based media queries. But I'm not sure if Safari dev doesn't work simply because media queries are not allowed to be nested in selectors, or there is sth else going on. If it is just that media queries are not allowed to be nested, then I will just rewrite the styling.

hugentobler avatar Feb 11 '25 17:02 hugentobler

What version of Safari are you using?

adamwathan avatar Feb 11 '25 18:02 adamwathan

Safari v18.3

hugentobler avatar Feb 11 '25 18:02 hugentobler

Just to continue this issue: In the skeleton framework, a nested media query is also used and we're encountering a similar issue. Being that the contents inside the query are not recognized by Safari:

:root {
	color-scheme: light;
	@variant dark {
  		color-scheme: dark;
	}
}

So on dev mode this is missing/won't be recognized as such (copy from a build version of the website, just an example):

@layer base {
	@media (prefers-color-scheme:dark) {
		body {
			color: var(--base-font-color-dark);
		}
	}
}

nwrenger avatar Feb 28 '25 21:02 nwrenger

Seems like the following is always failing for me using regular .css files:

@utility my-button {
  color: blue;
  @media (width >= theme(--breakpoint-md)) {
    color: red
  }
}

Currently have to do:

.my-button {
  color: blue;
}
@media (width >= theme(--breakpoint-md)) {
  .my-button {
    color: red;
  }
}

Cretezy avatar Mar 17 '25 18:03 Cretezy

@Cretezy just FYI we encountered similar issues with media queries for breakpoints. Variants are supported for these specifically.

@utility my-button {
  color: blue;
  @variant md {
    color: red
  }
}

endigo9740 avatar Mar 20 '25 19:03 endigo9740

I wanted to help showcase @nwrenger 's issue here. Here's a minimal reproduction:

https://play.tailwindcss.com/4zRUzHyTow?file=css

https://github.com/user-attachments/assets/4a60ca45-2f5a-4794-a896-120fc6f1a525

The catch being is this does not show the error, it's fully functional in Safari. But that's the weird part of this issue - it seems to be restricted to ONLY dev servers for SvelteKit and Astro apps (so far).

  • Safari + dev server => scheme does not change to match mode.
  • Safari + production build => scheme does change to match mode (the desired outcome)

To make matters more more interesting, the issue seems to have been introduced in macOS 15 Sequoia. The version of Safari is tied to the OS, so here's a quick comparison.

Here's an Astro-based app using light-dark + color scheme on Safari 17.5

https://github.com/user-attachments/assets/55a77a2f-86a6-4dcd-8bf4-a88babff37e7

And then again on Safari 18.3.1

https://github.com/user-attachments/assets/b7dbd85a-e03b-4705-bb7e-5eaa7d288836

My theory here is something has change in the latest version of macOS/Safari that's affecting the Vite dev server for SvelteKit and Astro based apps. I'm not 100% sure this is an issue on Tailwind's end, but we might need some coordination between Tailwind/Vite to figure this one out.

endigo9740 avatar Mar 21 '25 18:03 endigo9740

I have same issue with dev vs production builds.

Tailwind version is 4.1.7

Development build for .container class.

.container {
    width: 100%;
  @media (width >= 768px) {
    max-width: 768px;
  }
  @media (width >= 992px) {
    max-width: 992px;
  }
  @media (width >= 1200px) {
    max-width: 1200px;
  }
}

VS Production build for .container class.

.container {
  width: 100%
}

@media (min-width: 768px) {
  .container {
    max-width:768px
  }
}

@media (min-width: 992px) {
      .container {
          max-width:992px
      }
}

@media (min-width: 1200px) {
  .container {
    max-width:1200px
  }
}

The developer experience isn’t great, but the production CSS build currently works with older browsers, which is beneficial in my case since my application still needs to support them to some extent. My concern is that I can’t reliably test the production build while developing new features, even though I do my best to maintain style compatibility with older browsers. A new Tailwind release could potentially break the currently working CSS in production. That said, in a year or two, supporting older browsers may no longer be necessary, which would simplify things considerably.

sebcomeau avatar May 26 '25 17:05 sebcomeau

This issue is related to https://github.com/tailwindlabs/tailwindcss/issues/16416 , which provides a Minimal Reproduction example: https://play.tailwindcss.com/ejMhEzAx6k

<div class="relative flex h-screen items-center justify-center">
  <button class="m-4 rounded-md bg-blue-600 px-4 py-2 font-bold text-white hover:cursor-pointer hover:bg-blue-900">A button with no hover styles in Chrome/Edge/Brave 133</button>
</div>

Using your browser's inspector on this playground example, you can see the generated CSS from the class hover:bg-blue-900:

@layer utilities { 
  .hover\:bg-blue-900 {
    &:hover {
      @media (hover: hover) {
        background-color: var(--color-blue-900);
      }
    }
  }
}

It nests the media query in the innermost layer.

gdlmx avatar Jun 12 '25 12:06 gdlmx

Hey!

Going to close this issue because the difference between dev and build mode is expected right now. Tailwind CSS relies on nesting internally, and all supported browser should handle this just fine. Quick example: https://play.tailwindcss.com/8DevlSGJL8

One of the examples provided above, also work as expected (in Safari): https://play.tailwindcss.com/Qe1PPHCxMO

For "production" builds we rely on Lightning CSS which does some optimizations like handling nesting (@media will be hoisted, but it's not wrong that it's nested inside) and adding some fallbacks for colors and what not. This is also guarantees our minimal browser support mentioned here: https://tailwindcss.com/docs/compatibility#browser-support

I also just spun up a new SvelteKit project locally with Tailwind CSS v4. If I then use nested media query syntax and open it up in Chrome and Safari it all seems to be handled as expected.

I would therefore recommend to see if you can bump your dependencies.

Going to close this for now as it all seems to work as expected. If you are still running into an issue like this, feel free to open a new issue with a minimal reproduction repo attached so we can take a look.

RobinMalfait avatar Sep 11 '25 15:09 RobinMalfait