PlayForm/Compress

CSS compression is changing the order off lines of CSS

Closed this issue ยท 7 comments

I was wondering if you have come across this behaviour before. I believe to have isolated my problem to the astro-compress integration.

When I run astro build in my project and the CSS compression takes place, the order of the lines of my CSS are being changed in the compression process. This is causing the incorrect styling to take precedence, namely in my media queries as the breakpoints are in the incorrect order to work (I am using max-width breakpoints so require them to descend in size in my CSS for them to work correctly).

If I set compression to false in my config as below, the issue goes away, which makes me believe it's the integration's CSS compression causing the issue

export default defineConfig({
  integrations: [
    compress({
      css: false,
    }),
  ],
});

My CSS and overall Astro setup is a bit complicated so it may be difficult for me to make a minimum reproducible repo, but I can try if very necessary.

I use SCSS everywhere in my project, which may be relevant. The styles that I noticed this was happening in are in my global sass files as opposed to component styling.

These styles are in my /src/sass/ directory, where I have an abstracts and base directory with further sass files that all get imported into my global.scss. See image of directory below.

image

I've disabled CSS compression for now, and happy to help investigate the issue where needed.

Thanks for the great integration so far!

So, astro-compress uses csso under the hood for CSS compression, so you might want to check that out. https://www.npmjs.com/package/csso. In particular the restructure option. See if you can disable that and try again. Also you might want to try forceMediaMerge off.

import compress from "astro-compress";
import { defineConfig } from "astro/config";

export default defineConfig({
	integrations: [
		compress({
			css: {
				restructure: false,
				forceMediaMerge: false
			},
		}),
	],
});

Hope this helps!

xanode commented

Hello,

I've got the same problem in an Astro project.

I use the TailwindCSS integration and the typography plugin of this framework. When using media queries, for example like this:

<body>
  <h1 class="text-3xl font-bold text-red-500 md:text-green-500 lg:text-black">
    Hello world!
  </h1>
  <div class="prose lg:prose-lg">
    <h1>Title</h1>
    <p>Text</p>
  </div>
</body>

We get media queries written in this order:

@media (min-width: 1024px) {
  /* CSS related to lg:prose-lg */
}

@media (min-width: 768px) {
  .md\:text-green-500 {
    --tw-text-opacity: 1;
    color: rgb(34 197 94 / var(--tw-text-opacity));
  }
}

@media (min-width: 1024px) {
  .lg\:text-black {
    --tw-text-opacity: 1;
    color: rgb(0 0 0 / var(--tw-text-opacity));
  }
}

The use of astro-compress (and more specifically csso) gathers the media queries but does not correct the order which causes a distortion of the style :

@media (min-width: 1024px) {
  /* CSS related to lg:prose-lg */
  .lg\:text-black {
    --tw-text-opacity: 1;
    color: rgb(0 0 0 / var(--tw-text-opacity));
  }
}

@media (min-width: 768px) {
  .md\:text-green-500 {
    --tw-text-opacity: 1;
    color: rgb(34 197 94 / var(--tw-text-opacity));
  }
}

Then we have medium-screen style overriding large-screen style on large screens.

Although this avoids duplication of code, it seems that it would be better to keep a specific order so as not to break this kind of thing (decreasing order when using @media (max-width: ... and increasing order for @media (min-width: ... for example).

We would have preferred this:

@media (min-width: 768px) {
  .md\:text-green-500 {
    --tw-text-opacity: 1;
    color: rgb(34 197 94 / var(--tw-text-opacity));
  }
}

@media (min-width: 1024px) {
  /* CSS related to lg:prose-lg */
  .lg\:text-black {
    --tw-text-opacity: 1;
    color: rgb(0 0 0 / var(--tw-text-opacity));
  }
}

I think it is related to this issue of csso.
In this particular case setting forceMediaMerge: false is indeed a (partial?) fix.

@xanode Yeah, disable forceMediaMerge

Thank you for your input and quick response @nikolaxhristov - that worked from what I can see for the main issue I spotted!

However, I am seeing some other CSS compilation issues on build such as again the wrong CSS taking precedence, but also with my CSS being duplicated in some places, but I think the latter may just be related to Astro as even after removing the astro-compress integration it is still present. (I'd appreciate any signposting if you have heard of similar behaviour from Astro before, although I know this may be an issue for their Github!)

But after fully removing astro-compress, I do see certain style fixes related to the wrong styles taking precedence. Is it possible that HTML compression may also be causing these issues? If I disable both compression of HTML and CSS like so, the problem goes away.

export default defineConfig({
  integrations: [
    compress({
      html: false,
      css: false,
    }),
  ],
});

Thanks again for your input ๐Ÿ™๐Ÿผ

Yes, html-minifier-terser also has some CSS minification built-in, so you might want to disable that. Try minifyCSS false.

import compress from "astro-compress";
import { defineConfig } from "astro/config";

export default defineConfig({
    integrations: [
        compress({
            css: {
                restructure: false,
                forceMediaMerge: false
            },
            html: {
                minifyCSS: false
            }
        }),
    ],
});

Hello,

I had just ran into this problem yesterday.

I'm using tailwind integration. While using astro preview mode , I noticed that media qureies were being applied in reverse order than the astro dev mode. Making my div strech to the width limit.

<div
  class="container mb-6 mx-auto max-w-xs md:max-w-md lg:max-w-lg w-full rounded-lg bg-white p-6 shadow-lg">
...content
</div>

Luckily I was able to fix it with just

css: {restructure: false}

here is my config

import { defineConfig } from 'astro/config';
import tailwind from "@astrojs/tailwind";
import node from "@astrojs/node";

import compress from "astro-compress";

// https://astro.build/config
export default defineConfig({
  experimental: {
    assets: true
  },
  integrations: [tailwind(), compress({
      css: { restructure: false }
      })],
  output: "server",
  adapter: node({
    mode: "standalone"
  })
});

Thanks for your research guys. ๐Ÿซ‚

Fixed in 1.1.43