Mixing rel="preload" and rel="stylesheet" in a single tag: A guide

Google Pagespeed test is not able to recognize preload when it is used alongside a stylesheet. I attempted

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

and it continues to display the message "Consider using rel=preload to prioritize fetching resources that are currently requested later in page load.". When I remove 'stylesheet' from the rel attribute, the preload is recognized.

I am considering trying this:

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

but I am unsure if having two identical attributes for the same link tag would work. Can this be done?

Answer №1

To load CSS styles asynchronously, it's essential to designate it as a preload stylesheet. Simply using rel="preload" alone won't automatically transform it into a stylesheet upon page load; it will remain as a preload. To signify it as a stylesheet, you need to include another attribute like as, specifying the type of element, in this case, it should be style. Additionally, you must inform the browser when the loading process is completed by considering it as a stylesheet and defining attributes like onload along with its actual relation.

Therefore, the import should be structured as follows:

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

NOTE: For more information on this topic, refer to web.dev.

Update 2024

Utilizing preload in Practice

In an update provided by @Hewlett, there has been significant progress in browser support for preload. As indicated on Caniuse, the feature is now widely supported across major browsers. This advancement solidifies <link rel="preload"> as a dependable choice for prefetching resources without immediate execution. Specifically for preloading stylesheets, the basic implementation would resemble the following:

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

Implementing Preloaded Stylesheets

However, as emphasized by @MichaelFreidgeim and per MDN Web Docs, while preload prioritizes downloading and caching the resource, it does not directly apply the stylesheet. To ensure that a preloaded stylesheet functions as a stylesheet post-loading, a JavaScript-oriented solution is preferable. This approach allows for preloading the stylesheet to mitigate initial render-blocking effects, followed by application after full page load completion.

The enactment of this method is illustrated below:

<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>

With this configuration, the <link> tag initially preloads the stylesheet with rel="preload". Subsequently, the associated JavaScript snippet awaits the window.load event, triggered upon complete page loading, including all dependent resources. Upon this event, the script alters the rel attribute of the preloaded link to stylesheet, effectively applying the styles to the page. This strategy strikes a balance between efficient resource loading and optimal rendering performance.

Managing Specific DOM Positioning

In scenarios necessitating preloading of stylesheets positioned at specific locations within the DOM structure, leveraging JavaScript to dynamically insert the stylesheet post-preload phase offers a viable solution. This technique proves particularly beneficial when maintaining precise load order for styles is imperative. For example, to preload a stylesheet and insert it beneath an existing style tag, execute the following steps:

<!-- Initial style tag -->
<style id="firstStyle">
    /* Embedded CSS rules */
</style>
<!-- Preload the intended 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 methodology ensures successful preload of the stylesheet and subsequent insertion at specified DOM positions, thereby enhancing control over stylesheet loading and application precision.

Prior Update (now discontinued)

Since Firefox did not support preload until recently (referencing this source), the workaround involved declaring it twice in one rel tag or utilizing 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">

Alternatively

<link rel="stylesheet" rel="preload" as="style" href="http://www.example.com/style.css">
(Note: The second option crossed out was tested by @JohnyFree on Google pagespeed and found to be unrecognized as a valid preload style despite proper format compliance according to W3.org.)

Answer №2

optimize loading of CSS files by deferring non-critical resources Learn more here

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

Implement a fallback for browsers that do not support certain CSS features Check it out here

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

Answer №3

For those who find themselves resorting to this unique Javascript circus trick in order to save a few precious milliseconds, there is an alternative solution that I recommend. Instead of utilizing the method mentioned above, consider using the following code snippet for better cross-browser support:

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

But why does this workaround work? The answer lies in the fact that, historically, all browsers have universally supported linked stylesheets with a media type of "print" dating back to the 1990s. These linked print stylesheets were specifically designed for printing purposes only. Because browsers recognized that style sheets with a "sheet" media type needed to be downloaded before "print" styles, they often delayed or asynchronously downloaded stylesheets with a "media=print" attribute. No additional action was required on the part of the page author. This behavior has been consistent across most browsers for many years.

In more recent times, developers looking to adhere to Google's updated ranking guidelines stumbled upon this technique as a means to prevent certain styles from blocking others or downloading immediately. They soon discovered that the "print" media type was the ideal built-in, cross-browser method to persuade browsers to delay stylesheet downloads.

The transformation of your stylesheet into a "print" type using the aforementioned tactic does not mean that it remains exclusively "print", as the script triggers a change back to "all". Rather, it serves as a clever way to thwart modern browsers from concurrently downloading your CSS alongside other stylesheets.

