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

Viewed 7694

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?

4 Answers

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 and it will remain as preload, so to indicate it as stylesheet you should use another attribute such as as which indicate the type of element and in your case, it should be style. Then you need to tell the browser whenever the loading process got finished you need to consider this as 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 here in google developers.

UPDATE

Since preload is not supported in firefox until now (according to this), the only way to do it, is to declare it twice in the 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 valid preload style, whilst the format is valid according to W3.org.

If you feel you need to do this Javascript circus trick to save a few hundred milliseconds, I recommend the version below. Use it instead if you want cross-browser support:

<link media="print" onload="this.media='all'" rel="stylesheet" type="text/css" href="style.css" />

Why does this work? In nearly all browsers going back to the 1990's, support of linked "print" media type style sheet was universally supported. Linked print style sheets were only used when printing pages. Because browsers knew the "sheet" media type must always be downloaded before "print", they often delayed or downloaded sheets with "media=print" asynchronously. Nothing was needed by the page author. It has worked this way for many years in most browsers, naturally.

Recently, developers trying to follow Google's new ranking policies discovered this trick to stop some styles from blocking others or from downloading immediately. They then realized the "print" media type was the only built-in, cross-browser way to fool browsers into delaying downloading of style sheets.

Turning your style sheet into a "print" type using the trick above doesn't mean its "print", as the script later changes it back to "all". It is simply a "hack" or way to prevent modern browsers from downloading your CSS styles in parallel with other sheets.

Note: "all" is not supported in a wide range of older browsers including Internet Explorer versions 1-7, so a bad idea, anyway.

Stopping one or two style sheets from blocking another sheet from downloading would be the only reason to use this trick, and assumes you are using a HUGE style sheet that is 50+ kilobytes in size and use a server with slow connections.

RECOMMENDATIONS?

I recommend you do NOT ever "preload" CSS for the following reasons!

  1. Just because Google flags this as an issue in Lightspeed, doesn't mean filling your webpages up with duplicate style links and elaborate JavaScript hacks to shave off a 100 milliseconds is a good idea. You should care more about the quality and integrity of your HTML pages above all other concerns, including speed or advertising-driven search engine demands!
  2. There could be racing issues! What happens when your HTML downloads before your async "print" sheet resolves itself back to "all"? You may see a flash in some browsers where the HTML downloads first and rendering begins before the async styles are downloaded. Your user then sees your website layouts and fonts move or shift. Nasty!!
  3. Async'ing CSS is kinda pointless compared to these poorly designed Javascript frameworks kids are downloading in 2021 that waste download times anyway. Most style sheets are 50 kilobytes or less in size compared to the MASSIVE 500-1500+ kilobytes most modern Javascript frameworks shove into the browser today (ie. React, Angular, Ember, etc.). These downloads often "embedd" the same CSS over and over into the browser's cache anyway, forcing a reload of the same CSS each site visit unlike CSS linked styles which can be cached for months! So preloading linked CSS makes no sense if its reloaded every visit. So what is the point?
  4. Many browsers may crash and burn with this trick! The preload is not widely adopted anyway, so you run a huge risk in a percentage of your users seeing an unstyled web site if you use this "hack". Imagine 5%-10% of your users seeing your website displayed in the default 'Times Roman' font and a white block-level, unstyled content page because you wanted to save 500 milliseconds of download time? Sorry, not worth the risk!
  5. Most old browsers had only 2 open connections allowed when downloading files, so they were limited by open connections, not style sheet downloads. Many modern browsers have 6 maximum. So again, connections are the bottleneck here when combined with multiple open JavaScript calls, not style sheet downloads. So little is gained using this trick.
  6. Slow Servers are Often the REAL Bottleneck: Server delays on opening connections on the server can be huge bottlenecks. Even if your host provider or web application like Wordpress is using cached images, pages, and proxies but your waiting hundreds of milliseconds for a connection to open up on the server, all that becomes meaningless. CDN's can also fail, be delayed, blocked, etc., too.
  7. The number one factor delaying downloads, besides slow servers and giant JavaScript API libraries, is more often huge image files. Consider using new HTML5 'picture' elements with multiple image types like "WebP" that are highly compressed. If you page has "on-demand", non-streaming video, that also must be set to preload or download asynchronously. Adding "width" and height" values to force 'alt' attribute placeholders, as images download will create reserved dimensions in your page layouts so they don't shift waiting images to download. You will be amazed at the savings in download times and bottlenecks prevented when you focus on image and media issues, not CSS.

All that makes preloading CSS pretty worthless as far as website improvements. I would go look at the multiple Bootstrap, JavaScript modules, and JQuery file downloads stacked up in your browser grabbing limited, shared browser connections and focus on less scripts. 30 or so kilobytes of CSS will likely not be the issue.

Firefox has supposedly enabled "preload" in version 85, but it doesn't seem to work correctly. What I found that this code below works:

<link rel="preload stylesheet" as="style" href="style.css">
Related