12% off of LTD using this coupon: TWELVEPERCENTOFF. Promo ends on 2 Dec midnight UTC.
Published on Feb 26, 2022

How to load JavaScript files with defer attribute in WordPress using wp_print_script_tag function

Sridhar Katakam

Before WordPress 5.7, the way to add defer attribute to JS files was to first enqueue them and then apply the script_loader_tag filter on them as detailed here.

In WordPress 5.7 we now have a wp_print_script_tag() function using which we can load a JS file (external or internal) and set the defer attribute.

This function takes an array having 3 items as its argument:

  • script handle we would like to set
  • URL of the js file
  • attribute we would like to add to the opening script tag

Let’s say you want to load Swiffy Slider on all the pages in your WordPress site. From its documentation we can see that the following needs to be loaded in the site head:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/swiffy-slider.min.js" defer>

External JS file

Install and activate Code Snippets plugin.

Go to Snippets > Add New.

Title: Load scripts in head with defer attribute

Code:

add_action( 'wp_head', 'wpdd_load_scripts' );
function wpdd_load_scripts() {
	wp_print_script_tag(
		array(
			'id' => 'swiffy-slider',
			'src' => esc_url( 'https://cdn.jsdelivr.net/npm/[email protected]/dist/js/swiffy-slider.min.js' ),
			'defer' => true
		)
	);
}

Set the snippet to run only on the front end. It does not actually matter whether we select front end only or leave it as default in this case because the wp_head hook prints data or scripts on the front end anyway.

Save changes and activate.

Now reload any page of your site and view its source.

You should see:

If you would like to load the script on select pages or views you would need to use the appropriate if conditional tags.

Example 1:

add_action( 'wp_head', 'wpdd_load_scripts' );
function wpdd_load_scripts() {
	// if this is NOT the site's static homepage, abort.
	if ( ! is_front_page() ) {
		return;
	}
	
	wp_print_script_tag(
		array(
			'id' => 'swiffy-slider',
			'src' => esc_url( 'https://cdn.jsdelivr.net/npm/[email protected]/dist/js/swiffy-slider.min.js' ),
			'defer' => true
		)
	);
}

Example 2:

add_action( 'wp_head', 'wpdd_load_scripts' );
function wpdd_load_scripts() {
	if ( is_singular( 'post' ) || is_page( 'sample-page' ) ) { // load on single posts and a static Page having the slug of "sample-page"
		wp_print_script_tag(
			array(
				'id' => 'swiffy-slider',
				'src' => esc_url( 'https://cdn.jsdelivr.net/npm/[email protected]/dist/js/swiffy-slider.min.js' ),
				'defer' => true
			)
		);
	} // end of if
}

Internal JS file

If you would like to serve the JS file from your server (rather than some CDN), download the js file to your computer, upload to custom functionality plugin‘s assets/js directory and add this code at the end in the plugin’s main PHP file:

add_action( 'wp_head', 'wpdd_load_scripts' );
function wpdd_load_scripts() {
	wp_print_script_tag(
		array(
			'id' => 'swiffy-slider',
			'src' => esc_url( plugin_dir_url(__FILE__) . 'assets/js/swiffy-slider.min.js' ),
			'defer' => true
		)
	);
}

Multiple JS files

To load multiple js files use separate wp_print_script_tag() function call for each.

Ex.:

add_action( 'wp_head', 'wpdd_load_scripts' );
function wpdd_load_scripts() {
	wp_print_script_tag(
		array(
			'id' => 'swiffy-slider',
			'src' => esc_url( 'https://cdn.jsdelivr.net/npm/[email protected]/dist/js/swiffy-slider.min.js' ),
			'defer' => true
		)
	);

	wp_print_script_tag(
		array(
			'id' => 'isotope',
			'src' => esc_url( 'https://unpkg.com/[email protected]/dist/isotope.pkgd.min.js' ),
			'defer' => true
		)
	);
}

Background

Regarding parsing of JavaScript on a webpage:

Normal: HTML parser sees the script element, stops processing the HTML, waits for the JS file to be (down)loaded & parsed/interpreted and then moves on. Slows down the webpage loading. This is render-blocking, meaning it blocks the rendering of the webpage.

In the footer before the closing body tag: HTML gets loaded, then the script is loaded and run. This is widely used.

defer: HTML parser sees the script element, loads the JS but does not execute. The parser continues to parse the rest of the HTML. When that’s done, JS gets executed. This is the newer preferred method in general. Should go in the document head.

async: HTML parser sees the script element, loads the JS, and executes it. Does not wait for the rest of the HTML to be parsed. Not ideal for when we are manipulating DOM via JS. We can not control the order of loading of async scripts. Useful for scripts that are independent of other scripts. Most suitable option as it optimizes web page load time but is not always practical. Should go in the document head.

tagschevron-leftchevron-rightchainangle-rightangle-upangle-downfolder-ocalendar-check-omagnifiercrossmenuchevron-down