Hello and welcome to the beginner’s guide to developing a custom WordPress theme using Bootstrap. In this tutorial, we will be starting with a blank canvas, and build up our theme, piece by piece, until we are left with a fully functional WordPress blog theme.

Contents hide


Who this tutorial is for

This tutorial is not suited to people who are completely new to web design and WordPress. If you’ve never made a static HTML website before, or if you’ve never even touched WordPress, then go and brush up on the basics before coming back. This tutorial is suited to:

  • Anyone who has created static websites using HTML and CSS.
  • People who are comfortable using WordPress – you’ll know the basics of pages, posts, themes, plugins, menus, etc.
  • It will help if you know the basics of PHP, but it’s not essential.

What we will be building

In this tutorial, we will start with a .PSD file, and end up with a fully functioning WordPress theme. It won’t have all the bells and whistles of the themes you can find on Themeforest.net, but it will give you a solid foundation in WordPress theme development, which you can then build on. The theme will include:

  • A header, containing a logo (which can be dynamically changed using the theme customizer) and a navigation menu (again, editable via the customizer).
  • A homepage that consists of blog excerpts. Clicking on an excerpt takes you to the full post.
  • A sidebar, containing widgets that can be added, removed and edited via the WP dashboard.
  • A footer, featuring widget areas arranged in columns.

View the completed theme by clicking here.

*** Essential downloads ***

In order to follow along with this course, you will need to download the course files. In the course files, you will find the images and text you will need in order to build this theme.

You may wish to also download the PSD mockup of the theme homepage. It will help you to have a reference for what we are building, and it will help to be able to extract colours and measurements, etc.

The technologies we will be using

I’m not using anything too fancy throughout this course, but depending on your experience level, you may encounter tools and concepts you’re not familiar with. Don’t let that put you off, just follow the tutorial closely and you’ll hopefully pick up some cool new techniques. Here’s what we will be using:

  • A code editor. I use Brackets, but you can use whatever you are most comfortable with.
  • Bootstrap 4 (but just the grid system).
  • SASS. I can’t bring myself to make a website these days without using a CSS pre-processor. We will be using nested CSS and some variables.
  • To process SASS, I will be using a piece of software called Prepros. We’ll cover this later.
  • MAMP. To create a WordPress theme, it’s pretty much essential that you do so locally. I use MAMP, but you are free to use whatever software you like that will allow you to develop locally.
  • PHP. WordPress is built on PHP, so there’s no getting around the fact we’ll be getting stuck into some code. But don’t worry, it’ll be more a case of moving code around and editing existing code, rather than writing arrays, functions, etc from scratch.

Setting up our development environment and installing WordPress

Setting up a local development environment (using MAMP)

If you already know how to set up a local development environment running WordPress, you can skip this part.

When it comes to making WordPress themes, setting up a local development environment is essential. It means we can make changes to the code of our theme, and see the results instantly.

There are a multitude of tools out there for local development, but the one I use is MAMP. You can pay for the pro version, which comes with a number of fancy features, but for our purposes we’ll stick to the free version.

Head to https://www.mamp.info, download and install it.

If all goes well, you should be greeted with a screen that looks like this:

WordPress needs both the Apache server and MySQL servers running in order to work. Press the ‘start servers’ button and ensure that a green light appears next to both servers. If you experience problems, you may need to change the port numbers by going to MAMP > preferences > ports.

Hooray! Give yourself a pat on the back, you’re well on your way to being a WordPress theme guru. I mean, not really, we’ve barely started, but every journey starts with a single step. Let’s keep going…

Downloading WordPress

You can’t build a WordPress theme without first installing WordPress. That would be like trying to fit a car engine without having a car. So let’s do that now…

Head to https://wordpress.org/download/ and press the download button.

We need to unzip WordPress in a very specific place.

On a Windows PC, navigate to C:/MAMP/htdocs and create a new folder called ‘Scribbleit’. On a Mac, it’s Applications/MAMP/htdocs

It should look a bit like this:

Our newly created folder inside the htdocs directory.

What we need to do now is unzip WordPress inside this newly created folder.

The contents of your newly created Scribbleit folder should look like this:

The contents of our Scribbleit folder, after WordPress has been unzipped.

Perfect, we now have all of WordPress’ files and folders exactly where we need them.

Creating our database

WordPress requires access to an SQL database in order to function. So let’s go and create that now, using MAMP.

  • Open MAMP again and select ‘Open WebStart page’.
  • On the next page, select ‘phpMyAdmin’.
  • In phpMyAdmin, select ‘Databases’
  • Under ‘create database’, type ‘ScribbleitDB’, and select ‘create’.

Installing WordPress

With our database created, we have everything we need to install WordPress, so let’s get going.

Go back to MAMP and start the servers. Make sure that both the Apache server and MySQL servers are running.

Now open up your browser of choice, go to the address bar and type in localhost

If everything is working correctly, you should see the Scribbleit folder in there. Click on it, and you should be presented with the WordPress installation screen. Select ‘let’s go’.

You should now be invited to enter the details of the database we created.

Here’s what to enter:

  • Database name: ScribbleitDB (or whatever you chose as your database name)
  • Username: root
  • Password: root
  • Database host: localhost
  • Table prefix: wp_

The username and password are what MAMP uses by default. It is not a secure username and password, but it’s fine for local development. On a live site, you would never use such an easily guessable combination.

Now press the ‘submit’ button.

You should now be greeted with the message ‘All right, sunshine! You’ve made it through this part of the installation.‘ Select the ‘run the installation’ button.

Fill in the required fields, and select the ‘Install WordPress’ button. Make sure you note down your password – you’ll need it to log in to WordPress.

Now select ‘login’ and log in to WordPress using the credentials you set up in the previous step.

Done! You should now be looking at the WordPress dashboard.

This is what we have been aiming for

Congratulations! You now have WordPress set up on your local machine. All sparkly and fresh, ready for action.

To access your site in future, all you need to do is start the servers in MAMP and head to ‘localhost’ in your browser.

Now we have our development environment set up, it’s time to dive into creating our custom theme.

Downloading our starter theme (Underscores)

Now, when I said earlier we would be making our theme ‘from scratch’, I didn’t mean we would be starting with a completely blank code editor.

We are going to use a starter theme called Underscores.

Underscores will give us a massive head start. It does not provide a design for our theme, but rather provides all of the theme files, structure and components that we will need. Underscores is designed to be added to and amended. It is a bare-bones template that you build on to make your own. It is billed as a ‘1000 hour head start’, and who doesn’t love a head start.

So head to https://underscores.me. In the ‘theme name’ field, type ‘Scribbleit’, and select the ‘generate’ button. You will be prompted to download a zip file.

In order for WordPress to recognise our new theme, we need to unzip it into a specific folder within our WordPress directory. On a Windows PC, it will be C:\MAMP\htdocs\Scribbleit\wp-content\themes\

Activating our theme

With our starter theme in the right place, we can go ahead and activate it.

Head to your WordPress dashboard, go to appearance > themes.

In there you’ll see our Scribbleit theme. Go ahead and activate the theme.

Excellent! Our blank theme is now active.

Now visit your homepage by selecting the name of the website in the top left of the WordPress dashboard.

Wow, it looks amazing! Ok, no it doesn’t, it looks awful. But that’s what we’d expect to see. After all, Underscores doesn’t apply any styling – we need to hammer this theme into shape ourselves.

But look a bit closer at the homepage and you’ll notice something – it already has a lot of the features you would expect a blog to have, namely:

  • A header, featuring the site title and a navigation menu
  • Blog posts (we only have the default ‘hello world’ blog post published so far so far, so only one is displayed)
  • A sidebar (but it’s not on the side)
  • A footer

The beauty of using Underscores is that a lot of the raw ingredients are in place, it’s now up to us to manipulate these components to make something a bit prettier.

Making our first change

In the section after this one, we’re going to spend time setting up our tools, so I thought it would be a good idea in this section to get a quick win. Let’s make our first mark on our new theme.