It is important to note that "all" is unsupported by a variety of older browsers, including Internet Explorer versions 1-7, making it an ill-advised choice regardless.

The primary motivation for employing this trick would be to prevent one or two style sheets from obstructing the download of another sheet, assuming you are working with an extensive stylesheet exceeding 50 kilobytes and accessing a server with sluggish connections.

A WORD OF CAUTION:

I strongly advise against ever preloading CSS for several reasons!

  1. Merely because Google identifies this as an issue in Lightspeed, it does not justify inundating your webpages with redundant style links and complex JavaScript hacks to trim a mere 100 milliseconds off load times. Your top priority should always be the quality and validity of your HTML pages, surpassing concerns such as speed or search engine demands fueled by advertising!
  2. Potential race conditions! What occurs if your HTML loads prior to your asynchronous "print" sheet reverting back to "all"? Certain browsers may exhibit a flash where HTML loads first, triggering rendering before the async stylesheets complete their download. Consequently, users may witness layout discrepancies or font repositioning. Undesirable indeed!!
  3. Async'ing CSS lacks significance when compared to inadequately designed Javascript frameworks prevalent in 2021, squandering download time. Most stylesheets clock in at under 50 kilobytes, unlike the ENORMOUS 500-1500+ kilobyte behemoths introduced by modern JavaScript frameworks (e.g., React, Angular, Ember). These downloads commonly embed repetitive CSS content into the browser's cache, necessitating a reload of identical CSS every site visit, unlike externally linked styles that can linger in the cache for months! Hence, preloading external CSS appears futile if it undergoes reloading during each visit. So what purpose does it serve?
  4. Many browsers might falter with this trick! Since preload enjoys limited adoption, adopting this gamma poses a risk for a portion of your user base encountering an unstyled website. Picture 5%-10% of your visitors viewing your site in default 'Times Roman' fonts amidst barebones content due to the desire to clip 500 milliseconds from download times. Not worth the gamble!
  5. Older browsers restricted file downloads to just 2 open connections, indicating that the bottleneck was posed by active connections rather than stylesheet downloads. Conversely, contemporary browsers allow up to 6 maximum connections. Therefore, connection volume combines with multiple ongoing JavaScript calls represent bottlenecks, not stylesheet downloads. Consequently, minimal gain is derived from this trick.
  6. Slow servers essentially constitute the TRUE bottleneck: Delays in establishing server connections can result in substantial bottlenecks. Even if your hosting provider or platform like Wordpress exploits cached images, pages, and proxies, enduring lengthy waits for servers to accommodate connections renders such advantages moot. CDNs may encounter failure, delays, hindrance, etc., exacerbating matters further.
  7. One leading cause behind download delays, beyond dallying servers and colossal JavaScript API libraries, primarily involves oversized image files. Consider leveraging newfangled HTML5 'picture' elements encompassing varied image formats like "WebP" acclaimed for compressibility. If your webpage includes on-demand, non-streaming videos, these must be primed for asynchronous download or preload. Affixing 'width' and 'height' dimensions to enforce 'alt' placeholders ensures reserved dimensions within page layouts to preempt image displacement while awaiting downloads. Observe the remarkable savings in download durations and prevention of bottlenecks emanating from addressing image and multimedia concerns over CSS issues.

Ergo, preemptive CSS loading contributes minimally towards enhancing websites. It would be judicious to scrutinize the array of Bootstrap, JavaScript modules, and JQuery file bundles crowding your browser armed with shared, finite connections and divert attention towards scripting efficiency. Generally, around 30 kilobytes of CSS typically doesn't pose issues.

Answer №4

It has been reported that Firefox supposedly activated the "preload" feature in version 85, however, there seem to be some issues with its functionality. After some experimentation, I discovered that using the following code seems to produce the desired results:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for hiding the frame of a React MUI Select component

I am having trouble figuring out how to remove the border around the <Select> component from the React Material UI library. In the image below, you can see that when the <Select> component is not selected, it has a black border/frame. https:// ...

The DIV element is failing to fill the entire screen's width

