Search code examples
csspreloadgoogle-pagespeed

How to use both rel="preload" and rel="stylesheet" for the same tag?


Google Pagespeed test doesn't recognize preload when it is used together with stylesheet. I tried

<link rel="preload stylesheet" href="http://www.example.com/style.css" />

and it still shows "Consider using to prioritize fetching resources that are currently requested later in page load.". If I remove stylesheet from rel attribute, it recognizes the preload.

I was thinking to try this:

<link rel="preload" rel="stylesheet" href="http://www.example.com/style.css" />

but I am not sure if you can have 2 the same attributes for the same link tag. Would this work?


Solution

  • For loading CSS styles asynchronously, you should indicate it as a preload stylesheet. Whenever you use rel="preload" alone, it won't transform to stylesheet on page load. It will remain as preload, so to indicate it as a stylesheet, you should use another attribute such as as, which indicates the type of element; in your case, it should be style. Then you need to tell the browser when the loading process is finished You need to consider this a stylesheet, so you have to define another attribute like onload and then define its real relation.

    So you have to import it like this:

    <link rel="preload" as="style" onload="this.rel='stylesheet'" href="http://www.example.com/style.css">
    

    NOTE: You can read more about it in web.dev.

    Update 2024

    Basic Usage of preload

    Thanks to @Hewlett, we have an update regarding browser support for preload. According to Caniuse, the preload feature is now widely supported across all major browsers. This development makes <link rel="preload"> a reliable choice for prefetching resources without immediately executing them. For preloading stylesheets, the basic implementation would look like this:

    <link rel="preload" as="style" href="http://www.example.com/style.css">
    

    Applying Preloaded Stylesheet

    However, as highlighted by @MichaelFreidgeim, and per MDN Web Docs, preload merely prioritizes downloading and caching the resource; it doesn't directly apply the stylesheet. To ensure that a preloaded stylesheet is utilized as a stylesheet once loaded, a JavaScript-based solution is ideal. This method allows us to preload the stylesheet, reducing its initial render-blocking impact, and then to apply it after the full page load.

    Implement it as follows:

    <link rel="preload" as="style" href="http://www.example.com/style.css" id="preloadStyle">
    <script>
      window.addEventListener('load', function() {
        var preloadLink = document.getElementById('preloadStyle');
        preloadLink.rel = 'stylesheet';
      });
    </script>
    

    In this setup, the <link> tag initially preloads the stylesheet with rel="preload". The JavaScript snippet is designed to wait for the window.load event, which is triggered when the entire page, including all dependent resources, is fully loaded. Once this event occurs, the script changes the rel attribute of our preloaded link to stylesheet, thus applying the styles to the page. This approach strikes a balance between efficient resource loading and optimal rendering performance.

    Handling Specific Positioning in DOM

    In cases where you need to preload stylesheets but append them at a specific position in the DOM, you can utilize JavaScript to dynamically insert the stylesheet after its preload phase. This method is especially useful when you want to maintain a specific load order for your styles. For instance, to preload a stylesheet and insert it below an existing style tag, you can do the following:

    <!-- Your first style tag -->
    <style id="firstStyle">
        /* Your CSS here */
    </style>
    <!-- Preload your CSS file -->
    <link rel="preload" as="style" href="http://www.example.com/style.css" id="preloadStyle">
    <script>
      function loadAndInsertStyle(href, insertAfterId) {
        var link = document.createElement('link');
        link.href = href;
        link.rel = 'stylesheet';
    
        var ref = document.getElementById(insertAfterId);
        ref.parentNode.insertBefore(link, ref.nextSibling);
      }
    
      window.addEventListener('load', function() {
        loadAndInsertStyle('http://www.example.com/style.css', 'firstStyle');
      });
    </script>
    

    This method ensures that your stylesheet is preloaded and then inserted in the desired position within the DOM, allowing for more granular control over stylesheet loading and application.

    Previous Update(obsolete)

    Since preload is not supported in Firefox until now (according to this), the only way to do it is to declare it twice in one rel tag or two separate tags.

    <link rel="preload" as="style" href="http://www.example.com/style.css">
    <link rel="stylesheet" href="http://www.example.com/style.css">
    

    Or

    <link rel="stylesheet" rel="preload" as="style" href="http://www.example.com/style.css">
    

    NOTE: As @JohnyFree tested the second one (one with a line through) in the Google page speed, it won't be recognized as a valid preload style, whilst the format is correct according to W3.org.