Today we will learn where and how to add code outside the templates in our theme. We do this by adding the theme’s functions.php file. Along the way we’ll also learn how to add your stylesheets and scripts the proper way.

A theme’s functions.php file

A theme needs somewhere to place code that is not part of the templates. There’s always a bunch of code all themes need to add in order to handle functionality. For example enabling WordPress’ featured images feature (did you notice that it was missing?), support for menus, widgets, adding stylesheets and scripts (the proper way), and more.

That file is functions.php. WordPress automatically and always loads this file if it exists in your theme. It’s always loaded both in admin and in frontend.

Adding a functions.php file to our theme

Let’s create a new, empty file in our root theme folder and name it functions.php.

In that file, immidiately start with an opening PHP tag (<?php) and don’t include the closing tag. The functions.php file is meant for PHP code, not HTML. Your theme can break (or even just act weird) if you have characters or newlines outside PHP tags in this file. You can obviously break out of PHP tags to output HTML, but it must be done inside functions or hooks. Let me explain this with an experiment.

Let’s test this file out to see how it works. Inside functions.php write an echo of some dummy text:

functions.php
<?php
echo 'This is an experiment';

Refresh your frontend. The dummy text appears. But if you inspect or view the HTML source, you will see that the text appears before opening <html>. This makes for completely invalid HTML!

Go to your admin panel and hit refresh. It does the same thing there as well (it might be hidden behind admin bar, but it’s there in the HTML).

As you can see, any code in your functions.php loads before anything else in our templates. Therefore, as a rule, any output (HTML outside PHP tags or echo) must be inside functions that will be run at the right times, normally hooked to actions or filters.

Recall from when we learned about and added hooks in part 3 of the WordPress theme tutorial for beginners. The way we run code on a hook is to attach a function to the hook with add_action(). Let’s test something else out; let’s make a function hooked to a hook we already have defined in our templates; wp_footer.

In functions.php remove the echo we added for test purposes and instead write:

functions.php
<?php
add_action('wp_footer', 'wptutorial_print_footer');
function wptutorial_print_footer() {
	echo 'This sentence will appear in footer!';
}

Hit refresh in frontend and see that the string appears nicely at the exact place you have defined wp_footer, right before closing </body>. Also, notice that this will not echo anything out in admin. This is because wp_footer is a hook that is only run in frontend.

Let’s do our first proper operations in functions.php!

Note: In PHP it is not possible to have two functions with the exact same name. That includes function names in WordPress, your theme and any activated plugin! Follow best practices and prefix your functions with your theme slug, like in the above example: “wptutorial_<function_name>“. This greatly reduces WordPress from fatally crashing because of identical function names.

Note 2: It doesn’t matter in which order you add functions and hooks in your functions.php. Remember that hooks are run at certain checkpoints anyway, not the order they are in functions.php. The only exception is if you are including other files or initializing your own classes.

The right way to add styles and scripts vs the wrong way

Some of you might remember from part 3 where we added the wp_head hook in our header.php. After we did this WordPress was able to load its styles and scripts, including the admin bar. You might be thinking that in order to add our stylesheets we need to make a function hooked onto wp_head and output the <link> for the stylesheet… Usually you would be right!

However in WordPress there is a special way to go about adding scripts and styles. This is mainly to manage the load order and to avoid loading duplicate libraries. For example you as a theme author might want to add Javascripts that are dependent on the jQuery library. Then you need to make sure jQuery gets loaded before your files. But WordPress and any plugins have the same need, to make sure jQuery is loaded before their scripts as well. You can’t load the jQuery library multiple times because that causes problems. So WordPress has a way to manage in which order scripts and stylesheets are loaded.

Adding stylesheets (the right way)

For adding any styles and any javascripts, we use a hook called wp_enqueue_scripts. Yes, you use this hook for styles as well, despite its name. Adding scripts and styles are referred to as “enqueuing” – as in put in a queue. Let’s enqueue (add) our stylesheet by using the function wp_enqueue_style in our functions.php:

functions.php
<?php
add_action('wp_enqueue_scripts', 'wptutorial_enqueue_scripts');
function wptutorial_enqueue_scripts() {
	wp_enqueue_style('theme-main-style', get_stylesheet_directory_uri().'/style.css');
}

The wp_enqueue_style function takes as minimum two parameters. The first is an unique name (handle or “slug ID”), and second the location of the file. The handle needs to be unique as this is the identifier WordPress uses to determine if there are any duplicates.

As for returning the path to your theme, there are plenty of functions available. Above I used get_stylesheet_directory_uri() which returns the URL to your theme folder, and then I appended the rest of the path to our stylesheet.

PS: WordPress offers a separate function for returning the full URL to your theme’s style.css: get_stylesheet_uri(). I used the other function above as it’s more useful to get familiar with. You will use it for any other files you need to enqueue.

The function wp_enqueue_style accepts more useful parameters, such as dependencies (which other css files must be loaded before), and version number (useful for caching purposes).

Refresh your frontend and see that your stylesheet is loaded in <head> tag!

If you are one of those who are itching to make your theme look prettier while coding it, here’s your chance. I encourage you to start defining your HTML, classes and wrappers and add some styling in your style.css. We will add more content that will require styling as we go along in this tutorial series.

Adding scripts (the right way)

Let’s look into how we add javascripts to our theme. It is done using the same hook (so you can put it all inside one function). But for scripts we use a slightly different function.

To enqueue a script, you use wp_enqueue_script(). The parameters are the same as wp_enqueue_style(). The first is the unique handle and the second is the path to the script. Third (optional) is the array of dependencies. As fourth (optional) parameter you set the version number. And finally fifth (optional) you define whether or not the script should be loaded in the <head> tag or at the end of </body>.

WordPress comes with a large range of libraries already included. They are not always all loaded, but available if you need them. If you want to add a common library script, check if WordPress already has it first. Examples are jQuery, all of jQuery UI modules, Underscore and Backbone.

If you add one of WordPress’ included scripts as a dependency, you don’t need to enqueue that script! Let’s do this in practice.

Create a folder assets and inside it a subfolder js in our theme folder, and then add a new empty main.js file. Let’s say this script requires the jQuery library, so we set it as dependency. We know that WordPress comes with jQuery bundles and the handle for it is jquery. We’ll enqueue our script like this:

functions.php
<?php
add_action('wp_enqueue_scripts', 'wptutorial_enqueue_scripts');
function wptutorial_enqueue_scripts() {
	wp_enqueue_style('theme-main-style', get_stylesheet_directory_uri().'/style.css');
	wp_enqueue_script('theme-main-script', get_stylesheet_directory_uri().'/assets/js/main.js', ['jquery']);
}

If you refresh frontend, and check your source code, you should see that your script, main.js, is added, but also that jQuery library is loaded. And jQuery is loaded before your file!

You have now learned how to add styles and scripts. For adding more files, add a wp_enqueue_style() or wp_enqueue_script() for each new file.

Documentation on methods used