Importing CSS only once


#1

If you have two css files:

a.css

@import "./c.css";

b.css

@import "./c.css";

c.css’ rules are applied twice. Can we have an alternative syntax where the stylesheet is only applied if not already done so?


#2

AFAIK current best advice is simply to avoid @import entirely due to performance problems: https://gtmetrix.com/avoid-css-import.html

A redesigned @import should probably address the performance issue too.

Note that interestingly HTML imports have de-duplication, so using those to bring in stylesheets is sort-of there.


#3

@AshleyScirra The performance problem that article describes is fixed by <link rel="preload">. Is there another performance issue you are thinking of?

Interesting note about Imports, but does it make sense for a stylesheet to not be able to describe its own dependencies?


#4

If such a case did exist in nature, it seems like the two would actually do something potentially different in terms of rendering because of the cascade, no? Is there a reason that one or more is better or worse besides perf? Just curious. I’m not entirely sure why it is designed that way as opposed to the other - have you checked the archives of www-style?


#5

@briankardell You are comparing two things but I’m not sure what the two things you are comparing, so I can’t answer. Can you clarify?


#6

Just mocking this up with these three files, what is the expected currentColor value in three.css? Doing an importOnce style system messes with the natural cascading order of CSS. This is just once simple example of where things go wonky and get confusing. I’m sure there are more examples that could be thought of with more complex selectors becoming problematic as well, which would make for a difficult time debugging things.

one.css ```css .something { color: red; } ```
two.css ```css @importOnce('one.css');

.something { color: blue; }

</details>

<details>
<summary>three.css</summary>
```css
@importOnce('two.css');
@importOnce('one.css');

.anotherThing:has(.something):after {
  color: currentColor;
}

#7

I don’t find that confusing at all. Your example is equivalent to writing:

<link rel="stylesheet" href="one.css">
<link rel="stylesheet" href="two.css">
<link rel="stylesheet" href="three.css">

If you had used @import instead it would be equivalent of writing:

<link rel="stylesheet" href="one.css">
<link rel="stylesheet" href="two.css">
<link rel="stylesheet" href="one.css">
<link rel="stylesheet" href="three.css">

You can write a similar example of JS modules that clobber each other, but I don’t think that’s a good reason not to have modules.

@importOnce would be useful, for example, if you have a variables.css that contains :root defined variables that you want to use in other stylesheets.


#8

I’m curious, what’s the underlying issue you’re trying to solve?

With @import, you’re presumably using preload and technologies like appcache or service workers can be used to mitigate the extra http call so it’s probably not performance related.

While the sheet may be imported twice, it doesn’t change the specificity of the rules, just the cascade (which @Garbee pointed out) which is something you’d want when @import-ing twice.

If it’s merely to help identify dependencies, why not use a preprocessor and skip native @import altogether?


#9

I’m saying that the current behavior works as @Garbee illustrated and… yeah, it seems wonky… Same as including two links really though - should that change too? I’m not arguing one way or another, your thing sounds… kinda rational to me, but I presume there was probably discussion in making that set of choice tradeoffs (i.e. how it works now) as opposed to “if it already isn’t imported”/once thing you are suggesting which would effectively disallow import from creating that kind of situation. So i’m saying: have you looked to see if there are design conversations around this from way back already and read through them? I expect that recognition of/debate with original points as to why they are proving inadequate would be necessary to offer an alternative.