I am completely new to web development and currently working on creating my very first website. I've managed to set up the layout, but I'm facing an issue when trying to optimize it for mobile devices. Specifically, some of my divs (particularly ...

Scroll the second div to align with the first div

I am in need of a scrolling set of divs that functions like a slide show. I have been searching for a solution but haven't found one yet. Is there a way to make the commented-out div scrollable by clicking somewhere on the page or an arrow image? I wa ...

The modal popup will appear in the center of the screen when the scrollbar is positioned at the top

I have a modal popup that is not consistently displayed in the center of the screen, regardless of the scrollbar position. I always want it to render at the center so the user doesn't need to scroll to see it. Below is the code I am currently using: ...

Enhancing the styling of checkboxes using CSS and Javascript

My Javascript skills have been put to the test with a simple code snippet that customizes checkboxes by hiding them and using background images in CSS to display checks and unchecks. It's a neat trick, but I'm wondering if it's HTML/CSS comp ...

Creating a banner image that scrolls while maintaining a fixed size

I'm looking to add a banner image with a scrolling effect as users navigate down the page, but I'm not sure what this technique is called. An example of what I'm trying to achieve can be seen on this site. As the user scrolls down, the res ...

Attempting to design the appearance of the form fields within a Mat-Card

As someone new to UI development and lacking in-depth knowledge of css, I have been searching for examples to style a login page using Angular Material. My main struggle right now is getting the form fields to expand the width of the card (minus the paddin ...

Unusual marking on the navigation bar

Currently, I am making updates to a website that was created by a previous employee long before I joined the team. One of the requested changes is to eliminate the orange box surrounding the navigation links. The navigation appears to be generated using Ja ...

Attempting to create a div element that automatically adjusts itself horizontally in the center through the utilization of margins

I searched through examples on stack overflow that had similar problems to mine, but unfortunately, I couldn't find a solution. I'm not sure what I'm doing wrong, but the div is not aligning horizontally center as expected. It seems to work ...

Update the appearance of a cell if the value within it is equal to zero

I have discovered a way to achieve this using inputs. input[value="0"] { background-color:#F7ECEC; color:#f00;} Now, I am looking for assistance in applying the same concept to table cells. Can anyone provide guidance? Thank you. ...

What is the best way to incorporate code into a page with numerous conflicting CSS styles, without resorting to Scoped CSS?

Struggling to incorporate tab code into a page with conflicting CSS? Even after attempts to edit classes and labels, the original code fights back against the new additions. While scoped CSS seems like the perfect fix, it's not widely supported yet. ...

The frosting glass effect blur filter is malfunctioning, resulting in no blurring effect and affecting the content

I need help achieving a background photo with a div in front, featuring a blurry dark background with white text. Currently, the setup shows a dark background without blur and dark text. Can someone please assist me? #section0 { background-color: light ...

Creating rounded corners in Firefox can result in a gap between the border and the background

I'm trying to round the corners of a div, but in Firefox there seems to be an issue with whitespace between the border and background color. Check out my demo fiddle. <div>&nbsp;</div> div { margin: 20px; width: 250px; ...

Tips for incorporating a CSS class representing an image into a CodeIgniter form submission

<?php $data = array( 'class' => "btn btn-primary btn-lg", 'name' => 'report' ); echo '<span class="glyphicon glyphicon-exclamation-sign"></span> '; echo form_subm ...

Designing a photo frame slider for a unique touch

My skills in javascript and jQuery are limited, but I am looking to create a customizable slider. While exploring options like Flexslider (), I found it challenging to meet the following specifications: Eliminate color gaps between thumbnails Enable thu ...

Troubleshooting Bootstrap 5 Navbar Customization Problem: Vertical Display Instead of Horizontal Viewing

My current challenge involves customizing a Bootstrap 5 navbar to arrange three elements - a user avatar, a notifications panel, and a menu icon - in a horizontal layout. Despite my efforts, these elements are appearing in a vertical stack instead of horiz ...

How can I eliminate the tiny white square located beneath the scrollbar track?

`::-webkit-scrollbar{ width: 12px; } body::-webkit-scrollbar-track{ background: #f1e9e9; border-radius: 10px; margin-block: 0.1875rem; } ::-webkit-scrollbar-thumb{ background-color: #582965; border-radius: 10px; border: 3px so ...

The iOS platform is experiencing issues with displaying the entire page, making it difficult to

Struggling with my website for Freecodecamp. Works fine on desktop, but iOs is a nightmare. My contact page isn't showing at all, and 75% of the bottom is cut off. Even worse, I can't click on what's visible. Help needed! Only tested on iPho ...

Ways to arrange and space out td values

Here is an example of my HTML table: <table> <tr> <td>123 - 20 - 20</td> </tr> </table> The numerical values in the table are retrieved from a database and displayed like in this image: https://i.sstatic.net/ ...

resizing videos in wordpress

Similar Question: How to Resize Embedded Videos Using PHP I am looking to adjust the dimensions of videos to be 280 pixels in height and 520 pixels in width on my WordPress homepage. Currently, the code is using the original YouTube dimensions: ...