• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
NameHero Blog

NameHero Blog

Web Hosting Tips & Resources From NameHero

  • Web Hosting
  • Reseller Hosting
  • Managed Cloud
  • Domains
  • Account
  • Blog Home
  • Categories

How To Inline And Defer CSS On WordPress Without Plugins

Bhagwad Park

Published on: December 5, 2018

Categories: Showcase, WordPress 25

Knowing how to inline and defer CSS on your WordPress site is a vital part of improving the viewer experience. While it doesn’t improve your page load time, it makes a huge difference to how the user perceives the page to load.

Normally, all externally linked CSS stylesheets are render-blocking. Which means that the browser doesn’t proceed until they’ve been downloaded. So it’s a best practice to defer them (not the same “defer” as with Javascript though). Unfortunately, this has some side effects that we need to take care of.

This tutorial will show you how to:

  1. Generate critical CSS
  2. Defer CSS stylesheets
  3. Inline the critical CSS from Step 1

So let’s go.

Step 1: Generate Critical CSS

The importance of this step will become evident after step 2. For now, just visit a site like like, enter your site’s URL or page, and click “Generate Critical Path CSS”. The tool will scan your website and eventually give you a blob of text like this:

Copy Critical CSS

Copy this and keep it safe. We’ll use it later.

Step 2: Defer CSS Stylesheets

Most CSS in WordPress is (and should be) enqueued properly using the “wp_enqueue_style” function. This will place a <link> element in the head that looks like this:

CSS Files Without Preload

As mentioned earlier, this CSS stylesheet is render blocking. If you plug your page into a tool like Google’s PageSpeed insights for example, it’ll complain that a lot of stuff is preventing the page from displaying – and those tools will be right.

About the rel=’preload’ Attribute

To solve this problem, browsers have started supporting the “preload” attribute for resources like scripts. Basically, it tells the browser that the resources marked in this manner can be downloaded simultaneously in the background and that they’re not terribly important for page loading.

Of course, that’s not true. The CSS stylesheets are important. They define how your site looks after all! But for the moment, we’re interested in using the “preload” attribute value to defer our external stylesheets.

You can do this by inserting the following code into your WordPress’s functions.php file:

function add_rel_preload($html, $handle, $href, $media) {
    
    if (is_admin())
        return $html;

     $html = <<<EOT
<link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='$handle' href='$href' type='text/css' media='all' />
EOT;
    return $html;
}
add_filter( 'style_loader_tag', 'add_rel_preload', 10, 4 );

After you save your changes, your CSS stylesheets will have the “preload” tag attached to them like this:

CSS is Preloaded

Great right? Not so fast!

Step 3: Panic As your Site Breaks

Unfortunately, running the above code makes your site “unstyled” like this:

But the Page is Doesnt Display

This is because the CSS styles with “preload” haven’t been applied since the page went ahead and rendered without them. This is where the “critical” CSS from Step 1 comes in.

The “critical CSS” refers to only those CSS rules that apply to the “above the fold” content – namely the content that’s visible when your page first loads. This is typically a very tiny subset of the actual CSS contained in all the stylesheets.

In Step 1, we generated this critical CSS, and we need to insert it into the <head> of our webpage with following code:

function hook_css() {
    ?>
           [insert critical css here]
    <?php
}
add_action('wp_head', 'hook_css');

Replace [insert critical css here] with the code you copied from Step 1.

Note that this must include the <style></style> tags around it. If you’re using a different tool, it might just give you the CSS rules without the <style> opening and closing tags. Make sure you add them!

Once you’ve done this, your page will load normally and look the same. With the important difference that all your stylesheets are loading in a deferred manner! Say hello to fast page load speed scores!

Bhagwad Park Profile Picture
Bhagwad Park

I’m a NameHero team member, and an expert on WordPress and web hosting. I’ve been in this industry since 2008. I’ve also developed apps on Android and have written extensive tutorials on managing Linux servers. You can contact me on my website WP-Tweaks.com!

Reader Interactions