To do that, we’re going to need our code editor. I use Brackets, but you are free to use whatever you are most comfortable with (just don’t use Notepad!).

What we need to do is open the theme directory inside the code editor. In Brackets, I can do this by either dragging the theme folder onto the Brackets interface, or by going to file > open folder and choosing the theme folder located at C:\MAMP\htdocs\Scribbleit\wp-content\themes\scribbleit. If you’ve done it successfully, your code editor should look a bit like this:

Don’t be overwhelmed by the number of files you can see, we will cover them in a later section. For now, just select the header.php file.

This is the code that governs how our theme’s header looks and behaves. Look for the following line of code:

<div id="page" class="site">

Immediately below it, let’s just add a simple bit of text:

<p>This is my first custom WordPress theme!</p>

Now save the file. Go back to your browser and refresh the homepage of our site.

At the top of the page, you should see our new line of text.

Ok, so admittedly it’s a bit underwhelming. But it’s an important step: it proves we have total control over our theme, we are now officially building a theme.

Now delete that line of text from your code. Done that? Good, let’s carry on.

Setting up Prepros (for SASS and live preview)

SASS is what’s known as a CSS pre-processor. It’s designed to save time and avoid repeating code. I like it because it keeps my CSS more neatly organised, and if I’m working on a large project, it’s a life saver.

If you are already familiar with SASS and have your own way of doing it (e.g. via the command line), then please feel free to do integrate SASS in whatever way you are most comfortable.

If you’d like to use the same method that I use, then you will need to download and install a piece of software called Prepros.

Prepros is free to download and use, but the free version displays a popup message asking you to purchase a licence. You can easily live with it though. If you like the program, I would recommend purchasing a licence ($29).

Once you have downloaded the application, you should see a screen that looks like this:

