I'm working on a script to easily move js and css scripts to the footer using the add_data function in $wp_scripts and $wp_styles. I know for scripts that if the group is greater than 0 the script call will be moved to the footer (first foreach below does that). However, setting the group for styles doesn't have the same effect (and group is set properly with second foreach). Is there a way to move styles to the footer with the same method, or should I be looking for an alternative?

function mod_scripts(){
    global $wp_scripts, $wp_styles;
    foreach($wp_scripts->queue as $script){
        if ( ! $wp_scripts->get_data( $script, 'group' ) ){
            $wp_scripts->add_data( $script, 'group', 1 );
        }
    }
    foreach($wp_styles->queue as $style){
        if ( ! $wp_styles->get_data( $style, 'group' ) ){
            $wp_styles->add_data( $style, 'group', 1 );
        }       
    }
}

EDIT: The reason for the request is that I'm trying to remove blocking css to make a page load faster. The recommended method is basically to just embed the css directly into the page, but that's never worked out well. And now I realize that the question as I asked it is flawed. I'm just looking for an effective way to load styles that still maintains proper compatibility with plugins.

up vote 5 down vote accepted
+50

I don't know what your exact reason is for this, but you should scrap the idea of moving styles to the footer. If you though of a gain in speed, you might gain a unnoticable amount, if any, but that will be at the cost of other bigger things.

Styles should always be added inside the <head></head> tag. The reason is that <style> tags outside the head tags are invalid HTML. That is why you don't have that option to load styles in the footer with wp_enqueue_style and wp_register_style like you have with scripts.

I would seriously rethink this whole idea.

EDIT

As a sidenote from a comment to this answer from @G.M.

wp_enqueue_style add <link> tag, not <style> one. However, <link> tag is not allowed outside <head> too

  • I agree with you, the reason is unclear. I guess there's also a valid reason why there's no $in_footer argument for wp_enqueue_style? I also wonder what w3c validation says about using <link> tags outside the <head> tag. – birgire Sep 25 '14 at 10:30
  • That is quite interesting questions, specially the one about link tags – Pieter Goosen Sep 25 '14 at 10:36
  • Thanks for your response Pieter. I'm going to add something to the question. – Jeremiah Prummer Sep 25 '14 at 13:52
  • I appreciate your answer and I'm going to go back and look into some other options for this. – Jeremiah Prummer Sep 25 '14 at 14:04
  • Do you have a specific compatibility issue? Remember, you can load styles and scripts conditionally which might be a way to go here – Pieter Goosen Sep 25 '14 at 14:24

As @pieter-goosen and @birgire in other answer and comments, W3C specs do not allow css in footer, quote from specs page linked:

A link element must have a rel attribute.

If the rel attribute is used, the element is restricted to the head element.

Aside from that, you should note that when you add css in footer, when someone opens your page it appears unstyled until the full css is loaded: with slow connections your page will appear broken for some seconds, elements hidden via css will be visible, sliders appear like ul lists of visible images...

So, really, I think it's a bad idea.

That said, I don't like the "don't do that" kind of answers, I prefer the "you can do that in this way, but I suggest don't do that" kind.

So, here the way to do that, but hey, I suggest to don't do that.

Things are more easy as you can expect: scripts and styles should be added on wp_enqueue_scripts hook, but if you enqueue styles after wp_head hook has been fired, then scripts and styles are added in the footer.

An useful application of that is when scripts are enqueued inside a shortcode callback, adding possibility to add shortcode-specific scripts with ease.

Regarding styles, WordPress is not intransigent about W3C statements and will put styles on footer unblinkingly.

Workflow:

  1. hook 'wp_print_styles', when all scripts and styles are already enqueued, but not printed
  2. store current queue for scripts and styles in variables
  3. empty the queue for both scripts and styles, in this way, when WordPress look to print scripts and styles in head will find nothing to print
  4. hook 'wp_footer' with priority 0, and restore the styles and scripts queue you stored at point #2, in this way, when WordPress look for styles and scripts to print in footer can find and print them.

All can be done in few lines of code:

add_action('wp_print_styles', function() {
  if ( ! doing_action( 'wp_head' ) ) { // ensure we are on head
    return;
  }
  global $wp_scripts, $wp_styles;
  // save actual queued scripts and styles
  $queued_scripts = $wp_scripts->queue; 
  $queued_styles  = $wp_styles->queue;
  // empty the scripts and styles queue
  $wp_scripts->queue = array();
  $wp_styles->queue  = array();
  $wp_scripts->to_do = array();
  $wp_styles->to_do  = array();
  add_action( 'wp_footer', function() use( $queued_scripts, $queued_styles ) {
    // reset the queue to print scripts and styles in footer
    global $wp_scripts, $wp_styles;
    $wp_scripts->queue = $queued_scripts;
    $wp_styles->queue  = $queued_styles;
    $wp_scripts->to_do = $queued_scripts;
    $wp_styles->to_do  = $queued_styles;
  }, 0 );
}, 0);

Note

Code above require PHP 5.3+ for the usage of closure and WP 3.9 for the usage of doing_action.

  • This is awesome. I appreciate the answer given and definitely agree that there are issues with loading css in the footer. But, this is useful for instances when the css file is non-critical for elements that are displayed above the fold. – Jeremiah Prummer Sep 25 '14 at 16:20

