Last week we got a local version of WordPress up and running along with a brand new fresh theme. This week I’ll be going through the WordPress hierarchy, files you need and best practices for your functions.php file.

Get the files for this tutorial

There are links right at the end of this post, but you can skip to it here.

WordPress File Heirarchy

If you’re not already familiar with the WordPress template heirarchy it is most certainly worth reading about it here and here.

By using the underscores theme in part 1 we already have the basic recommended file structure we need:

  • 404.php
    This is where the “page not founds” will go, for example a random URL.
  • archive.php
    This will display all of your blog posts if browsed to via a category.
  • comments.php
    Your comments format.
  • footer.php
    Anything you want to display globally in your site footer goes here.
  • functions.php
    All site functions go in here.
  • header.php
    Anything you want to display globally in the header goes here.
  • index.php
    This is the homepage essentially and by default is similar to the archive.php, showing all of your blog posts.
  • page.php
    Show the contents of any “Page”, e.g. if you create a page in WordPress via Pages > Add New, this template will be used.
  • screenshot.png
    This displays a static screenshot on Appearance > Themes.
  • search.php
    When search is used, this template is used to display the results.
  • single.php
    Show the contents of any “Post”, e.g. if you create a page in WordPress via Posts > Add New, this template will be used.
  • style.css
    Controls the main CSS of your website, there is also a declaration at the top of this file which is used by Appearance > Themes and a few other aspects which I’ll detail later.

In addition to those required files we also have:

  • inc
    This folder is used to inc lude additional PHP files from your functions.php.
  • js
    A folder where all of your JavaScript files live.
  • languages
    This folder holds any language .pot or .po files.
  • layouts
    This is an extra folder for CSS in relation to the sidebar. Underscores adds this in by default, but we’ll strip it out later in this tutorial.
    A useful help guide for getting up and running with underscores. We’ll keep this and change it later on for theme specific advice.
  • readme.txt
    This file holds useful information like changelog history, description and compatibility information.
  • rtl.css
    A Right to Left CSS for anyone using an RTL based browser.
  • sass
    This is the folder where all of our SCSS files are currently saved.
  • sidebar.php
    Control over the sidebar, typically where all the widgets go.
  • template-parts
    A folder to organise all of our template parts. Template parts are like PHP includes but used on a file basis. e.g. you’d call these in post.php and page.php but not from functions.php.


Now I’ve gone through all of the files you need and have, let’s tackle the functions.php.

Open functions.php from your base theme in a text browser of your choice, I use Atom.

The underscores functions.php file is very well laid out and easy to get started with. I’d heartily recommend reading this WordPress Codex article for detailed information: Theme Functions.

You’ll see inline comments in the functions.php so I’m not going to go through every single line of code with you as this should all be self-explanatory.


The single most important thing to do in your functions.php when adding anything new is to prefix all the things with your namespace. This article explains it better than I could: Prefix all the things.


There are a few adjustments I’d recommend making to the functions.php though and these are detailed below.

Content Width

Search in your file for content_width().

