How to enqueue WordPress CSS and JS in style.

4th February 2020

Adding scripts and styles is one of the most basic (and important) things for any website. Your content might be amazing, but if it’s set out in default black and white Times New Roman it’s going to be a real struggle to get anyone to read it.

So, you toil away at a beautiful design. Great. Beautiful.

But writing your funky code is only half the battle. It’s more important than you’d think to get it right when you add your scripts and styles to your theme, particularly if you’re not the only one involved in the project.

We’ll be looking at adding my-script.js and my-styles.css to the default Twenty Twenty theme, the start and end of which look something like this:

<?php 
/**
 * Header file for the Twenty Twenty WordPress default theme.
 *
 * @link https://developer.wordpress.org/themes/basics/template-files/#template-partials
 *
 * @package WordPress
 * @subpackage Twenty_Twenty
 * @since 1.0.0
 */
?><!DOCTYPE html>

<html class="no-js" <?php language_attributes(); ?>>

	<head>

		<meta charset="<?php bloginfo( 'charset' ); ?>">
		<meta name="viewport" content="width=device-width, initial-scale=1.0" >

		<link rel="profile" href="https://gmpg.org/xfn/11">

		<?php wp_head(); ?>

	</head>

	<body <?php body_class(); ?>> ?>

...
  
<?php
/**
 * The template for displaying the footer
 *
 * Contains the opening of the #site-footer div and all content after.
 *
 * @link https://developer.wordpress.org/themes/basics/template-files/#template-partials
 *
 * @package WordPress
 * @subpackage Twenty_Twenty
 * @since 1.0.0
 */

?>
			<footer id="site-footer" role="contentinfo" class="header-footer-group">

<!-- A lot of footer stuff we don't need to worry about for the purpose of this tutorial -->


			</footer><!-- #site-footer -->

		<?php wp_footer(); ?>

	</body>
</html>

How not to do it

A right way to add scripts and styles? A little pedantic, surely. So let’s look at a few ways a beginner to WordPress might do things, and why problems might arise.

Oldschool – don’t do this

The traditional static html method of yore. Stick our scripts and styles in the head of the page.

<?php 
/**
 * Header file for the Twenty Twenty WordPress default theme.
 *
 * @link https://developer.wordpress.org/themes/basics/template-files/#template-partials
 *
 * @package WordPress
 * @subpackage Twenty_Twenty
 * @since 1.0.0
 */
?><!DOCTYPE html>

<html class="no-js" <?php language_attributes(); ?>>

	<head>

		<meta charset="<?php bloginfo( 'charset' ); ?>">
		<meta name="viewport" content="width=device-width, initial-scale=1.0" >

		<link rel="profile" href="https://gmpg.org/xfn/11">

		<?php wp_head(); ?>

		<script src="https://example.com/wp-content/themes/my-theme/my-script.js"></script> <!--Script Here-->
		<link rel="stylesheet" href="https://example.com/wp-content/themes/my-theme/my-styles.css"> <!--Stylesheet Here-->

	</head>

	<body <?php body_class(); ?>> ?>

...

What’s the issue with this? There are a few things to consider:

  • Your links are hard-coded in, so if your url changes (maybe you’ve changed from example.com to example.co.uk) you’ll have to go in and edit the code to avoid errors. Some sites will have a different folder configured for wp-content, causing all kinds of headaches
  • Unless your script is needed before any of the page content, it should be loaded at the bottom of the page. That way you won’t be waiting for it to download before getting to readable content.
  • It’s impossible to remove the script and stylesheet without editing the file itself. This one is really important, particularly if you’re building a theme or plugin that someone else may need to build on. They may need to make changes to which styles and scripts are included, and we should make it as easy as possible for them to do so.
  • It’s hard to ensure things load in the right order. Our styles and scripts don’t exist in a vacuum, and the order is important. For scripts, we will need to make sure they load after things they depend on, but before things that depend on them. For styles, the latest file to load takes precedence over earlier files.
  • If we update the files it’s difficult to clear them from caching.

Hooks and Actions – closer but still no

A lot of WordPress functionality uses hooks, filters and actions. These are vitally important for customisation, and I’d encourage taking the time to make sure you understand them.

Two major hooks that should show up in every theme are wp_head and wp_footer, and these are sometimes used for scripts and styles as below:

<?php 
/**
 * functions.php in your theme
 *
 * 
 */

$directory = get_template_directory_uri();

add_action('wp_head',function(){

?>

<link rel="stylesheet" href="<?php echo $directory?>/my-styles.css"> <!--Stylesheet Here-->


<?php

},10);

add_action('wp_footer',function(){

?>

<script src="<?php echo $directory?>/my-script.js"></script> <!--Script Here-->


<?php

},10);


		

	

This is a far better approach:

  • If the site url changes our code will still work.
  • We can remove these actions with another function.

But

  • We still can’t control the order of dependencies.
  • We still have no control over the cache

The right way

WordPress actually has a hook and two functions specifically designed to add scripts and styles, which allow us to solve all of these problems.

The functions used are wp_enqueue_script and wp_enqueue_style.

These functions should always be put inside the wp_enqueue_scripts, hook, which manages all scripts and styles.

<?php 
/**
 * functions.php in your theme
 *
 * 
 */

$directory = get_template_directory_uri();

function mytheme_add_scripts_styles() {
    wp_enqueue_style( 'my-styles', $directory."/my-styles.css", array('dependency-style.css'),'1.0.0' );
    wp_enqueue_script( 'my-script', $directory."/my-script.js", array('dependency-script.js'), '1.0.0', true );
}
add_action( 'wp_enqueue_scripts', 'mytheme_add_scripts_styles',10 );

		

	

This solves our remaining problems perfectly:

  • Each function has takes an array of dependencies as its third argument
  • Each function takes a version number as its fourth argument (this can be anything, from a number to a date). When this is updated it will encourage refreshing the cache. You can use your theme version number or even get the modification date using the function filemtime().
  • The fifth argument in wp_enqueue_script allows us to specify whether or not the script should be loaded in the footer
  • Because we’re using standardised WP functions, everything can be tweaked and removed in other themes and plugins

TLDR

WordPress has a dedicated hook and functions for adding scripts and styles.

Always use wp_enqueue_script and wp_enqueue_style.