4

Assuming there are no internal embeds within the CSS files, is there any performance drawback using CSS layers and @import vs. <link> in the following server-side-rendered scenario:

Using <link>:

<html>
<head>
  <link rel="stylesheet" href="reset.css">
  <link rel="stylesheet" href="helpers.css">
  <link rel="stylesheet" href="grid.css">
  <link rel="stylesheet" href="theme.css">
</head>
<body>
  <link rel="stylesheet" href="header.css">
  <header><!-- Site header, logo, nav etc --></header>

  <main>
    <link rel="stylesheet" href="carousel.css">
    <div class="carousel-module"><!-- Carousel module --></div>

    <link rel="stylesheet" href="cards.css">
    <div class="cards-module"><!-- Cards module --></div>
  </main>

  <link rel="stylesheet" href="footer.css">
  <footer><!-- Site footer --></footer>
</body>
</html>

Using @import with layers:

<html>
<head>
  <style>
    @layer default, theme;
    @import url("reset.css") layer(default);
    @import url("helpers.css") layer(default);
    @import url("grid.css") layer(default);
    @import url("theme.css") layer(theme);
  </style>
</head>
<body>
  <style>
    @import url("header.css") layer(default);
  </style>
  <header><!-- Site header, logo, nav etc --></header>

  <main>
    <style>
      @import url("carousel.css") layer(default);
    </style>
    <div class="carousel-module"><!-- Carousel module --></div>

    <style>
      @import url("cards.css") layer(default);
    </style>
    <div class="cards-module"><!-- Cards module --></div>
  </main>

  <style>
    @import url("footer.css") layer(default);
  </style>
  <footer><!-- Site footer --></footer>

</body>
</html>

Background…

The system I'm using outputs the <link> mark-up above, with shared/common/layout-related CSS loaded in the <head> and content-specific CSS loaded alongside the HTML. It's nice and performant and lets the browser handle CSS loading without having to create spurious "above the fold" and "below the fold" bundles. It works great but comes unstuck when applying theme styling, which is intended to override any of the other CSS properties.

When applying theme styles by referencing theme.css in the <head> the themes are overridden because the inline-linked styles are loaded later in the document. Loading theme.css at the end of the document creates layout shifts because the browser needs to repaint everything which has already been rendered but subsequently changed by the late-loaded theme. I need to find the optimum way to deal with themes in this scenario other than having additional theme files for each module, which I'd rather avoid (we can only have one theme file which trumps everything it needs to).

A potentially neat solution is to utilise CSS layers so that all of the CSS is loaded in a default layer but theme.css is prioritised in its own layer, maintaining the desired "trump all" specificity of the theme. Presently the only way to do this without having to wrap each CSS file's contents in a @layer() is to switch from <link> to @import. I wondered if this impacts performance though.

Many thanks.

Dan
  • 5,836
  • 22
  • 86
  • 140
  • 3
    Everything I've read says that these are the same. i.e. that the performance concerns of @import relate only to internal embeds. In all the CSS working group discussions around the introduction of cascade layers, although there was a desire to have a `` mechanism for adding layered style sheets, I don't recall performance concerns over @import ever being raised. Although absence of evidence is not evidence of absence of course. (There's backward compatibility difficulties that make adding layers to the link element problematic) – Alohci Jan 23 '23 at 18:03
  • Many thanks @Alohci, although not categorical I find your insight reassuring. – Dan Jan 24 '23 at 13:03

0 Answers0