I was recently researching this very question specifically because of the requirement from Google PageSpeed Insights:

Eliminate render-blocking JavaScript and CSS in above-the-fold content

Your page has 1 blocking script resources and 1 blocking CSS resources. This causes a delay in rendering your page.

None of the above-the-fold content on your page could be rendered without waiting for the following resources to load. Try to defer or asynchronously load blocking resources, or inline the critical portions of those resources directly in the HTML.

Optimize CSS Delivery of the following:
.../style.min.css?ver=4.8

Google's recommendation was to embed critical CSS using an inline <style>...</style> block in the <head>...</head> and load non-critical CSS via JavaScript.

I wasn't able to figure out how to use WordPress's native functions to enqueue a native style block without first requiring an external stylesheet (see: wp_add_inline_style. So, I just completed the task using my own custom header.php and footer.php template files:

header.php

<!-- ... -->
  <?php wp_head(); ?>
  <style id="critical-styles" type="text/css" media="screen">html { background: black; } body { opacity: 0; }</style>
</head>
<!-- ... -->

footer.php

  <!-- ... -->
  <noscript id="deferred-styles">
    <link rel="stylesheet" type="text/css" href="<?php echo get_stylesheet_directory_uri() . '/style.min.css?' . urb_get_version(); ?>" />
  </noscript>
  <script>
    var loadDeferredStyles = function() {
      var addStylesNode = document.getElementById('deferred-styles');
      var replacement = document.createElement('div');
      replacement.innerHTML = addStylesNode.textContent;
      document.body.appendChild(replacement)
      addStylesNode.parentElement.removeChild(addStylesNode);
    };
    var raf = requestAnimationFrame || mozRequestAnimationFrame || webkitRequestAnimationFrame || msRequestAnimationFrame;
    if (raf) raf(function() { window.setTimeout(loadDeferredStyles, 0); });
    else window.addEventListener('load', loadDeferredStyles);
  </script>
  <?php wp_footer(); ?>
</body>
</html>

Note: My critical style block includes: body { opacity: 0; } as a way to hide un-styled content. Once my deferred stylesheet is loaded, it includes body { opacity: 1; } to clear this attribute with a transition.

The page load speed is probably beeing affected by other requests.
Like Pieter Goosen said you are probably not going to notice the difference.
To prove that: Remove those scripts requests and check the difference on the page load.

With the Firefox or Google Chrome Developer Tools you can easily check all the requests, and see which ones are slowing down your site.

Speed up page load:

  • check SQL queries and optimize them
  • minify scripts
  • use a cache plugin
  • ...

Cheers

Regardless of suggestions for not loading CSS on footer (and I agree with that) if you really need to load your CSS on frontend's footer then the simplest way is to hook the enqueue function on the wp_footer hook (or admin_footer in case of Admin) where you will enqueue your stylesheets:

// change these variables to fit your needs
$handle = 'my-css';
$css_url = plugins_url( 'plugin_style.css', __FILE__ );
$priority = 10; // make it 9999 if you want to enqueue it just before </body>

add_action('wp_footer','enqueue_my_styles', $priority);

function enqueue_my_styles(){
    wp_enqueue_style( $handle, $css_url);
}

Actually, the rationale behind the idea of FULL css should be put at the bottom (footer) and loaded lastly is quite complicated.

It began with "how to do business" (MONEY), found out from Google's researches that if [mobile] users have to wait for more than 3 seconds for a webpage to be rendered, they will "abandon their carts and walk away" --> websites will lose like xxx percent of profit. The researches are here: https://think.storage.googleapis.com/docs/mobile-page-speed-new-industry-benchmarks.pdf

https://www.thinkwithgoogle.com/marketing-resources/data-measurement/mobile-page-speed-new-industry-benchmarks/

more referece: https://developers.google.com/speed/docs/insights/mobile https://www.thinkwithgoogle.com/feature/mobile-app-user-demographics/#/

From the research(es), they came to the conclusion(s) that webpages must be able to deliver THE FIRST RENDER (and so, "above the fold content" -- AFT) within the FIRST second to be able to NOT loose visitors (and so financial benefits). This is particular for MOBILE sites, but the same (at somewhat lesser degree) would also be true for "desktop sites".

From the conclusions obtained from the researches, they develop the principles and implementations to OPTIMIZE "the way/order webpages should be rendered" in order to have the maximum benefit and to keep as many visitors as possible (to loose as fewer visitors as possible, for more exactly).

That's how (according to Google) websites should only have essential resources (CSS, JS) included in the header: to deliver the AFT content as fast as possible towards the ideal time of ONE second for the delivery of the AFT content. All the remaining resources (FULL CSS, FULL JS, etc.) should be loaded BEHIND THE SCENE while the AFT content is being delivered to visitors within the first second to keep them stay on the webpage.

That's how and why they promote the method. Remember that, websites' benefit is also Google's benefit: if websites loose too many visitors (53% if they have to wait for more than 3 seconds, according to the researches), they will loose financial benefit; if websites loose financial benefit, Google will loose their own financial benefit too -- it's mutual benefit. And the researches are for mobile sites, for "desktop sites", the effects would be somewhat lesser -- but still exits!

You may agree with me, and with Google, or not! You may have a better/different way to do business as well!

All the bests!

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.