DEV Community

Cover image for WordPress: Css Styles and Javascripts in theme development (In depthish).
Stephan Nijman
Stephan Nijman

Posted on • Updated on • Originally published at since1979.dev

WordPress: Css Styles and Javascripts in theme development (In depthish).

Originally posted on my website February 21 2019

Adding Css and Javascript to WordPress themes.

In this tutorial I will show you “the right way” to include Css styles and Javascripts in your WordPress themes. If you have previously created websites without WordPress, you are probably used to using link href=“” and script src=“” tags. While there is nothing that prevents you from inserting these tags into your themes directly, this is considered a “bad habit” in WordPress development.

WordPress has its own specific way to handle Css styles and Javascripts through the wp_enqueue_style() and wp_enqueue_script() family of functions.

Doing things the WordPress way will be a little bit more code to write, but has some real advantages over the direct use of tags, such as reusability of code, basic dependency management and the fact that, if you insert your Css styles and Javascripts correctly, plugins can take control over them for all kinds of purposes, such as, minification and concatenation.

Lets get started…

Adding Css Styles to WordPress themes:

To add stylesheets we first need to hook into the WordPress process. If you want to know all the nuts and bolts about WordPress hooks check out this article, but in short… Hooks are like asking a chef to call upon you at a certain point of the cooking process. For instance asking him to call you when it is time to add vegatables to the soup, so you can add your own favourite one. In our case WordPress is cooking up webpages and we want to be called when it is time to collect styles and scripts (enqueue_scripts) so we can add our own.

Hooking into WordPress:

Add the following code to your theme’s functions.php

You can hook into WordPress with either a Filter or an Action. Filters let you change something (We’ll come to these later), and Actions let you do something. In our case we need to do something (Add styles) so we use the add_action() function to add an action to the wp_enqueue_scripts hook, and register the callback function my_theme_enqueue_styles() which will be executed when its time to collect Css styles or Javascripts from your theme.

The add_action() function takes 4 parameters:

  • $tag: The name of the action to which the callback function is hooked.
  • $function_to_add: The name of the callback function you wish to be called.
  • $priority: Used to specify the order in which the functions associated with a particular action are executed.
  • $accepted_args: The number of arguments the callback function accepts.

Notice that in this case we dont need the last two parameters so we don’t pass them, but we’ll get to them later.

To avoid name collitions its a good practice to prefix your function names with your themes name. So, if your theme is called “personal-theme” rename the above callback function to “personal_theme_enqueue_styles”, and change the name in the add_action() function accordingly.

This piece of code won’t do very much yet, so lets start adding stylesheets. As an example in this tutorial I’m going to add the PureCss framework. You can change this to Bootstrap or whatever Css you like.

Enqueue a remote Css stylesheet:

Update the code in your functions.php and add the code from line 6 below:

To add a stylesheet we use the wp_enqueue_style() function which accepts 5 parameters. I’ll explain these from left to right:

  • $handle: Every stylesheet (or script) in WordPress needs a unique name so you, or a plugin, can refference it later. Here it’s also a good practice to prefix these with your theme name.
  • $src: A URL to you stylesheet. This can also be a local path, but we’ll get to that later.
  • $deps: An array of stylesheet handles this stylesheet depends on.
  • $ver: A string specifying the stylesheet version number, this will be added to the URL as a query string to bust out of caching by browsers and CDN’s .
  • $media: The mediatype for this stylesheet. Like ‘all’, ‘print’ and ‘screen’, or media queries like ‘(orientation: portrait)’ and ‘(max-width: 640px)’.

The above code will “Enqueue/Add” the new stylesheet and WordPress will output the following link tag into the head of your webpages:

Adding Conditional stylesheets:

PureCss requires two conditional stylesheets for it’s responsive grid to function. One stylesheet for Internet Explorer 8, and One for any browser above IE8

Change the code in your functions.php and add the code on lines 8 to 12.

