Frauds
Frauds

Reputation: 137

How to eliminate render blocking resources (app.css)?

enter image description here

I'm testing the performance of the web that I created. I tried to use Google's Page Speed ​​and GT Metrix. In each application different performance results.

I'm trying to see the results in Top Issue GT Matrix, there is a problem with rendering resources in app.css. I've tried to work around this by using the code below the initial render results are not very good to look at.

Can anyone help me how to handle this?

<link rel="stylesheet" href="http://103.148.190.87/css/app.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript>
  <link rel="stylesheet" href="http://103.148.190.87/css/app.css">
</noscript>

Upvotes: 4

Views: 15952

Answers (3)

Tim Bednar
Tim Bednar

Reputation: 136

Okay, critical CSS is hard. It is hard to implement, test, and then keep up to date. So if you don't want to do that work, you do have some options. The CSS file is still render-blocking, but you can mitigate its impact.

As suggested, make your app.css file as lean as possible by removing unused CSS (i.e. if you're using a framework only include the parts you use). But don't get hung up here.

Then preload the stylesheet in the head. Don't worry about pre-connect or pre-fetch -- just preload it.

https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload

Then I'd make sure any images that are in the viewport have a loading="eager" attribute (may or may not be imporant) AND importantly are preloaded as well.

You can still get a fast FCP/LCP on desktop and mobile even with no critical CSS and even if most of your rules are unused. You can see an example with my app here (which by the way might be able to help you).

https://waterfaller.dev/?url=https://waterfaller.dev/

The idea is to make sure that any files you do load before LCP are few, fast, and small. Then you can avoid messing around with critical CSS.

Upvotes: 1

GrahamTheDev
GrahamTheDev

Reputation: 24935

Understanding what a "render blocking resource" is.

When a browser requests your page it needs the HTML and CSS for any content that appears "above the fold" before it can render it correctly.

"Above the fold" is essentially any content that is visible on the screen without scrolling.

Critical CSS is all of the CSS required to render the above the fold content.

If your site happens to be rendered with JS then you also need to employ a similar technique as I describe below for the JS required to hydrate / render the initial page content. However this answer is focused on CSS (the principles are the same, just the methods are different).

Why does it matter?

If you have your styles in an external style sheet the browser has to do the following:

  1. Download the HTML for the page.
  2. Look to see what styles are required to render the above the fold content.
  3. Download the styles that are required
  4. Once the styles are downloaded the content can be rendered.

Those extra network requests for the CSS can really slow the page down if someone has a high latency connection (4G for example where the round trip time to the server can be 300ms and higher).

What we instead want to do is provide all of the styles required to render the above the fold content immediately so that no further network requests are required.

Steps to fix

The principle is simple, however it can be quite difficult to get right and may take a bit of patience.

Identify Critical CSS

There are numerous ways you can do this but they often depend on your build process, stack etc.

In principle though you are looking for a tool that will map the HTML that is above the fold to the CSS classes and styles that match those items. The tool should then export these styles for you.

Unfortunately I have yet to see a tool that is 100% effective at this so I would suggest you use a tool to grab most of the styles and then (after inlining the critical CSS - see below) remove all external style sheets and see if there are things that do not render correctly. Inspect them on a page with the external CSS included and copy the styles across.

It can be laborious if you haven't designed the site with this in mind but is worth it.

Inlining Critical CSS

Once you have identified the critical CSS you simply inline it.

This just means that you minify it and then add it to your site inside a <style> tag at the top of the page.

This goes back to the part I was saying in the introduction. Once you inline all the styles the browser has everything it needs to render the page without another network request. This massively helps your First Contentful Paint, Largest Contentful Paint (normally) etc.

Deferring none critical CSS

Now that you have inlined the critical CSS you only have two steps left:

  1. Remove the critical CSS from your style sheet - there is no point downloading it twice!
  2. Use the method you showed within your original question:
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>

Here's how it works:

  • link rel="preload" as="style" requests the stylesheet asynchronously. You can learn more about preload in the Preload critical assets guide.
  • The onload attribute in the link allows the CSS to be processed when it finishes loading.
  • "nulling" the onload handler once it is used helps some browsers avoid re-calling the handler upon switching the rel attribute.
  • The reference to the stylesheet inside of a noscript element works as a fallback for browsers that don't execute JavaScript.

Taken from https://web.dev/defer-non-critical-css/

Pseudo example

Just to make this clear, let's assume we have a website with a simple hero section that appears above the fold. There are only three CSS classes required to make this hero section work so we inline the CSS for it.

<style>
.hero{
   min-width: 100%;
   height: 100vh;
   background: #333;
}
.hero h1{
  position: relative;
  float: left;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
}
section{
    width: 75%;
    margin: 0 auto;
    padding-top: 20px;
}
</style>

We then load the rest of the CSS using the method you described:

<link rel="preload" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
    <noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"></noscript>

Quick example

<!-- normal styles that appear below the fold -->
<link rel="preload" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"></noscript>

<!-- all styles required for above the fold -->
<style>
.hero{
   min-width: 100%;
   height: 100vh;
   background: #333;
}
.hero h1{
  position: relative;
  float: left;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
}
section{
    width: 75%;
    margin: 0 auto;
    padding-top: 20px;
}
</style>

<!-- above the fold -->
<section class="hero">
   <h1>Above the fold - all required styles inlined</h1>
</section>

<!-- below the fold -->
<section class="below">
<h2>Below the fold, all classes in external style sheet</h2>
<p class="lead">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. </p>

<p>Sed dignissim lacinia nunc. Curabitur tortor. Pellentesque nibh. Aenean quam. In scelerisque sem at dolor. Maecenas mattis. Sed convallis tristique sem. Proin ut ligula vel nunc egestas porttitor. Morbi lectus risus, iaculis vel, suscipit quis, luctus non, massa. Fusce ac turpis quis ligula lacinia aliquet. Mauris ipsum. </p>

<p>Nulla metus metus, ullamcorper vel, tincidunt sed, euismod in, nibh. Quisque volutpat condimentum velit. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam nec ante. Sed lacinia, urna non tincidunt mattis, tortor neque adipiscing diam, a cursus ipsum ante quis turpis. Nulla facilisi. Ut fringilla. Suspendisse potenti. Nunc feugiat mi a tellus consequat imperdiet. Vestibulum sapien. Proin quam. </p>

<p class="h4">Etiam ultrices. Suspendisse in justo eu magna luctus suscipit. Sed lectus. Integer euismod lacus luctus magna. Quisque cursus, metus vitae pharetra auctor, sem massa mattis sem, at interdum magna augue eget diam. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Morbi lacinia molestie dui. Praesent blandit dolor. Sed non quam. In vel mi sit amet augue congue elementum. Morbi in ipsum sit amet pede facilisis laoreet. Donec lacus nunc, viverra nec, blandit vel, egestas et, augue. Vestibulum tincidunt malesuada tellus. Ut ultrices ultrices enim. </p>

<p>Curabitur sit amet mauris. Morbi in dui quis est pulvinar ullamcorper. Nulla facilisi. Integer lacinia sollicitudin massa. Cras metus. Sed aliquet risus a tortor. Integer id quam. Morbi mi. Quisque nisl felis, venenatis tristique, dignissim in, ultrices sit amet, augue. Proin sodales libero eget ante. Nulla quam. Aenean laoreet. </p>


</section>

Upvotes: 13

Keimeno
Keimeno

Reputation: 2659

Your only viable option would be to minify your app.css file, or remove code that is unused.

CSS files are always render blocking because you wouldn't want to see a site that doesn't have any CSS, even for a moment.

Also, another tip: You can use https for your website, compression methods such as brotli or gzip to further minimize the load. Also, you can use HTTP/2, which works faster when loading multiple resources.

Upvotes: 0

Related Questions