Select ‘add project’ and navigate to our theme folder (C:\MAMP\htdocs\Scribbleit\wp-content\themes\scribbleit (you are adding the whole folder, not a single file).

Prepros can do a lot of cool things, but we’re only going to use two: SASS and live preview.


Let’s create our first SASS file. In your file explorer, create a new directory within your theme folder and name it CSS.

Now go back to your code editor.

Create a new file and name it styles.scss

scss is the file extension we must use so that Prepros knows we want to use SASS.

Let’s add a quick bit of CSS inside our newly created styles.scss file:

header {
background-color: red;    

Now save the file.

Go back to your file explorer and check inside the /css folder. Prepros should have created a ‘styles.css’ file. What Prepros has done is compile the CSS inside our styles.scss file and output the compiled CSS into styles.css.

Great work! So does this mean the background of our header will now be red? Well no, not yet. Our CSS file is in place, but it is not linked to our theme yet. Before we go ahead and do that, I want to introduce you to one more Prepros feature:

Live preview

Live preview means we don’t have to wait to reload the page in order to see our CSS changes. Prepros will automatically watch for changes and reload the page as soon as we save our CSS file.

Open Prepros, and right click on the website name, then select ‘project settings’.

Make sure ‘use external server’ is checked, and enter ‘http://localhost/scribbleit’ for the server URL. Close the settings.

Now right click on the website name again and select ‘open preview’.

A new tab should have opened, displaying our homepage. It looks the same as before, only this time the page should refresh whenever any changes are made to our theme.

Using live preview gets around the fact that browsers often cache CSS files, meaning that changes we make may not immediately take effect.

Attaching stylesheets using wp_enqueue_style

It’s time to tell our theme to load the stylesheet we created in the previous section.

If we were making a static website, it would simply be a case of simply writing:

<link rel="stylesheet" href="css/styles.css">

But that is not the way it’s done in WordPress. With WordPress, we use the wp_enqueue_style function. The reason for using this method is it avoids any compatibility issues with any plugins that may be active on the site.

Open ‘functions.php’ in your code editor. This is the file we use to load our stylesheets and JavaScript files.

Scroll down to about line 142 and you’ll see that Underscores has already enqueued a few files. The function is already there, so we just need to add to it.

Right before the add_action function, and before the closing curly brace }, add the following code:

wp_enqueue_style( 'my-styles', get_stylesheet_directory_uri() . '/css/styles.css'); 

So we are calling the function wp_enqueue_style, and then passing it a few parameters. ‘my-styles’ is just a handle (a nickname), it can be anything you like.

Next we are calling the get_stylesheet_directory_uri() function. This indicates to WordPress to look inside our theme directory. Next we are providing the path to our styles.css file, relative to our theme directory.

This whole section should now look like:

 * Enqueue scripts and styles.

function scribbleit_scripts() {
	wp_enqueue_style( 'scribbleit-style', get_stylesheet_uri(), array(), _S_VERSION );
	wp_style_add_data( 'scribbleit-style', 'rtl', 'replace' );

	wp_enqueue_script( 'scribbleit-navigation', get_template_directory_uri() . '/js/navigation.js', array(), _S_VERSION, true );

	if ( is_singular() &amp;&amp; comments_open() &amp;&amp; get_option( 'thread_comments' ) ) {
		wp_enqueue_script( 'comment-reply' );

    wp_enqueue_style( 'my-styles', get_stylesheet_directory_uri() . '/css/styles.css'); 


add_action( 'wp_enqueue_scripts', 'scribbleit_scripts' );

The code of our website should now be linking to our styles.css file. Go ahead and check the homepage again – the header should now be red! If it’s not, try refreshing the page. If the header still hasn’t changed colour, right-click on the page and select ‘view page source’. Search for ‘styles.css’. If there’s no match, then the stylesheet is not attached properly.

Behold! An ugly red header.

This is a big step! We now have the ability to change the style of any part of our theme.

Delete the CSS that makes the header red – there’s no way we are proceeding with a big red header!

Loading Bootstrap

I want our theme to be organised into columns, and I want it to be responsive. To do that, we need to use some kind of grid system. My framework of choice is Bootstrap 4. There are lots of other grid systems out there, but I’ve been using Bootstrap for a long time, and I’m perfectly happy with it.

Note that we won’t be using all of the bells and whistles that come along with Bootstrap (sliders, accordions, etc). I only want the grid system.

So head to https://getbootstrap.com/ and select ‘download’.

Download the file and unzip it somewhere on your computer (you’re a grown up, I’ll let you decide where).

Go into the /css directory and find the bootstrap.grid.min.css file. Copy it.

Now navigate to our theme directory, go inside the CSS directory and paste the file in there. Your theme’s CSS directory should now contain styles.scss, styles.css and bootstrap.grid.min.css.

Now the CSS file is in place, we need to link it to our theme using wp_enqueue_style, using exactly the same method we used to link our styles.css file.

Go back into functions.php, and add the code to enqueue Bootstrap:

    wp_enqueue_style( 'bootstrap', get_stylesheet_directory_uri() . '/css/bootstrap-grid.min.css');
    wp_enqueue_style( 'my-styles', get_stylesheet_directory_uri() . '/css/styles.css');

Notice that we enqueue Bootstrap before styles.css. This is because WordPress will load the stylesheets in the order we write them here, and we want our styles.css file to take precedence over any styles contained within the bootstrap CSS file.

Go back to your homepage, view the source code and search for ‘bootstrap’ to ensure the stylesheet is indeed being loaded.

With Bootstrap in place, we can start working on the layout of our theme.

Adding the ‘Show Current Template’ plugin to make theme development easier

At this point, I want to introduce you to a plugin I always use when developing themes.

Its called ‘Show Current Template’, and what it does is display in the WordPress toolbar the current template file we are working on. Depending on what page you’re working with, WordPress will serve a different template file. For example, a single blog post is single.php, a static page is page.php, the categories page is archive.php, and so on. Using this plugin allows us to know at a glance what file we need to edit.

In your WordPress dashboard, go to plugins and search for ‘Show Current Template’. Install and activate it.

Now go back to your homepage and look in the toolbar. You should see ‘Template: index.php’. That means the template WordPress is currently serving is the index.php file.

This will make life easier going forward, trust me 🙂

Defining the structure of index.php

Now we know our homepage is using the index.php template, we can begin making changes to it.

Open index.php in your code editor and let’s take a look.

Near the top of index.php you will see:


This is a WordPress function that inserts the contents of the header.php file into the page. This is typical of the way a WordPress theme is structured – the blocks of code are modular. So rather than including the entire contents of header.php on multiple pages, all that needs to happen is to use get_header();. This method keeps everything neat and easily maintainable.

Scroll down index.php and you will find:




Similarly to header.php, the code for the footer is contained in footer.php and the code for the sidebar is contained in sidebar.php.

The content in between get_header() and get_sidebar() is what is contained in the main body of the page, i.e. our blog posts.

This diagram illustrates the way the index.php file (and other template files) are structured.

So in summary: the index.php file is made up of:

  • header.php – contains the logo, navigation menu, etc.
  • the code contained within index.php that outputs blog posts (the WordPress loop)
  • sidebar.php – displays the sidebar
  • footer.php – displays the footer.

Got that? Good, because it’s essential knowledge for building WordPress themes.

Adding structure to our page

As things currently stand with our theme, there is no real structure to our homepage. It goes header > blog articles > sidebar > footer, all in a vertical column. And they all extend to the outermost edge of the viewport. What I want to do is:

  • Arrange the blogposts and sidebar in columns, with the blog post column taking up 3/4 of the available space and the sidebar taking up 1/4.
  • Add a container so that all of our content is contained within a boundary, and not touching the edges of the viewport.

We are going to use the Bootstrap .container class to contain our content.

Let’s start with header.php. Open that file in your code editor.

After the code that says <header id =”masthead” class=”site-header”>, add:

<div class="container">

Then close the div just before the closing header tag – </header> (bottom of the page).

If you’re unsure, you can view the new code for header.php here.

Good work! Now go and view the homepage again, and you should see the header contents no longer touch the edges of the screen – they are contained in a nice little box.

Now let’s do the same for the main body of the page.

Go back to index.php and just before <main id=”primary” class=”site-main”>, add:

<div class="container">

Unlike the container for header.php, we are not closing the div within this file. We are instead closing the div within sidebar.php. That’s because the container will also cover the sidebar.

Open sidebar.php and add </div> to the very end of the document.

Your index.php file should now look like this and your sidebar.php file should now look like this.

Check your homepage again. The blog post area should now also be contained, in alignment with the header.

We’re on a roll now! Only the footer left to do.

Open footer.php, and add your container after <footer id=”colophon” class=”site-footer”>. Then close the div just before the closing footer tag </footer>.

Your footer code should now look like this.

Check your homepage again to ensure the contents within the footer are now contained.

Splitting the main content into two columns

What we want to do now is split the blog post section and sidebar into two side-by-side columns. We will do so using the Bootstrap grid.

Open index.php, and after our opening container div, we are going to add two lines of code:

<div class="row blog-row">
   <div class="col-md-8">

Line one – in order to add columns, we must contain them within a row.

Line two – our blog section will take up 8 parts of our 12 part column.

Now we have to go and close these divs. The 8 column div is closed within index.php, after the closing main tag – </main>

Your index.php file should now look like this.

Now open sidebar.php.

Before <aside id=”secondary” class=”widget-area”> add:

<div class="col-md-4">

and close the div after the closing aside tag </aside>

Now we need to close the row. Add </div> just before the closing container tag you added earlier.

Your sidebar.php file should now look like this.

Phew! That was hard work, wasn’t it? Check your homepage to see if your hard work has paid off. You should see the blog area and the sidebar are now arranged into two neat columns.

The structure of our website is really coming together! Let’s keep going…

Building the header

In a moment we will start work on our header. But first I want to touch on an invaluable tool when it comes to WordPress theme development, and that is developer tools.

Using developer tools allows us to identify the elements of our theme we need to target in order to customise it the way we want it. Let’s use an example:

I want to change the background colour of our header. In order to do that, I need to know the ID or class of the header, in order to target it with the correct CSS selector. The best way to do this is by using developer tools.

To access developer tools in chrome, right click on the element you want to inspect, and select ‘inspect’ (this is in Google Chrome; other browsers are similar).

Inspect our header area, and you will find that the header has an ID of masthead. It is this ID we will use to change its properties.

If we refer to our PSD file, you’ll see the background colour we want for our header is #313131

Open styles.scss in your code editor, and add the following CSS:

/* - Header

#masthead {
  background-color: #313131;

The commented section is how I divide my CSS into sections, to keep it neater.

Save the file and check your homepage – the header should now be a dark gray colour.

Organising the logo and navigation menu into columns

Perhaps the most common layouts for website headers is logo on the left and navigation menu on the right, and that’s exactly what we are going to do here.

To accomplish this, we are going to contain our logo and menu in a row, then we are going to place them each inside a column.

In your header.php file, add <div class=”row”> immediately after the container element we added in a previous lesson.

Close the row div immediately before the closing container element.

Now let’s separate the logo and navigation menu into columns.

Add <div class=”col-md-3″> immediately before <div class=”site-branding”> then close the div immediately after the site branding closing div.

Now add <div class=”col-md-9″> immediately before <nav id=”site-navigation” class=”main-navigation”>

Then close the div immediately after the closing nav element – </nav>

Your header.php file should now look like this.

Now go and take a look at your homepage. The logo and nav menu (such as it is) should be separated into two columns.

Now it’s time to add our logo. But we want to do it in such a way that it can be updated using the WordPress customizer. It wouldn’t be much of a WordPress theme if the end user couldn’t update the logo themselves.

At the moment WordPress is displaying our site title and description. We want to replace that code with our dynamic logo code.

Delete everything found inside the <div class=”site-branding”> div, and replace it with <?php the_custom_logo(); ?>

The code should now be:

<div class="site-branding">
     <?php the_custom_logo(); ?>
 </div><!-- .site-branding -->

the_custom_logo() is a WordPress function that outputs whatever logo has been uploaded to the theme customizer.

Head to the theme customizer (appearance > customise) and select ‘site identity’. Upload the Scribbleit logo contained in the course files (downloadable at the start of this tutorial). When prompted, skip cropping. Publish the changes.

Your header.php file should now look like this. And the front end should look like this:

The navigation menu

Our navigation menu is looking a bit pathetic. It only has the default sample page in it so far. Let’s start by filling it up a bit.

Because this is a blog, I’m going to list our blog categories in the navigation menu. So let’s go and create some now.

Head to the WP dashboard, and select posts > categories. Add three new categories: WordPress, Web Design, and Travel.

We’re going to add a page too, so go to pages > add new. Add a new page called with the title ‘Contact me’ and publish the page.

Now head to appearance > menus.

Delete the existing menu items, so you are only left with the homepage link.

From categories, add to our menu: WordPress, Web Design, and Travel. From pages, add the contact page. Give the menu the name ‘Main navigation’ and select ‘create menu’. Finally, check the box that says ‘primary’. Now save the menu.

Your menu should now look like this:

Go back to the homepage to take a look at the menu.

It still looks awful, but you now have a fully functioning, dynamic menu! We’ll get it looking a bit prettier soon enough.


One of the ways in which we can put our own mark on a website is to use some custom typography. A popular way of doing this is to use the Google fonts library.

I have two fonts in mind for Scribbleit. For the headings I want to use Roboto Slab, and for the body copy I want to use Roboto.

So head to Google fonts and search for ‘Roboto Slab’. Select it, and choose ‘select this style for regular 400 and bold 700.

Go back to the Google fonts homepage by clicking on the logo, and search for ‘Roboto’.

Add the following styles: regular 400, regular 400 italic, bold 700, and bold 700 italic. Your font selection should look like this:

Select the ’embed’ tab and you’ll find the embed code. Now, as with CSS files, there is a specific method in WordPress to load fonts, and that is by enqueueing them.

Leave the Google fonts tab open, and open functions.php in your code editor.

Underneath the CSS we enqueued in a previous lesson, add the following code:

    //    Google fonts
wp_enqueue_style( 'google-fonts', 'https://fonts.googleapis.com/css?family=Roboto+Slab:400,700|Roboto:400,400i,700,700i&amp;display=swap', false );      

The URL is taken from the Google fonts embed code. The rest of the function is the same as we use for loading CSS files.

Your functions.php file should now look like this.

Go and view the source code of your homepage and search for ‘Roboto’, to ensure the font is definitely being loaded.

Now that our desired fonts are being loaded, we can write some CSS to set the typography of our theme. But before we do that, let’s first look at…


Variables are a handy feature of SASS that allow us to assign a value to a name, and then throughout the rest of our CSS we can refer to the name, rather than the value. It’s probably easier if I just show you. At the very top of your styles.scss file, add:

/* - Variables

$orange: #e7450d;
$black: #525252;

We are creating two variables. They each refer to colour hex codes (which I always find difficult to remember).

What this means is that instead of writing ‘color: #525252;’, we can now write ‘color: $black;’.

Back to our typography

Now we have our variables in place, add the following CSS to the styles.scss, just above the site header section:

/* - Typography

h1,h2,h3,h4,h5,h6 {
font-family: 'Roboto Slab', serif;      
color: $black;

body, p, li {
font-family: 'Roboto', sans-serif;          
font-size: 18px;
color: $black;

This will ensure that all of our headings are Roboto Slab, and all other typography on the site will be Roboto. We are using the $black variable (although it’s actually a dark gray colour) for all typography throughout the theme.

Your styles.scss file should now look like this.

Styling the navigation menu

If you inspect the navigation menu using developer tools, you will see it is made up of an unordered list with the ID of #primary-menu, containing a series of list items, which contain the <a> tags (the links). Add the following CSS, below the header section:

/* - Primary menu

#primary-menu {
justify-content: flex-end;
    li {
    padding: 0 30px;
    &amp;:last-child {
    padding-right: 0;    
        a {
        font-family: 'Roboto Slab', serif;  
        color: white;
        font-size: 17px;
        transition: 0.3s ease all;
            &amp;:hover {
            color: $orange;    

In this code, we are taking advantage of SASS’s nesting feature, to keep our CSS neat and ensuring we are targeting only the elements we need to target.

To give our list items a bit of breathing space, we apply 30 pixels of padding to the left and right of each item. I use the &:last-child selector to ensure this padding does not apply to the last menu item (the one furthest to the right).

We target the anchor tags to set the typography for the menu. I want the menu items to use the Roboto Slab font in white, and I want them to transition to our orange colour when the user hovers over them.

For #primary-menu, we are using Flexbox to align our menu to the right-hand side of the screen (flex-end).

Completing our header

We’ve almost completed our header – just a few more tweaks to go.

Let’s add some padding to the header. At the moment the logo butts up against the top and bottom of the header.

Find the #masthead selector in your styles.scss file, and add:

padding: 20px 0;

This will add top and bottom padding to our header, and give the elements a bit of room to breathe.

The last thing I want to do is vertically centre the elements inside our header. At the moment our navigation menu is near the top of the header, rather than in the centre.

To do this, we are going to use a handy Bootstrap class.

Open your header.php file, and find the row we added that contains our logo and navigation menu. Add the class ‘align-items-center’ to it, so it becomes:

<div class="row align-items-center">

Go and check your homepage again and you should see everything in our header is now vertically centred.

Your header.php file should now look like this, and your styles.scss file should now look like this.

Congratulations for sticking with the tutorial this far! We now have a completed site header. Let’s keep going…

A few miscellaneous CSS tweaks

We just need to get a few CSS changes out of the way. Add the following block of code to your styles.scss file, just beneath the variables section:

/* - General styles

body {
background-color: #f5eeee;    

a:hover {
color: $orange;    

a:visited {
color: inherit;    

If you refer to the PSD mockup, you’ll see that the background colour of the body isn’t white, rather it’s a very light grey colour.

Next we are setting all links to have the hover colour of orange, and all visited links to inherit their colour, rather than being the default purple colour.

Your styles.scss file should now look like this. And your homepage should look like this:

The blog excerpt section

It wouldn’t be much of a blog if we only had the default ‘Hello World’ post on display. So let’s change that now by adding some blog posts to our website.

We are going to add six blog posts to our site. You can find them all within the course files (downloadable at the top of this tutorial), in the blog-posts directory.

Blog posts to add

Article 1

Title: My first time in the big apple
Featured image: new-york.jpg
Category: Travel
Text: as contained within blog-text.txt

Article 2

Title: 10 things I always take when I travel
Featured image: travelling.jpg
Category: Travel
Text: as contained within blog-text.txt

Article 3

Title: What’s new in WordPress version 5.0
Featured image: wordpress.jpg
Category: WordPress
Text: as contained within blog-text.txt

Article 4

Title: Is WordPress truly the best CMS?
Featured image: wordpress2.jpg
Category: WordPress
Text: as contained within blog-text.txt

Article 5

Title: What is SASS?
Featured image: sass.jpg
Category: Web Design
Text: as contained within blog-text.txt

Article 6

Title: Getting started with Flexbox
Featured image: flexbox.jpg
Category: Web Design
Text: as contained within blog-text.txt

Go and create those blog posts now! And while you’re at it, delete the ‘hello world’ blog post.

Your homepage should now look like this (plus the other 4 articles):

Ok, we’ve made some good progress. We have our blog posts displayed on the homepage.

It’s not exactly an optimal reading experience though, is it? In the next section we will whip our blog posts into shape.

Changing our blog posts to only display excerpts

What you’ll probably notice about our blog posts, is that WordPress is displaying the full text of each post. If we were to have 10 blog posts on the page, that would make for an incredibly long page. A better solution is to tell WordPress to just display an excerpt of the blog post, rather than the full post. The user then clicks on the excerpt in order to read the full post. Pretty standard practice for blogs.

Open up your index.php and we’ll take a look at what’s going on.

Find the commented line that says ‘Start the loop’. The WordPress loop is the code that displays blog posts and pages. It pulls in the title, body text, featured image, category, and any other information, for each post and outputs the data on the page.

We’ve already discussed the modular way in which Underscores is designed, and that modularity is used here within the WordPress loop. Look at this line:

get_template_part( 'template-parts/content', get_post_type() );

This is pulling through the code that is contained in the file content.php within the template-parts directory.

However, we do not want to use the content.php file, because that file will be used for our single blog posts. Instead we want to create a new file.

Open up content.php in your code editor (it’s inside the template-parts directory).

Now copy all of the code within this file.

Create a new file and paste in the code in your clipboard.

Save the file as content-excerpt.php and save it within your template-parts directory.

Now come back to the index.php file, and change the code so it reads:

get_template_part( 'template-parts/content-excerpt', get_post_type() );

What this means is that the code injected into the page will be from our newly created content-excerpt.php file, and not our content.php file.

Now open up content-excerpt.php. In here is the code that outputs the various components of our blog post. Look for the_content() (line 36). That is the code that outputs the full text of our blog posts. Delete the whole function.

In place of the_content(), we are going to add:


This tells WordPress that we only wish to display the post excerpt, not the full text.

Your content-excerpt.php file should now look like this, and your index.php file should now look like this.

Take a look at your homepage and you should see that only an excerpt of each blog post is displayed. Perfect!

Styling our blog posts

Our blog posts are much improved since we changed them to only display excperts, but they still don’t look great. But never fear, we can make them a bit prettier using some CSS.

If we inspect the blog post using developer tools, we find that each blog post has the class of .post, so let’s go and target this with CSS.

Open styles.scss and add the following code, below the primary menu section:

/* - Blog excerpts

.post {
background-color: #fff;  
padding: 30px;
border:1px solid #dddddd;
    .entry-title a {
    color: $black;
    text-decoration: none;
        &amp;:hover {
        color: $orange;    

In this code we are:

  • Changing the background colour of the posts to white, adding some padding around the posts, and giving them a subtle border.
  • ‘.entry-title a’ selects the headings. I’m changing their colour to our dark text colour and removing the underline. We also change their colour to orange on hover.

Looking better already! Still some work to do though.

I want to move the featured image above the blog title and meta information. We can’t accomplish this with CSS, so we need to change one of our template files.

Open up content-excerpt.php and look for:

<?php scribbleit_post_thumbnail(); ?>

This is the WordPress function that outputs the featured image (otherwise known as a post thumbnail).

What we want to do is cut this line, and paste it just below the code that reads <header class=”entry-header”>. This will ensure our featured image appears at the top of our blog post.

The content-excerpt.php file should now look like this.

Go and check your homepage and you should see the featured image is now above the title and meta information. Huzzah!

Styling the meta information

The meta information includes the date of the post and the post author. Let’s work on making this information a bit more presentable.

Take a look at the excerpt.content.php file and you will find <div class=”entry-meta”>. Inside this div, there are two functions – scribbleit_posted_on() and scribbleit_posted_by(). This is another example of modular design; these functions are contained within the ‘inc’ directory in ‘template-tags.php’.

Before we edit the code inside template-tags.php, first I want to include Font Awesome in our theme. Font Awesome is a free to use icon library, featuring hundreds of useful icons. We are going to use some of these icons to help represent our meta information.

Head to https://fontawesome.com/ and select ‘start for free’.

Enter your email address and select ‘send kit code’. Check your email; you should have received an email from Font Awesome containing the embed code.

You’ll notice the embed code links to a JavaScript file, not a CSS file. Instead of using wp_enqueue_style(), we use wp_enqueue_script().

Open up your functions.php file, and add the following code, just after the code we added to enqueue our Google fonts.

    //  JavaScript
wp_enqueue_script( 'wpb-fa', 'https://kit.fontawesome.com/793dbaab6b.js', array(), '1.0.0', true );

Replace the URL with the URL contained in your email from Font Awesome.

View the source code of your homepage and search for ‘font awesome’ to ensure the file is being loaded.

Your functions.php file should now look like this (but with your Font Awesome URL instead of mine).

With Font Awesome now available to us, open up your template-tags.php file again.

Find the code that says:

echo '<span class="posted-on">' . $posted_on . '</span>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped

This code is responsible for outputting the date of each blog post. Replace this code with:

echo '<span class="posted-on"> <i class="fas fa-clock"></i> </a>' . $posted_on . '</span>'; // WPCS: XSS OK.

You’ll see we have added the font awesome clock icon by including the code <i class=”fas fa-clock”></i>.

Check your homepage again and you should see the clock icon has been added to the meta information.

Let’s now remove the words ‘posted on’, so that we are just displaying the clock icon and the date of the post. It will look cleaner.

In your template-tags.php file, look for:

$posted_on = sprintf(
	/* translators: %s: post date. */
	esc_html_x( 'Posted on %s', 'post date', 'scribbleit' ),
	'<a href="' . esc_url( get_permalink() ) . '" rel="bookmark">' . 
        $time_string . '</a>'

and remove the words ‘Posted on’, so the code becomes:

$posted_on = sprintf(
         /* translators: %s: post date. */
	esc_html_x( '%s', 'post date', 'scribbleit' ),
	'<a href="' . esc_url( get_permalink() ) . '" rel="bookmark">' . 
        $time_string . '</a>'

Let’s now add the ‘user’ icon to our post author code.

In your template-tags.php file, find the code that says:

echo '<span class="byline"> ' . $byline . '</span>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped

and replace it with:

echo '<span class="byline"> <i class="fa fa-user"></i> ' . $byline . '</span>'; // WPCS: XSS OK.  

Check your homepage and confirm that the user icon is now being displayed.

Lastly, I want to remove the word ‘by’ from the meta information. In your template-tags.php file, look for this code:

$byline = sprintf(
	/* translators: %s: post author. */
	esc_html_x( 'by %s', 'post author', 'scribbleit' ),
	'<span class="author vcard"><a class="url fn n" href="' . esc_url( 
        get_author_posts_url( get_the_author_meta( 'ID' ) ) ) . '">' . esc_html( 
        get_the_author() ) . '</a></span>'

and remove the word ‘by’, so it becomes:

$byline = sprintf(
	/* translators: %s: post author. */
	esc_html_x( '%s', 'post author', 'scribbleit' ),
	'<span class="author vcard"><a class="url fn n" href="' . esc_url( 
        get_author_posts_url( get_the_author_meta( 'ID' ) ) ) . '">' . esc_html( 
        get_the_author() ) . '</a></span>'

Check your homepage again and confirm it’s looking like this:

Your template-tags.php file should now look like this.

Styling our meta information with CSS

Now we have our icons in place, it’s time to style our meta information using CSS. Open up your styles.scss file and add this code, below the code for .post:

.entry-meta {
color: #adadad;
text-transform: uppercase;
text-decoration: none;
font-size: 15px;
margin-top: -10px;
    a {
    color: #adadad;    
    text-decoration: none;
    .posted-on {
    margin-right: 10px;
    padding-right: 10px;
    border-right:1px solid #adadad;
    .fas, .fa {
    margin-right: 5px;    

The meta information is contained within a div with the class .entry-meta. In this CSS we are:

  • Giving the text a subtle grey colour, making it uppercase, and setting a negative margin to shift it up a bit.
  • .posted-on is our post date info. We are giving it some margin, some padding, and adding a subtle border on the right hand side.
  • Finally we are targeting our font awesome icons and giving them some right-hand margin.

Go and check your homepage and confirm the meta information is now looking like this:

Perfect! I know that took a long time just to change small piece of our theme, but that’s just the way it goes sometimes!

The category link

Let’s move on to styling the category link, found in each blog post.

Open up content-excerpt.php again and scroll down until you find <footer class=”entry-footer”>. You’ll see a function called scribbleit_entry_footer(). This is the function responsible for outputting the category link, and it can be found in template-tags.php.

Open your template-tags.php file and look for:

printf( '<span class="cat-links">' . esc_html__( 'Posted in %1$s', 'scribbleit' ) . '</span>', $categories_list ); 

We want to make a very simple change here, which is replacing the words ‘posted in’ with ‘category:’. So the code should now look like this:

printf( '<span class="cat-links">' . esc_html__( 'Category: %1$s', 'scribbleit' ) . '</span>', $categories_list ); 

If you and look at the homepage, you’ll see there is a ‘leave a comment’ link. I don’t think that’s necessary for a blog excerpt, so let’s delete it now.

Delete this block of code from the template-tags.php file:

		if ( ! is_single() &amp;&amp; ! post_password_required() &amp;&amp; ( comments_open() || get_comments_number() ) ) {
			echo '<span class="comments-link">';
						/* translators: %s: post title */
						__( 'Leave a Comment<span class="screen-reader-text"> on %s</span>', 'scribbleit' ),
							'span' => array(
								'class' => array(),
					wp_kses_post( get_the_title() )
			echo '</span>';

If you’re logged in, you will also see an ‘edit’ link. Let’s delete this too, to keep everything neat. Delete this block of code:

					/* translators: %s: Name of current post. Only visible to screen readers */
					__( 'Edit <span class="screen-reader-text">%s</span>', 'scribbleit' ),
						'span' => array(
							'class' => array(),
				wp_kses_post( get_the_title() )
			'<span class="edit-link">',

Your template-tags.php file should now look like this.

And your blog posts should now look like this:

Styling our category link

Now let’s use some CSS to style our category link. Open your styles.scss file, and add the following code, below the code for .entry-meta:

.cat-links {
position: absolute;
right: 10px;
bottom: 5px;
color: $orange;
font-size: 15px;
    a {
    color: $orange;
    font-size: 15px;
    text-decoration: underline;

.cat-links is the div containing our category links. Most of this CSS is to style the font.

You will notice that I have set the position of the .cat-links div to be absolute, and moved it to the bottom right of its parent div.

In order for this absolute positioning to work correctly, we must apply position:relative to the parent container, namely the .post div.

In your styles.scss file, add ‘position:relative;’ to the .post selector. The CSS should now read:

.post {
background-color: #fff;  
padding: 30px;
border:1px solid #dddddd;
position: relative;

The contents of the styles.scss file should now look like this.

Take a look at your homepage and you should see our orange category link in the bottom right of each of our blog posts.

Nice! Our blog posts are really coming together. We only have a few more tweaks to make. Stick with it 🙂

Adding a ‘continue reading’ button

Because we are displaying blog excerpts, the aim is for the user to click on the post in order to read the full article. Currently they can do this by clicking the post title or the featured image. But let’s make it even easier for them by adding a ‘continue reading’ button.

First let’s add the code for our button.

Open up content-excerpt.php and look for the <div class=”entry-content”> element. Immediately before the closing div tag, add:

<?php echo '<a class="button" href="' . get_permalink() . '"> Continue Reading</a>'; ?>

In this code we are outputting an anchor tag, with the class of ‘button’. For the href, we are adding the WordPress function get_permalink(), which will output the URL of this specific post (it will be different for each post).

Your content-excerpt.php file should now look like this. And your blog posts should look like this:

Great! With our link in place, we can now style our button by targeting the .button class. Open up styles.scss, and add this code to the end of the ‘general styles’ section:

.button {
color: $orange;
text-decoration: none;
border:1px solid $orange;
padding: 12px 30px;
text-transform: uppercase;
font-size: 15px;
transition:0.3s ease all;
    &amp;:hover {
    background-color: $orange;
    color: #fff;

This is all fairly standard CSS. We are changing the typography, padding and border of the button, and we are giving it an orange background colour on hover.

Go and take a look at your homepage and you should see our beautiful orange button in place. Clicking it takes you to the single blog post page. Perfect!

Creating some space between our header and our blog row

We are almost finished with our blog posts, but something you may have noticed is that our main content area is butting up against our header. This is not a good look!

To fix this, we are going to to have to add a margin.

Open your index.php file and find the <div class=”row”> code we added in a previous section. We are going to add another class to this div, so it becomes:

<div class="row main-content-row">

We can now target this row in CSS. Applying some top margin will move our main content away from our header.

Open styles.scss and add the following CSS inside the ‘general styles’ section:

.main-content-row {
margin-top: 60px;

Take a look at your homepage again and you should see some space between the main content area and the header.

Congratulations! Our blog post area is now complete. I hope you enjoyed learning how to manipulate blog posts in WordPress, and you’re looking forward to creating your own theme.

We’re not finished though! Onwards!

The sidebar

The sidebar of a theme is usually composed of widgets – chunks of useful code that perform a specific function. There could be a widget that displays recent posts, recent comments, a list of blog categories, and so on.

In this section we will take a look at our sidebar, and customise it to suit our needs.

As you’ve probably already seen, our homepage already contains a sidebar. This is because our index.php file is pulling through the code found in sidebar.php.

At the moment, though, it contains WordPress default widgets. Let’s go and amend the widgets that are being displayed. Head to the WordPress dashboard, select ‘appearance > widgets’. You’ll see there is one sidebar area, named ‘sidebar’.

Remove ‘search’, ‘archives’, and ‘meta’.

Add a text widget to the top of the widget area. Give it the title ‘About me’. Inside the text widget, add ‘about-me’.jpg from the course files. Add the following lorem ipsum:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum suspendisse ultrices gravida.

Save the widget.

Now go and take a look at your homepage. It should look like this:

Inspect the sidebar area using your browser’s developer tools, and you will see that the whole sidebar is contained within an ‘aside’ element with the ID of ‘secondary’.

Each widget has its own ID, and they all share the class of ‘widget’.

Each widget has a title, with the class of widget-title.

Inside each of our widgets there is a unordered list, which contains list items, which in turn contain anchor tags. WordPress outputs the contents of each widget into these list items, e.g. for the recent posts widget, each post will be contained within a list item.

Using this information, we can begin to target these elements.

Open your styles.scss file in your code editor, and add the following CSS to the bottom of the document:

/* - The sidebar

#secondary .widget {
background-color: #fff;
border:1px solid #ddd;
padding: 20px;
    .widget-title {
    text-align: center;    
    ul {
    padding-left: 0;
    margin-left: 0;
    list-style: none;
        li {
        border-bottom:1px solid #dcdcdc;
        padding: 6px 0;
            &amp;:last-child {
            a {
            color: $black;
            text-decoration: none;
            transition:0.3s ease all;
                &amp;:hover {
                color: $orange;    

There’s quite a lot of CSS there, so let’s unpack it a bit:

  • Firstly we are changing the background colour of each widget area, adding some padding, and applying a border. It’s the exact same styling we use for the blog posts.
  • Next we are setting the widget titles to be centre aligned.
  • We remove all of the margin and padding from our unordered list, and we get rid of the bullets. Even though it is an unordered list, we don’t want it to look like one.
  • For the list items, we are applying some padding and adding a bottom border. Using the last-child pseudo selector, we ensure the border does not apply to the last list item (looks neater that way).
  • Then we apply some typographic styles to the anchor tags (they don’t take effect if we apply them to the list items).
  • Finally we add our usual orange hover state to the links.

Save your styles.scss file and go and take a look at your homepage. It should look like this:

Much better!

One thing to note is that our ‘recent comments’ widget is empty. This is because we have no comments on our blog posts yet. We can fix this by clicking on our blog posts, scrolling down to the comments section, and leaving a random comment (the single blog posts still look a mess – don’t worry, we will fix that soon enough!). Here’s my ‘recent comments’ widget now with a few random comments added:

And that completes our work on the sidebar! Take a look at your homepage – is it just me or is it starting to look pretty good!?

The footer

If you take a look at our PSD mockup, you will see we want our footer to be split into four columns, with a widget in each column. This is a fairly typical layout for a WordPress theme’s footer.

As you would expect, the code for our footer is contained within footer.php. Open that file now in your code editor.

Currently our theme is displaying the message ‘Proudly powered by WordPress | Theme: scribbleit by Underscores.me‘. We need to delete the code that is displaying this message.

Delete the following code:

<div class="site-info">
            <a href="<?php echo esc_url( __( 'https://wordpress.org/', 'scribbleit' ) ); ?>">
		            /* translators: %s: CMS name, i.e. WordPress. */
		            printf( esc_html__( 'Proudly powered by %s', 'scribbleit' ), 'WordPress' );
            <span class="sep"> | </span>
		            /* translators: 1: Theme name, 2: Theme author. */
		            printf( esc_html__( 'Theme: %1$s by %2$s.', 'scribbleit' ), 'scribbleit', '<a href="http://underscores.me/">Underscores.me</a>' );
        </div><!-- .site-info -->

So you should just be left with:

<footer id="colophon" class="site-footer">
    <div class="container">
    </div> <!--container-->
</footer><!-- #colophon -->

We want to display a widget area in our footer, and in order to do so, we must first register a new widget area.

Open up your functions.php file and look for the code that reads: function scribbleit_widgets_init(). You will see the code that creates our sidebar, with the ID ‘sidebar-1’. We are going to use the same method to register our second sidebar.

After the ); of our first sidebar, add:

        register_sidebar( array(
            'name'          => esc_html__( 'Footer', 'intandem' ),
            'id'            => 'sidebar-2',
            'description'   => esc_html__( 'Add widgets here.', 'intandem' ),
            'before_widget' => '<div class="col-lg"><section id="%1$s" class="widget %2$s">',
            'after_widget'  => '</section></div>',
            'before_title'  => '<h2 class="widget-title">',
            'after_title'   => '</h2> ',
        ) );  

Your functions.php file should now look like this.

The code we used is almost exactly the same as the code in place for registering our first sidebar. We are giving the new sidebar the name ‘Footer’, and we are assigning it the ID ‘sidebar-2.

We have made an important amendment to the ‘before-widget’ and ‘after-widget’ parameters. In ‘before-widget’ we are adding <div class=”col-lg”>. This ensures we are containing our widgets in a column. Then in ‘after-widget’ we are closing our column using </div>. The widgets will now each be placed inside a column.

Open up your footer.php file, and modify the code so it reads:

<footer id="colophon" class="site-footer">

    <div class="container">
        <div class="row footer-row">
            <?php dynamic_sidebar( 'sidebar-2' ); ?>
    </div> <!--container -->

</footer><!-- #colophon -->

We are adding a row inside the container. This is because our footer will contain columns, and in Bootstrap columns must be contained within a row.

We are then using the dynamic_sidebar() function to specify we want to output our widget area with the ID sidebar-2.

Your footer.php file should now look like this.

Adding widgets to our footer widget area

With our widget area registered in our functions.php file, we can now go and add some widgets to it.

Head to your WordPress dashboard and go to appearance > widgets. You should see our new widget area – Footer.

Add the following widgets to the new widget area:

  • Text widget
  • Recent posts
  • Recent comments
  • Categories

Open the text widget we added, and give it the title ‘About me’. Select ‘add media’ and add ‘logo-white.png’ from the course files (the reason we are adding a white logo is that our footer background colour will be dark so the logo we used for in the header wouldn’t work).

Add the following lorem ipsum to the text widget:

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Quis ipsum.

Save the text widget and go and take a look at the homepage.

Not bad! Our four widgets are being displayed in a column, as we intended.

Styling our footer

Now we have our footer widgets in place, it’s time to open up styles.scss and apply some styling to our footer.

Add the following block of code to the bottom of your styles.scss file:

/* - Footer

.site-footer {
background-color: #313131;   
margin-top: 80px;
padding-top: 20px;
border-top:8px solid #ccc;
    .widget-title {
    color: #eee;
    font-size: 22px;
    border-bottom:1px solid #4a4a4a;
    padding-bottom: 10px;
    p {
    color: #adadad;    
    ul {
    margin: 0;
    padding: 0;
    list-style: none;
    color: #adadad;  
        li {
        color: #adadad;  
        border-bottom:1px solid #4a4a4a;
        padding: 4px 0;
            &amp;:last-child {
        a {
        color: #adadad;  
        text-decoration: none;
        transition:0.3s ease all;
            &amp;:hover {
            color: $orange;    

Let’s go through the CSS:

  • We start by targeting the footer itself, which has the class of .site-footer. We are giving it a dark background colour, some top margin so it’s kept away from our main content, and a top border (for no particular reason other than I like the way it looks).
  • Next we are setting the font properties of our widget titles.
  • We then target the unordered list and list items. We remove the margin and padding, and add a bottom border to each list item (with the exception of the last list item).
  • We target our anchor tags to change the font properties, and finally we update the hover state.

Go and take a look at your footer. It should look like this now:

Not bad at all! We now have a footer comprised of dynamic widgets. If I wanted to, I could add a social media widget, or a contact form widget, or whatever I want!

That concludes our work on the theme footer. And in fact, that concludes our work on our homepage. Go and take a look. I hope you agree it’s a decent looking theme homepage.

We are not done there though! We still have quite a few other pages to hammer into shape.

The single blog post template

If you click on one of the blog post excerpts you will be taken to the single blog post page. Currently, this page is a bit of a mess.

Click on any of the blog excerpts view the single blog post. Remember the plugin we added earlier to see what template is currently being served? Check the toolbar and you’ll see the template used for a single blog post is single.php. This is the template we will be working with in this section.

Open up single.php in your code editor and we will take a look.

It is very similar to the index.php file – it contains the WordPress loop, which pulls through code from content.php.

It also contains post navigation (for browsing to the previous post or next post), and the comments system. As with index.php, at the bottom of the file the template pulls through sidebar.php and footer.php.

The first thing we need to do is add a container, then separate our main content area and sidebar into columns.

Above the code that says <main id=”primary” class=”site-main”>, add:

<div class="container">
    <div class="row main-content-row">
        <div class="col-md-8">

This code opens our container, our row, and our 8 columns.

Now we need to close our 8 column div. We do so immediately after the closing main tag – </main>

Your single.php file should now look like this.

Our container div and our row div are both closed within sidebar.php, so we don’t need to close them. In fact, a lot of the hard work was already done when we were amending our index.php file.

Go and take a look at your homepage.

Wow, what a transformation! With very little editing, our single blog posts are now looking quite good. That is because they share so many elements with the blog excerpt page – the posts have the .post class, the meta information is the same, the sidebar is the same, etc. The only difference is that these pages display the full blog post, rather than just the excerpt (because they are using content.php rather than content-excerpt.php).

Post navigation

Below the blog post, you will see links to the previous and next blog posts. Let’s style these links so they look a bit nicer.

The first thing we are going to do is change the text so it only displays the words ‘previous post’ or ‘next post’, and we are going to add some Font Awesome icons to the links.

Open your single.php file, and look for this code block:

					'prev_text' => '<span class="nav-subtitle">' . esc_html__( 'Previous:', 'scribbleit' ) . '</span> <span class="nav-title">%title</span>',
					'next_text' => '<span class="nav-subtitle">' . esc_html__( 'Next:', 'scribbleit' ) . '</span> <span class="nav-title">%title</span>',

Replace this code with:

the_post_navigation( array(
            'prev_text'                  => __( '<i class="fa fa-angle-left"> </i>Previous post', 'intandem' ),
            'next_text'                  => __( 'Next post <i class="fa fa-angle-right"> </i>', 'intandem' )
        ) );

We are inserting a left-facing arrow to the previous link, and a right-facing arrow to the next link. Your navigation links should now look like this:

Inspect this element in developer tools and you’ll see they are contained within a div with the class of .nav-links. The previous link has the class .nav-previous, and the next link has the class .nav-next.

Open up your styles.scss file and add the following code to the bottom of the document:

.nav-links {
margin: 40px 0;
    .nav-previous a, .nav-next a{
    background-color: #fff;
    border:1px solid #ddd;
    padding: 15px 40px;
    display: inline-block;
    text-decoration: none;
    color: $black;
    transition:0.3s ease all;
    font-size: 15px;
        &amp;:hover {
        background-color: $orange;  
        color: #fff;
        .fa-angle-left {
        margin-right: 5px;    
        .fa-angle-right {
        margin-left: 5px;    

In this code we are basically turning the nav links into buttons – adding padding, a border and setting the typography. We are also applying a bit of margin to the Font Awesome icons.

Check the single blog post page again, the navigation links should now look like this:

Good work! I know it might seem a like a lot of work, but that’s what WordPress theme development is all about – lots of little elements that add up to create an awesome overall experience.

Styling the comments section

Next up we are going to style the comments section.

Open up your single.php file and you’ll find a block of code that reads:

// If comments are open or we have at least one comment, load up the comment template.
	if ( comments_open() || get_comments_number() ) :

This code is pulling through the code found in comments.php (but only if comments are enabled).

You’ll find the code that outputs the comments in comments.php. Take some time to go through the file and get a rough understanding of how comments are displayed.

We are not going to make any changes to comments.php, rather we are going to take what is already there and customise it using some CSS.

Open your styles.scss file and add the following code to the bottom of the document:

#comments {
    ol {
    list-style: none;    
    .comment-metadata {
    font-size: 12px;    
        a {
        text-decoration: none;
        color: #828282;
        .edit-link {
        margin-top: -5px;    
    .comment-body {
    margin-bottom: 20px;
    padding-bottom: 20px;  
    padding: 20px;
    background-color: #f5eeee;
    .says {
    display: none;    
    .comment-reply-link {
    font-size: 12px;
    padding: 0px 22px;
    display: inline-block;
    color: $black;
    text-decoration: none;
    margin: 0;
    transition:0.3s ease all;
    background-color: $orange;
    color: #fff;
        &amp;:hover {
        background-color: $orange;
        color: white;
    .comments-title {
    text-align: center;
    margin-bottom: 30px;    
    #comment {
    padding: 5px;    
    .children {
    list-style: none;    
    .comment-list {
    padding-left: 0;    
    margin-left: 0;
    #respond {
        #submit {
        border: 1px solid $orange;
        border-radius: 0px; 
        font-size: 13px;
        line-height: 1;
        padding: 15px 25px;  
        margin-top: -10px;
        transition:0.3s ease all;
        color: $orange;
            &amp;:hover {
            background-color: $orange;
            color: #fff;

There is quite a lot of code there, and that’s because the comments section is made up of lots of small components. We are not going to spend time going through each line of CSS. Please feel free to experiment for yourself. Either go through the code found in comments.php, or use developer tools to examine the different components of the commenting system.

The comments section should now look like this:

The category page (archive.php)

Let’s move on to the next template we want to update. One of the features of WordPress is the ability to filter posts by category. Selecting a category will display all of the blog posts within that specific category.

Navigate to a category now by selecting a category from the main navigation menu, or the ‘category’ widget in the sidebar.

It looks very similar to the single.php page before we added some structure to it.

Let’s go ahead and add our container and columns to the page.

Refer to the toolbar and you’ll see the template used for the category page is ‘archive.php’. Open this file in your code editor.

We are following the exact same process as we did for single.php. Before <main id=”primary” class=”site-main”>, add:

<div class="container">
    <div class="row main-content-row">
        <div class="col-md-8">

Then close the 8 column div immediately after the closing ‘main’ element – </main>.

We do not need to close the row div or the container div, as these are being closed within sidebar.php.

If you check the category page again, you’ll notice that the full blog post is being displayed. I think it would be better if we only displayed the excerpt.

So find the code that says:

get_template_part( 'template-parts/content', get_post_type() );

And change it to read:

get_template_part( 'template-parts/content-excerpt', get_post_type() );

This ensures our category page displays only the excerpt of the post and not the full post.

Your archive.php file should now look like this. Your category page should now look like this:

Perfect! Now when a user selects a category, they will be presented with only blog excerpts from that particular category. Clicking on an excerpt will take them to the single blog post.

It’s all starting to come together! Let’s keep going!

The page template

Another important template.php in our theme is page.php. This is the template that dictates how our pages will look. So if our website had an about us page, a services page, contact page, etc, the template being served would be page.php.

We have one page on our website – the contact page. Let’s amend our page.php file then add some content to our contact page.

Open page.php in your code editor, and take a look. You’ll notice that it looks very similar to our other template files – it includes the WordPress loop.

There is one main difference though. Look inside the loop and you’ll see:

get_template_part( 'template-parts/content', 'page' );

Page.php is pulling through content from content-page.php.

Select the ‘contact me’ page from the navigation menu. You’ll notice that it only contains the sidebar. That is because we haven’t added any content to our page within WordPress, and we haven’t added any bootstrap layout elements to the template file yet.

We are going to add the container, row and column to our page.php file, just the same way we did for the other template files.

Open page.php and just before <main id=”primary” class=”site-main”>, add:

<div class="container">
    <div class="row blog-row">
        <div class="col-md-8">

Then close the 8 column div immediately after the closing main tag. We won’t need to close the container or row, as they are closed in sidebar.php.

Your page.php file should now look like this.

Go and add some dummy text to the contact page. Just something simple like: “This is some dummy content”. Now take a look at the contact page.

You will notice that the page has the correct structure now (columns), but the main content area doesn’t look quite right. It doesn’t have our white background or border.

If you inspect the content using developer tools, you will see that the content area has the class .type-page. Our blog posts have the class .post. This is why our CSS is not taking effect on the page.

Open up styles.scss and add the following code at the bottom of the document:

/* - Page

.type-page {
background-color: #fff;  
padding: 30px;
border:1px solid #dddddd;    

Check your contact page again and you should see our content now has our white background, border and padding.

Adding content to our contact page

With our structure and styles in place, let’s add some actual content to our contact page. I want to add a contact form to the page, and to do that I’m going to use Contact Form 7.

Go to plugins > add new and search for contact form 7. Once installed and activated, select ‘contact’ from the WordPress menu.

You’ll see that a contact form, has already been set up for us. It contains fields for ‘name’, ’email’, ‘subject’ and ‘message’. That’s enough for our purposes, so copy the shortcode into your clipboard.

Now head back to edit the contact page. In the editor, write:

If you have any questions or comments about my blog, I would be delighted to hear from you. Simply fill out the contact form below and I will get back to you soon.

Then underneath that, paste in the shortcode you copied.

Save the page and take a look. It should look like this:

Not bad! It’s maybe not the prettiest contact form in the world, but it does the job.

And that concludes work on our contact page. Of course, it didn’t need to have been a contact page – we could have created an about us page, services page, or any other kind of page.


We have a few more templates to customise to ensure that every page a user might visit is properly formatted. Let’s work on the 404 page first, which as I’m sure you can guess it the page that is displayed when the user lands on a page that doesn’t exist.

Open the 404.php file and add our usual container/column code, immediately before </main id=”primary” class=”site-main”>:

<div class="container">
    <div class="row main-content-row">
        <div class="col-md-8">

Then close the 8 column div immediately after </main>.

Take a look at 404.php and you will notice that it doesn’t call the sidebar. Let’s change that now. Immediately before get_footer(); add:


Go to your browser and head to a URL that doesn’t exist on your website, such as localhost/scribbleit/kfrf5

You’ll see that our columns are in place, but the left-hand column needs a bit of work. At the moment the left-hand column is displaying our sidebar widgets, which isn’t ideal as our sidebar is now in place, displaying the same widgets.

In your 404.php file, delete everything contained within the <div class=”page-content”> div. Replace the contents with:

<p>Perhaps try returning to the <a href="<?php echo get_home_url();?>">homepage</a> and finding your way from there.</p>

This is inviting the user to return to the homepage. We output the URL of the homepage using the WordPress function get_home_url();.

Your 404.php file should now look like this.

Lastly, let’s give our 404 main content area our usual white background style.

Open up styles.scss and add the following code to the bottom of the document:

There! That’s a much better looking 404 page now.

Theme information and screenshot.png

Head to appearance > themes in the WordPress dashboard. You’ll notice that there is no image for our theme, and if you select ‘theme details’, the information is not relevant to our specific theme. Let’s change this now.

First let’s start with the screenshot. You can find the screenshot.png file we are going to use in your course files directory.

Copy screenshot.png and paste it into your theme directory, which in my case is c:\mamp\htdocs\Scribbleit\wp-content\themes\scribbleit. You will have to overwrite the existing screenshot.png in there.

Theme information

The information for our theme is contained within style.css (not our styles.css file!), which you can find in your theme directory. Open that file now and at the top you should see:

Theme Name: Scribbleit
Theme URI: http://underscores.me/
Author: Underscores.me
Author URI: http://underscores.me/
Description: Description
Version: 1.0.0
Tested up to: 5.4
Requires PHP: 5.6
License: GNU General Public License v2 or later
Text Domain: scribbleit
Tags: custom-background, custom-logo, custom-menu, featured-images, threaded-comments, translation-ready

To make this theme truly our own, we must update this information to make it specific to our own theme.

Here’s what mine looks like after updating it:

Theme Name: Scribbleit
Theme URI: https://wpthemeacademy.com
Author: David Sharkey
Author URI: https://wpthemeacademy.com
Description: A minimalist blogging theme
Version: 1.0.0
Tested up to: 5.4
Requires PHP: 5.6
License: GNU General Public License v2 or later
Text Domain: scribbleit
Tags: custom-background, custom-logo, custom-menu, featured-images, threaded-comments, translation-ready

Save style.css, go back to appearance > themes and check the theme details again. The theme information is now much specific to the Scribbleit theme.


And that concludes the first part of this guide to creating a custom WordPress theme from scratch.

How did you get on? I hope you managed to follow along and learned some new tricks.

If you have any feedback, please leave a comment below!

I’m working on a second part to this tutorial, which include page templates, custom post types, and more.

Thanks for reading, and take care.



Please enter your comment!
Please enter your name here