Here we simply enqueue two more stylesheets like we did before, but straight after that we add conditions via the wp_style_add_data() function. This function Accepts three parameters. I’ll explain these from left to right:

  • $handle: Name/handle of the stylesheet.
  • $key: Name of the data point for which we’re storing a value. Accepts ‘conditional’, ‘rtl’ , ‘suffix’, ‘alt’ and ‘title’.
  • $value: String containing the data to be added.

The code will now enqueue and output two more stylesheets in the head of your webpages with conditional comment:

Enqueue a local Css stylesheet:

To enqueue a local Css stylesheet we use the same process of adding a remote one, with one little addition.

Update the code in your functions.php and add the code from line 14 below:

Here you see that the process is the same. We use the wp_enqueue_style() function again, but make use of the get_template_directory_uri() function within the $src parameter. This function returns an full url to your custom themes folder, making sure your urls dont break when you rename your theme or theme folder.

The code will now enqueue and output the extra local stylesheets in the head of your webpages with a full url like below:

Enqueue inline Css styles:

There may be times where you need to inline a piece of Css. This could be the case when you need to add styles which depend on some wordpress setting, or where your styles depend on some other data.

Update the code in your functions.php and add the code from line 16 to 18 below:

Here we first register the style using wp_register_style() with a handle only, so we can add data to it before enqueueing. We then add the Css we want to inline with the wp_add_inline_style() function. This function accepts two parameters:

  • $handle: The name of the script to which to add the extra styles.
  • $data: String containing the Css to be added.

Finaly we enqueue the style using the wp_enqueue_style() function again passing just the handle name.

The code will now enqueue and output the inline styles in the head of your webpages like shown below:

Adding Javascripts to WordPress themes:

The process of adding Javascript to your theme is very similar to adding styles, but there are some small differences and extra options.

Hooking into WordPress again:

Lets start by adding another hook to your functions.php. You could very well use the hook we just used for the styles, but I advise you to keep things seperated for the sake of maintainability.

Update the code in your functions.php and add the code from line 4 to 9 below:

Here we create a new callback function called my_theme_enqueue_scripts() and register it to the wp_enqueue_scripts hook, just like we did for the styles.

Again this doesn’t do much yet so let’s add the first Javascript file.

Enqueue a Javascript file:

Update the code in your functions.php and add the code from line 6 below:

Instead of using the wp_enqueue_styles() function we now use the wp_enqueue_scripts() function, which makes sense since we are adding scripts now.

The wp_enqueue_scripts() function accepts the same parameters as wp_enqueue_styles() except for the last one. For styles we pass the $media parameter, but for scripts we pass the $in_footer parameter. As you can gues when set to true this parameter tells wordpress to put the script in the footer of the file.

  • $in_footer: Whether to enqueue the script before the body tag instead of in the head. Defaults to ‘false’.

The code will now enqueue and output a new Javascript tag in the footer of your webpages like shown below:

Remove a Javascript file:

In some cases it could be usefull te remove a script from the que simply becouse its not needed. For instance most WordPress themes enqueue the jQuery library. Now if you (or plugins) don’t need it it’s better for performance to just remove it from the page.

Update the code in your functions.php and add the code from line 6 below:

Here we call the wp_deregister_script() function and pass the handle for jquery. WordPress will now remove the jQuery library from the page.

Passing data from Php to Javascript:

Let’s say you have created a piece of Javascript that manipulates you webpage in such a way that it outputs a part of the interface. Great but what if part of that is some sort of text that you want to be translatable? Or what if that script depends on a path to your theme? That path could be changed by someone else!

WordPress has a way to pass data from Php to Javascript by using the wp_localize_script(). As it’s name implies this function is originally meant for passing translatable/localized strings, but it can very wel be used to pass other data like paths or theme versions.

Update the code in your functions.php and add the code from line 8 to 16 below:

Here instead of enueueing the script like we did before, wo now first register it using the wp_register_script() function. we then create a new array called $data_array which contains the data that we want to pass. It this case we pass two values:

We then pass the $data_array to the wp_localize_script() function. Wp_localize_script() accepts 3 paramaters:

  • $handle: The name of the script you are attaching the data to.
  • $name: The name of the variable/object which will contain the data in your Javascript. (This name has to be unique within your Javascript).
  • $data: The array of data you wish to pass to your Javascript.

