Wordpress - Enqueue core jQuery in the footer?

Here's another option which avoids having to de-register and re-register:

/**
 * Move jQuery to the footer. 
 */
function wpse_173601_enqueue_scripts() {
    wp_scripts()->add_data( 'jquery', 'group', 1 );
    wp_scripts()->add_data( 'jquery-core', 'group', 1 );
    wp_scripts()->add_data( 'jquery-migrate', 'group', 1 );
}
add_action( 'wp_enqueue_scripts', 'wpse_173601_enqueue_scripts' );

This solution mimics WordPress core by setting the group to 1, which is how WordPress determines if a script should be in the footer or not (I'm not aware of the reasoning for 1, as @jgraup noted in the comments it seems a bit arbitrary).


To do that you will first have to deregister your jQuery script and then register again. If you use jQuery comes with WordPress then following is the function your are looking for.

function starter_scripts() {
    wp_deregister_script( 'jquery' );
    wp_register_script( 'jquery', includes_url( '/js/jquery/jquery.js' ), false, NULL, true );
    wp_enqueue_script( 'jquery' );

    wp_enqueue_style( 'starter-style', get_stylesheet_uri() );
    wp_enqueue_script( 'includes', get_template_directory_uri() . '/js/min/includes.min.js', '', '', true );
}
add_action( 'wp_enqueue_scripts', 'starter_scripts' );

If you use Google CDN hosted version of jQuery then let me know I will modify this code for Google CDN URL.


A better solution:

add_action( 'wp_default_scripts', 'move_jquery_into_footer' );

function move_jquery_into_footer( $wp_scripts ) {

    if( is_admin() ) {
        return;
    }

    $wp_scripts->add_data( 'jquery', 'group', 1 );
    $wp_scripts->add_data( 'jquery-core', 'group', 1 );
    $wp_scripts->add_data( 'jquery-migrate', 'group', 1 );
}

Why its better then the accepted answer IMO

  1. Changes it at the very core not at a later stage where other things might already messed with it.
  2. The version string it kept in place and not removed!
  3. It does not unregister and reregister a script but it just sets the group value that is essentially the same as if the script would be registered with $footer = true.

About not doing this to the admin

If plugins add inline jquery to the wp_head it will fail when jquery is not loaded at that point, so I suggest you avoid that until you have millions editing your site and you try to performance optimize your admin. This is true for frontend as well so you should watch out for bad coded themes or plugins that assume jquery in the head by using inline jQuery code. WP and plugins register other scripts to the admin head with jquery in deps so it would not work anyway I think.

About it not working

You need to be aware that if any other script is loaded to the head that has jQuery in its dependencies, it will also make jQuery load in the head right before itself. And this is good and expected, the reason the wp_enqueue system exists. This means you will learn soon if you use a few plugins that one of them will require cause jquery to the head. It the the default for enqueued scripts, sadly.

Radical Solution

I think it will brake any inline JS that assumes jquery but should that should be rare. This will force all scripts to the footer regardless of how they are enqueued.

add_action( 'wp_enqueue_scripts', 'js_to_footer' );

function js_to_footer() {
  remove_action( 'wp_head', 'wp_print_scripts' );
  remove_action( 'wp_head', 'wp_print_head_scripts', 9 );
  remove_action( 'wp_head', 'wp_enqueue_scripts', 1 );
}