Page MenuHomePhabricator

Move CSS @imports to the top of the output
Closed, DeclinedPublic

Description

When user scripts are loaded from load.php, all custom user CSS pages are added to one file and served to the user. The issue with this is that if a CSS page that is not the first page has a @import it will fail because it is not at the top of the combined CSS script. To resolve this, all @import rules in the CSS need to be moved to the top of the combined CSS script. This issue occurs with the user.styles module, for example https://en.wikipedia.org/w/load.php?lang=en&modules=user.styles&only=styles&skin=vector&user=BrandonXLF&version=1ivau.

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript
Krinkle triaged this task as Low priority.EditedMay 13 2020, 9:52 PM
Krinkle subscribed.

Changing the order changes their meaning and cascading precendence. Today vector.css applies after common.css, which makes sense. Moving the @import would mean that imports from vector.css apply before the bulk of common.css. That seems confusing. If this is the intended behaviour, a user could place it at the top of common.css themselves, which seems preferrrable. It does mean one can't have it apply conditonally based on current skin selection. I don't know how common it is that users frequenly switch between skins, though. Note that styles can be applied specifically to one skin nowadays by using the .skin-vector selector.

This caveat with @import is why ResourceLoader automatically slices up chunks of CSS loaded via JavaScript up as needed so that sequences of @import are always at the start of a fresh <style> tag. However, this trick cannot be used for user syles because they meant to apply directly to the HTML (not load late after the page has already rendered for the user).

Having @import in both common.css and vector.css has never been supported for this reason, dating back to at least 2009 including in the time before ResourceLoader was created. As such I'm marking this as "Low" priority because it is not something that has stopped working. (Correct me if I misunderstood this!)

As for how to make this work today, there's a few options:

  • at the top of common.css only. – applies even if you switch skins.
  • at the top of vector.css, without anything in common.css. – need to copy the styles for multiple skins to each file.
  • if you're fine with the styles being split up and loading "late", then you can use importStylesheet from a vector.js page instead. This will achieve the "no copying" and "only for one skin", but at the expense of loading relatively late.
  • move common.css to another name (e.g. shared.css) and use @import at the top of vector.css. – this means there is no compression or optimisation benefits applied and will page your browser load pages a bit load slower. But, otherwise has the best of all the above, including that there will be no "late" arrivals for styles.

I do acknowledge that the current situation isn't ideal. This is mainly due to the limitation of @import itself as provided by web browsers. Perhaps a good first step would be to make this clearer to our users. For example, by informing users while editing if they have created this kind of situation.

Krinkle moved this task from Inbox to Backlog on the MediaWiki-ResourceLoader board.