Question

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.

Was it helpful?

Solution

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

OTHER TIPS

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.

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.

I'm going to echo the other answers on here that say you probably shouldn't put styles in the footer without a good reason. However, I just had to do this on a site where a plugin inserted styles inside the body tag, so I wanted to share how I added styles in the footer.

<?php
function print_footer_styles() {
    $style_handle  = 'footer-styles';
    wp_register_style( $style_handle, get_template_directory_uri() . '/css/footer-styles.css' );
    wp_print_styles( array( $style_handle ) );
}

add_action( 'wp_footer', 'print_footer_styles' );

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!

Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top