Performance of CSS @import with layers vs. link

418 views Asked by At

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.

0

There are 0 answers