Finaly we enqueue the script by using the wp_enqueue_script() function again.

The code above will result in the following output in the footer of your webpagte:

You can now access the passed data in your Javascript like shown below.

Here the object_name variable (Object) name comes from the $name parameter passed to the wp_locatize_script() function. And its members/values come from the $data_array array we passed.

Changing the Link and Script tags:

Lately there has been some debated if the type attribute is really necessary on link and script tags. This is up to you but If you wish to remove them, or if you want to change your tags for some other reason like testing out the new resource prioritization attributes, add the following code to your functions.php.

Before we used actions which let you do something, now we are going to use filters that let you change something. In this case we need to change the link and script tags so we use the add_filter() function here.

The add_filter() function takes 4 parameters, like the add_action() function:

  • $tag: The name of the action to which the callback function is hooked.
  • $function_to_add: The name of the callback function you wish to be called.
  • $priority: Used to specify the order in which the functions associated with a particular action are executed.
  • $accepted_args: The number of arguments the callback function accepts.

In the code above we add two filter hooks with the add_filters() function. But this time we do pass the last two parameters because we need the callback to accept more parameters. so in this case we set $priority to 10 and the $accepted_args to 4 for the style_loader_tag hook and to 3 for the script_loader_tag hook. Again more on this can be found in this article.

The my_theme_optimize_style_tags() callback function is now called for each Css stylesheet that has been enqueued and recieves 4 paramters since we set the $accepted_args to 4:

  • $html: The complete html for the link tag.
  • $handle: The handle/name of the stylesheet.
  • $href: The Url/Path to the stylesheet.
  • $media: The mediatype for this stylesheet.

Within this function we need to return the changed/filtered value of the $html parameter but we simply return an new string containing the link tag, as we want it to be output by WordPress, using the passed in parameters with php string enterpalation.

The my_theme_optimize_script_tags() callback function is now called for each Javascript file that has been enqueued and recieves 3 paramters since we set the $accepted_args to 3:

  • $tag: The complete html for the script tag.
  • $handle: The handle/name of the stylesheet.
  • $src: The Url/Path to the stylesheet.

Again we need to return the changed value of $tag but we return an new string containing the script tag, as we want it to be output by WordPress.

The code above changes the output to the following into your webpage.

Note that the inline styles still have the type=”text/css” attribute. I still have to find a solution to this. If you know of any please let me know so i can add it to this article.

Async/defer your Javascripts:

Async and defer are relatively new atrtributes to the script tags. You can read all about defer here and async here. To add these to your script tags we need to change the code off the my_theme_optimize_script_tag() function from earlier as shown below.

Here we check the $handle parameter to see if this is the correct script because we likely dont want to async defer all javascript files. If true we pass the string “async defer” to the $defer vaiable, if false we pass an empty string.

We then add the content of the $defer vanriable to the returned script tag.

The code change above adds the defer and async atributed to the my-theme-scripts script tag like shown below:

Use wp_get_theme:

To make your functions.php file a bit more maintainable I advise you to make use of the wp_get_theme() functionality. This function returns a WP_Theme class instance containing the Name, ThemeURI, Description, Author, AuthorURI, Version, Template, Status, Tags, TextDomain and DomainPath of the current theme as private properties.

The returned class instance also contains a get() method which can be used to get the values mentioned above from the object. As an example you can use this code to prefix your handles and pass the theme version to your wp_enqueue_style() and wp_enqueue_script() functions as shown below:

Now when you change your theme name or theme version this will automaticaly be reflected within the output of Link and Script tags.

Completed code:

Below you find the completed code which you can use as a boilerplate for your functions.php file.

Tip: FunctionsPhp

As your theme grows in complexity so does your functions.php file and it can quickly become hard to maintain. For that reason i created FunctionsPhp: A Maintainable OOP WordPress functions.php boilerplate. Check it out on GitHub.

Suggestions!?

