LibraryDiscoveryParser overwrites theme CSS group ordering

Created on 8 April 2019, almost 6 years ago
Updated 13 January 2024, about 1 year ago

My theme uses Bootstrap and I noticed I cannot change the library load order to appear before any module CSS libraries, no matter the group I specified (base, component, theme, etc.) - even if specified manually (`group: -200`). I tracked this down to core/lib/Drupal/Core/Asset/LibraryDiscoveryParser.php:165:

$options['group'] = $extension_type == 'theme' ? CSS_AGGREGATE_THEME : CSS_AGGREGATE_DEFAULT;

This essentially forces any theme CSS libraries into the CSS_AGGREGATE_THEME group (100) and overwrites/ignores any specified SMACCS group settings, e.g. 'base' (my_theme.libraries.yml):

bootstrap:
  css:
    base:
      libraries/bootstrap/bootstrap.min.css: {}

And also overwrites setting group specified like this:

bootstrap:
  css:
    base:
      libraries/bootstrap/bootstrap.min.css: { group: -200 }

So this doesn't function according to 'group' property described in the docs: Adding Stylesheets CSS and Javascript JS to a Drupal Theme which specifies the "rarely used" group setting causes assets to be aggregated per group - because it's overwritten in the case of themes and modules.

Even if my module (e.g. Faculty Cards) libraries file specifies 'css: theme' grouping, it still appears in the HTML loaded before the theme bootstrap library (which specifies 'base'):

faculty-cards:
  css:
    theme:
      css/faculty-cards.css: {}
   

The line in LibraryDiscoveryParser means that module CSS libraries are always loaded before theme CSS libraries regardless of SMACCS category (base, layout, component, theme, etc.) specified in respective files. Which means that greater CSS specificity or even worse !important needs to be used in module CSS files to override a theme that uses Bootstrap.

If I comment out the affected line in LibraryDiscoveryParser, ordering is as I would expect and group settings are respected.

🐛 Bug report
Status

Active

Version

9.5

Component
Asset library 

Last updated about 6 hours ago

No maintainer
Created by

🇨🇦Canada manafire Peterborough, Ontario

Live updates comments and jobs are added and updated live.
  • CSS

    It involves the content or handling of Cascading Style Sheets.

Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇺🇸United States JonMcL Brooklyn, NY

    Very frustrating to find out that using the "theme" category on a module's library, with a group value that is higher than CSS_AGGREGATE_THEME (100), does not allow the module's CSS to come after the theme's CSS in the DOM. Impossible to do simple CSS refinements when the module wants to do them.

    I am glad I am not alone in this :)

    For what it may be worth, here is my implementation of hook_css_alter that re-applies the group property from the library data:

    function modulename_css_alter(&$css, \Drupal\Core\Asset\AttachedAssetsInterface $assets) {
    
      foreach($assets->getLibraries() as $name) {
        [$module, $id] = explode('/', $name);
        if ($module && $id) {
          $library = \Drupal::service('library.discovery')->getLibraryByName($module, $id);
          foreach($library['css'] ?? [] as $definition) {
            if (isset($definition['group']) && $path = $definition['data']) {
              if (isset($css[$path])) {
                $css[$path]['group'] = $definition['group'];
              }
            }
          }
        }
      }
    }
    

    It is probably not very efficient, but should only run when needed and then the alterations are cached.

  • 🇪🇨Ecuador jwilson3

    Agree this is fairly frustrating and more than slightly nonsensical that there is no way to define a "base" SMACSS in a theme and make it appear first before module code and even before other SMACSS groups from the same theme.

    Even stable9 theme in Drupal core suffers from this exact issue out of the box:

    Given the following three examples...

    stable9.libraries.yml:

     css:
        base:
          css/core/assets/vendor/normalize-css/normalize.css: { weight: -20 }
    

    core.libraries.yml:

    internal.jquery_ui:
      css:
        component:
          assets/vendor/jquery.ui/themes/base/core.css: { weight: -11.8 }
        theme:
          assets/vendor/jquery.ui/themes/base/theme.css: { weight: -11.8 }
    

    system.libraries.yml:

    base:
      css:
        component:
          css/components/ajax-progress.module.css: { weight: -10 }
    

    One would expect normalize.css to be the first CSS file in the HTML, but in fact, it shows up last.

    Expected result:

    /core/themes/stable9/css/core/assets/vendor/normalize-css/normalize.css
    /core/assets/vendor/jquery.ui/themes/base/core.css
    /core/themes/stable9/css/system/components/ajax-progress.module.css
    /core/assets/vendor/jquery.ui/themes/base/theme.css
    

    Actual result:

    /core/assets/vendor/jquery.ui/themes/base/core.css
    /core/themes/stable9/css/system/components/ajax-progress.module.css
    /core/assets/vendor/jquery.ui/themes/base/theme.css
    /core/themes/stable9/css/core/assets/vendor/normalize-css/normalize.css
    
  • First commit to issue fork.
  • 🇩🇪Germany woldtwerk Stralibu

    I think we have 2 Issues here:
    1: group key is overwritten by LibraryDiscoveryParser (commit)
    2: we can't disable grouping. CssCollectionGrouper only checks for preprocess key. Thus you can't use preprocess, but opt out of grouping. (commit)

    For 2 it's debatable if 0 or -1 would be preferred.
    Let me know what you think

    fork

  • Pipeline finished with Success
    7 months ago
    Total: 524s
    #261187
  • 🇬🇷Greece vensires

    I am not yet 100% this issue is related but maybe the problem described in 🐛 Library gin_custom_css should depend on gin/gin for higher priority Active is something we should take into account here too.

  • First commit to issue fork.
  • 🇮🇳India arisen Goa

    I face the same issue. I need to load certain libraries from the modules after the theme libraries. The logic in the LibraryDiscoveryParser completely overrides any group settings done in the library. I feel it should be conditional rather(only applied if not set already).

    There is no way to work around this other writing a hook_css_alter() to set the group again for the required libraries.

  • Status changed to Needs work 4 months ago
  • 🇩🇪Germany woldtwerk Stralibu
Production build 0.71.5 2024