(This is my first bug report on drupal.org, feel free to point out things that I could have done better)

Problem/Motivation

It seems that CSS aggregation changes the order of CSS rules if "@import" rules are used.

I've created a simple theme to reproduce the issue:

test_theme.info.yml

name: Test theme
type: theme
description: Test theme
core: 8.x

libraries:
  - test_theme/main

test_theme.libraries.yml

main:
  css:
    theme:
      static/main.css: {}

static/main.css

@import url(first.css);
@import url(second-desktop.css) screen and (min-width: 1024px);
@import url(second-mobile.css) screen and (max-width: 1023px);

static/first.css

.first { margin: 0; }

The contents of "second-desktop.css" and "second-mobile.css" are irrelevant.

If I use this theme with CSS aggregation turned on then the whole CSS for the theme is served as a single file with the following content:

@import url(/themes/custom/test_theme/static/second-desktop.css) screen and (min-width:1024px);@import url(/themes/custom/test_theme/static/second-mobile.css) screen and (max-width:1023px);.first{margin:0;}

As you can see, the content from "first.css" is now contained in the file instead of being imported. However, it is included after the "second-*.css" files. While this is correct according to the CSS standard (which mandates that "@import" rules must come before any other rules) it changes the meaning of the CSS, since I now cannot override rules from "first.css" in the "second-*.css" files.

If I turn of CSS aggregation then the theme works as expected.

Proposed resolution

"@import" rules should only be inlined during CSS aggregation if all "@import" rules after them can also be inlined. If some are guarded by media queries as in my example then only "@import" rules after the last guarded "@import" rule should be inlined.

Comments

torf created an issue. See original summary.

star-szr’s picture

Version: 8.0.4 » 8.0.x-dev
Component: theme system » asset library system

Thanks for the report, I think asset library system is a more accurate component but could be wrong :)

wim leers’s picture

Title: CSS Aggregation changes order of rules » @import rules with media queries break in CSS aggregation
Issue tags: +Needs backport to D7, +mobile, +front-end performance

Great find! I'm 99% certain this bug then also exists in Drupal 7.

The proposed resolution says:

"@import" rules should only be inlined during CSS aggregation if all "@import" rules after them can also be inlined. If some are guarded by media queries as in my example then only "@import" rules after the last guarded "@import" rule should be inlined.

I was gonna say But why not just import the ones we can, and respect their order, but then I remembered that all imports must be at the top, per http://www.w3.org/TR/REC-CSS2/cascade.html#at-import.

I honestly think it's only by accident that we don't resolve the @import rules that have a media query. I bet the regular expressions we use just don't find those.

Your proposed solution would work. But wouldn't it be better to also resolve those with a media query and then just wrap the CSS in a @media rule? The browser always fetches all CSS, even if it doesn't currently meet that particular media query. If we don't do what I propose, then the effectiveness of CSS aggregation is severely diminished.

torf’s picture

Wim Leers said:

But wouldn't it be better to also resolve those with a media query and then just wrap the CSS in a @media rule? The browser always fetches all CSS, even if it doesn't currently meet that particular media query. If we don't do what I propose, then the effectiveness of CSS aggregation is severely diminished.

That does indeed sound like a better solution.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev
catch’s picture

Status: Active » Closed (outdated)
Issue tags: +Bug Smash Initiative