I hope you liked this tutorial and found something usefull. If you have any questions or suggestions please get in touch via Twitter: Vanaf1979, my website Since1979.dev or comment here on Dev.

Top comments (1)

Collapse
 
digital_hub profile image
hub

good day dear Stephan

first of all; hello to you to the Dutch - the pay bas the awesome netherlands. I am a big fan of Texel, Amsterdam and all the great towns
in this lovley contry.

many thank you so much for spending your time creating and posting this article.

I really like the idea of the support the discussion about the Css Styles and Javascripts in theme development in the WordPress development.
i just found your article and i like it. The way you talk about the usage of the Css Styles and Javascripts in theme development in the WordPress development.

Many thanks for the article it is just great!!

i am currently working on some issues - that have to do with the CSS and google fonts.

to begin with the beginning:i have found out that my wordpress-site fetches two google fonts:

one of them is montserrat

i decided to host them locally. so i have to

a. fetch the fonts
b. correct the css code

with the following tool i fetch them

google-webfonts-helper.herokuapp.c...

here i have the option to add the paths - to customize the path in the css-data

/* montserrat-regular - latin / u/font-face { font-family: 'Montserrat'; font-style: normal; font-weight: 400; src: url('../fonts/montserrat-v25-latin-regular.eot'); / IE9 Compat Modes / src: local(''), url('../fonts/montserrat-v25-latin-regular.eot?#iefix') format('embedded-opentype'), / IE6-IE8 / url('../fonts/montserrat-v25-latin-regular.woff2') format('woff2'), / Super Modern Browsers / url('../fonts/montserrat-v25-latin-regular.woff') format('woff'), / Modern Browsers / url('../fonts/montserrat-v25-latin-regular.ttf') format('truetype'), / Safari, Android, iOS / url('../fonts/montserrat-v25-latin-regular.svg#Montserrat') format('svg'); / Legacy iOS */ } Customize folder prefix (optional):

and now i have to add a path to set the correct path - (that means to customize the path )

../fonts/

some additional thought: what makes me wonder is the fact that some of the examples show full paths as reference - others dont:

see the following examples;

a. wp-ninjas.de/wordpress-google-font...

url("https://wp-ninias.de/fonts/muilti-latin-300.woff2") format (
url("https://wp-ninias.de/fonts/muilti-latin-300.woff") format (

b. pixelgrade.com/docs/advanced-custo...

Copy the URL Path field and paste it before each URL in the Embed Code field. The example code will look like this:

@font-face {
font-family: 'Name of the font';
src: url('http://yourwebsite.com/wp-content/uploads/fonts/11148/name-of-the-font-file.woff2') format('woff2'),
url('http://yourwebsite.com/wp-content/uploads/fonts/11148/name-of-the-font-file.woff') format('woff');
}

c. themeisle.com/blog/custom-fonts-wo...

Once the file is in place, open up your child theme’s stylesheet. Now you’ll need to call on that font so you can use it, via a snippet that should look like this:

`

@font-face {
font-family: New Font;
src: url(yourwebsite.com/wp-content/themes/...);
font-weight: normal;
}

`

and now compare it with the following example here:

  1. Copy CSS: (default is Best Support) Modern Browsers Choose Best Support if old browsers still need to be supported. Formats in this snippet: [eot,woff,woff2,ttf,svg]

Code:
/* montserrat-regular - latin */
@font-face {
font-family: 'Montserrat';
font-style: normal;
font-weight: 400;
src: url('../fonts/montserrat-v25-latin-regular.eot'); /* IE9 Compat Modes */
src: local(''),
url('../fonts/montserrat-v25-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('../fonts/montserrat-v25-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
url('../fonts/montserrat-v25-latin-regular.woff') format('woff'), /* Modern Browsers */
url('../fonts/montserrat-v25-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
url('../fonts/montserrat-v25-latin-regular.svg#Montserrat') format('svg'); /* Legacy iOS */

see the helper-tool google-webfonts-helper.herokuapp.c...

the question: so the question is: how to set the path correct for the CSS... which path should we use here!?

Dear Stephan i look forward to hear from you