function cwtheme_content_width() {
    $GLOBALS['content_width'] = apply_filters( 'cwtheme_content_width', 640 );
add_action( 'after_setup_theme', 'cwtheme_content_width', 0 );

You’ll see an arbitrary width of 640 here, that stands for 640px and is the width of your content editor in WordPress. You should adjust this to match your themes output. For example if posts and pages content area is 820px, adjust that value to 820.


Next, search for scripts().

The first thing I like to do here is rename that function so it is more accurate.

So I’ll rename cwtheme_scripts to cwtheme_styles_and_scripts and update the add_action line directly beneath the function too.

Next, on the first line inside that function you’ll find wp_enqueue_style enqueing your main CSS style.

This outputs a media="all" declaration onto your front end code. I prefer to split this for screen and print.

So update that first function from:

wp_enqueue_style( 'cwtheme-style', get_stylesheet_uri() );


wp_enqueue_style('cwtheme-style', get_bloginfo('stylesheet_url'), array(), '1.0.0', 'screen');
wp_enqueue_style('cwtheme-print', get_template_directory_uri() . '/print.css', array(), '1.0.0', 'print');  

And save out a blank print.css into your root folder, the same directory as your style.css.

Just to explain the enqueues you just wrote a little bit more…

the 1.0.0 prints out a version into the link to the CSS and the print / screen parameter tells the media attribute to use media="print" and media="screen".

If you are supporting Internet Explorer 8, I’d also advise adding in an Internet Explorer conditional to deal with anything below Internet Explorer 9. I use a simple SCSS mixin to output an IE stylesheet, but that is probably for another post.

For now, here is how you add in a conditional.

* Enqueue styles for IE
add_action('wp_enqueue_scripts', 'cwtheme_load_ie_css');
function cwtheme_load_ie_css()
    wp_enqueue_style( 'cwtheme-ie9', get_template_directory_uri() . '/ie.css', array(), '1.0.0', 'screen' );
    wp_style_add_data( 'cwtheme-ie9', 'conditional', '(lt IE 9) & (!IEMobile)' );

Make sure you save a blank ie.css into your root theme folder too.


To go along with the IE CSS I like to include an HTML5 shim too. You can also do that in a conditional statement like this:

* Enqueue scripts for HTML5 shim - less than IE9 browsers
add_action('wp_enqueue_scripts', 'cwtheme_load_html5_shim',95);
function cwtheme_load_html5_shim()
    wp_enqueue_script('cwtheme-html5', get_template_directory_uri() . '/js/html5.js', '1.0.0', true);
    wp_script_add_data( 'cwtheme-html5', 'conditional', 'lt IE 9' );

You’ll find the html5.js file in the Github commit zip (link below).


If you want to adjust the excerpt ends and length drop in these snippets:

Excerpt end
* Change Excerpt end
function cwtheme_excerpt_more($more)
    return '...';
add_filter('excerpt_more', 'cwtheme_excerpt_more');
Excerpt Length
* Update Excerpt length
function cwtheme_custom_excerpt_length($length)
    $excerpt_length = 20;
    return $excerpt_length;
add_filter('excerpt_length', 'cwtheme_custom_excerpt_length', 999);

Theme Constants

When it comes to theme creation I like to set a few constant variables. This gives me the ability to update the WordPress admin footer and utilise the theme version numbers dynamically.

Scroll up to just above where you enqueue the scripts and styles and add:

* Define Theme Constants
$theme = wp_get_theme();
$theme_title = $theme->name;
$theme_version = $theme->version;
$author_url = '';

define('CWTHEME_THEME_SLUG', get_template());
define('CWTHEME_THEME_NAME', $theme_title);
define('CWTHEME_THEME_VER', $theme_version);
define('CWTHEME_URL', $author_url);

Where CWTHEME is your theme slug and the $author_url is your URL.

We won’t cover amending the WordPress admin footer today, but here is how you get that version number.

Version number

In your style.css that underscores created you’ll notice a few lines in CSS comments at the top.

Theme Name: cwTheme
Theme URI:
Author: Chris Wharton
Author URI:
Description: A starter theme based on the wonderful _undescores
Version: 1.0.0

The constant we just set for CWTHEME_THEME_VER gets that version number and we can then apply it to anything we want.

It speeds up my workflow to replace all the 1.0.0 versioning we added earlier with this theme constant variable.

Just do a search and replace in your functions.php for '1.0.0' and replace with CWTHEME_THEME_VER.

You don’t need the single quote marks when using a variable.

This means every time you update the line in the CSS with your version number, it updates it everywhere you have used that variable.

You can also update the '20151215' from the underscores to the CWTHEME_THEME_VER too – those two files may well come in handy for you.

This comes in very handy when releasing new theme versions to customers and clients as the query string at the end of each file link gets updated with the version number. This resolves potential caching issues on updates (where clients see old versions of CSS / JS instead of new versions).

Get the files for this tutorial

You can get a zip download of the whole wp-content folder by going to the “Part 2” commit on Github.

Part 2 Commit Files on Github
Part 2 Commit Zip Download on Github

Each part will come as its own commit so you can easily keep track now and in the future.

That’s it for now

In the final part of this series I’m going to delve a little deeper and get you up and running with a basic blog design. I’ll explain how to map across your HTML and CSS into the various WordPress files and templates. It’s going to take me a few weeks to get that ready though, but make sure you sign up below so you don’t miss it!

So if you’re not signed up already, sign up now to be the first to hear, all my subscribers get the new blog post at least a day before everyone else!