Comments

  1. Zach says

    February 5, 2019 at 2:34 pm

    Hey there,
    Really interesting method to remove CSS render-blocking. An issue with the function though, it only works for the home page. The critical path CSS I copied into the head only works for the home page. So other pages still break and even after page loading is complete, the layout is broken.

    Could the function and method be improved to include conditional logic so I can target pages on an individual basis? Or even better, on a template by template basis?

    Reply
    • Bhagwad Park says

      February 20, 2019 at 11:42 am

      It’s possible, but I would suggest just including ALL the critical CSS inline – even for those pages that don’t need it.

      What you’re suggesting is valid in theory, but in practice it would require a LOT of maintenance. And each time you make a change like adding a plugin, changing a theme, or even styling a table, you would need to make modifications to your code. This would quickly become unmanageable.

      Given the small size of text, the performance benefits would be truly minuscule – so small, that I doubt they could even be measured. So if I were you, I would gather all the critical CSS from all my site’s pages in one blob and paste them for all pages.

      Reply
  2. David Elstob says

    June 9, 2019 at 6:50 am

    If you use Fast Velocity Minify – some prefer Autoptimize – you can inline all your CSS in the header or header and footer. As long as the file size in the header is no more than 50 – 60 kb you are good. No need to worry about critical CSS.

    Obviously it’s better to deffer unused style rules, but if you’re within this limit then the benefits aren’t worth the hassle.

    AMP has a 50 kb CSS limit for same reason.

    Reply
    • Dragan says

      November 16, 2020 at 10:53 am

      Hello David,
      I’m amateur, with no previous knowledge or experience with website building nor wordpress or something but I’m leraning little by little. I have a question with Fast Velocity Minify and what to do with CSS or JS processed files.
      – /wp-content/plugins/elementor/assets/xxx.css
      – /wp-content/plugins/woocommerce/assets/js/xxx.js
      Should I exclude or include any of them or what ? Honestly I haven’t ask on WP forum since I started with FVM recently and then I noticed this blog and topic that I was looing for. Thank you in advance. Cheers and take you all care! Dragan

      Reply
  3. Manish Vadnathani says

    September 10, 2019 at 3:52 am

    I’m having little problem with this technique. I’m using W3 Total cache plugin, As I load my critical css before loading any css and js, Critical css works fine but My Combined CSS Files doesn’t load combinely, they load separately. So my http requests increases from 29 to 45. This technique works but i don’t know how to load my combined css files after putting critical css first in the header.

    Can anyone please tell me why that’s happening? and give me a solution if possible 🙂

    Reply
  4. Egan says

    January 12, 2020 at 12:25 am

    I’m personally use AO for my website. The interface seems more friendly for me instead fvm. Unfortunately AO does not have feature for defer some assets, but they have preload and preconnect. I got 85 – 89 score in PageSpeed and thats more than enough since the page below 500kb. The real problem i need to solve is the Ads.

    Reply
  5. Philip says

    February 4, 2020 at 9:37 am

    Is there a way to defer a single stylesheet instead of all stylesheets?

    Reply
    • Bhagwad Park says

      February 5, 2020 at 12:26 pm

      You’ll need to modify the code with an “if” condition to check for the specific style tag that you want to defer.

      Reply
    • Rémi Meullemeestre says

      May 14, 2020 at 8:28 am

      You can.
      I personnaly did it like that so far :

      function add_style_attributes( $html, $handle ) {

      if ( ‘bootstrap’ === $handle ) {
      return str_replace( “media=’all'”, “media=’all’ integrity=’sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T’ crossorigin=’anonymous'”, $html );
      }
      if ( ‘fontawesome’ === $handle ) {
      return str_replace( “media=’all'”, “media=’all’ integrity=’sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr’ crossorigin=’anonymous'”, $html );
      }
      return $html;
      }

      add_filter( ‘style_loader_tag’, ‘add_style_attributes’, 10, 2 );

      In this exemple, I also add the integrity and crossorigin attributes that the regular enqueue script does not handle by default.

      Hope it helps.

      Reply
  6. Martin says

    March 21, 2020 at 3:09 pm

    Hi,

    the above code doesn’t work – if uploaded in the functions.php, it results in string errors. Suggest this to be checked, so it can be used.

    Thanks!!
    Martin

    Reply
    • Bhagwad Park says

      March 23, 2020 at 12:11 am

      Hi Martin,

      Could you share the exact error you’re getting when you add the code along with the line number if possible, and the exact code you’re using?

      Reply
  7. Martin says

    March 24, 2020 at 6:23 pm

    Hey,
    sure: I am using exactly your code snipped that you highlight above for the functions.php and pasted it in the functions.php of my child theme folder.

    The resulting error: Parse error: syntax error, unexpected end of file in /XXX/XXX/XXX/wp-content/themes/mindfulness/functions.php on line 552

    Reply
  8. Ryan Pearson says

    May 2, 2020 at 4:03 pm

    I’m having an issue in Firefox with this code. With Chrome, Safari, Opera and Edge, this code correctly works, and loads the css files after the page has rendered.

    However, with Firefox, this code is preventing the CSS files from loading at all.

    Has anyone else experienced this problem?

    Reply
    • Remondo says

      May 13, 2020 at 12:00 pm

      I have the same issue, my styles aren’t fonctional withing Firefox, plus, my nagivation is not even displayed in Chrome on top. Beside that, I also encounter various issues with img sizes on the front page, and, I presume, in other pages as well.

      In short, it might be an interesting solution, because yes, the Chrome audits tells me it indeed remove most of the render-blocking CSS assets, but in the end it’s definitely not fully fonctionnal for my case, so I guess I will try another method or will just simply let them the way the behave initially.

      Reply
  9. Denish says

    May 3, 2020 at 9:10 am

    Thanks, this is great!

    Reply
  10. apmeyer says

    July 10, 2020 at 9:40 am

    As noted above, this isn’t playing nice with Firefox.

    Reply
  11. Pereceh Internet says

    July 10, 2020 at 10:06 pm

    it’s better to just defer javascript than defer css.

    Reply
  12. Squivo says

    July 15, 2020 at 1:39 am

    This works fine in FF for me – just need to follow the more detailed guidelines here: https://web.dev/defer-non-critical-css/

    and also, instead of adding the critical.css in wp_head, it’s better to carve out a case in the style_loader_tag where:

    if ( strpos( $href, ‘themes//critical.css’ ) ) return $html;// Make sure this loads and is not deferred

    Reply
  13. Squivo says

    July 21, 2020 at 3:55 pm

    I lied by the way ( caching is hard ) : FF sucks… you have to include a clause to return based on HTTP_USER_AGENT ( if Firefox, don’t mess with the script_tag )

    Reply
  14. Q says

    September 25, 2020 at 3:45 am

    There are several solutions for FF, but the easiest is to add something like:

    rel=”stylesheet preload”

    which works as a fall-through, for browsers which do not support preload.

    Reply
  15. Bryan Veloso says

    February 18, 2021 at 1:16 am

    Pagespeed optimisation really takes time. Thanks for sharing this stuff, it’s quite useful. Less plugin, less bloat.

    Reply
  16. Thomas Vav says

    March 22, 2021 at 2:01 am

    Hello and thank you for this guide.
    Unfortunately something is wrong with my setup.

    I have installed both codes to my site (1st part with preload at the functions.php file and 2nd part with thefunction hook_css code at the header), but when I reload my site, I get a phrase appearing at my homepage, at the top left corner. This includes a few words from the function command.

    Why is this happening and how to fix it?

    Reply
  17. Giuseppe Mastrangelo says

    April 27, 2021 at 11:49 am

    Hi man! Thanks for your precious post, so useful! I would have a question: where have I to insert the inline css? In which php files? In the function as well?

    Thanks,

    Giuseppe

    Reply
  18. Rodolfo Alexander says

    June 22, 2021 at 1:43 pm

    defer code loads everywhere. Is there any way to make it load only in single pages? I tried everything but couldn’t make it work. It will be huge help if you can help me defer stylesheets in posts only.

    Reply
  19. quinqui says

    October 7, 2021 at 2:57 pm

    Thank you very much for the tip. I’ve just started working on WordPress, and it has been tough to me, since I’m a programmer who likes to build every inch of my development, hahaha! Now I’m looking for solutions to fix WP jams with no plugins involved, and your tip was just what I wanted! It worked fine at my work’s website. Thanks again! Greetings from Chile ^_^

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Primary Sidebar

Follow & Subscribe

Exclusive promos, content and more!

Most Popular Posts

NameHero’s Recommended WordPress Plugin and Theme Setup (2023)

How To Increase The InnoDB Buffer Pool Size

How To Fix A Stuck All-in-One WP Migration Import

How To Add A Subdomain In Cloudflare

How To Inline And Defer CSS On WordPress Without Plugins

Top Categories

  • WordPress
  • Website Performance
  • Web Hosting
  • Resellers
  • Website Security
  • VPS Hosting
  • Website Development
  • SEO Tips
  • Announcements
  • Domain Registration
NameHero

NameHero proudly provides web hosting to over 40,000 customers with 99.9% uptime to over 750,000 websites.

  • Master Card
  • Visa
  • American Express
  • Discover
  • Paypal
Name Hero
  • Web Hosting
  • Reseller Hosting
  • Managed Cloud
  • Domains
Help & Support
  • NameHero Blog
  • Knowledgebase
  • Announcements
  • Affiliates
Company
  • About Us
  • Contact Sales
  • Reviews
  • Uptime
  • We're Hiring

Copyright © 2023 NameHero, LLC. All rights reserved.

  • Privacy Policy
  • Terms of Use
  • Acceptable Use Policy
  • Payment Policy
  • DMCA