Skip to content

Part 1: Building A WordPress Theme

Calum Childs edited this page Nov 8, 2023 · 45 revisions

Hello and welcome to the Building a WordPress Theme tutorial! You'll learn how to build a basic WordPress theme from scratch to use on your own blog or website. Let's get started!

Getting the starter files

We're going to upload a blank(ish) WordPress theme to our website in our set up of our local environment. To get the files for this, just go to https://github.com/CalumChilds/your-wp-theme/archive/refs/heads/main.zip. Don't extract the .zip file, as you'll be uploading it to WordPress later on. Make sure you rename the zip file to your-wp-theme.zip.

Installation of local environment

We'll be using Local to create a local WordPress environment on our computer. This means you'll be able to run WordPress without having to worry about web servers or hosting fees!

Make sure you've downloaded and installed this software at https://localwp.com, then do the following:

  1. Click the + button on the bottom-left to create a local website.
  2. Select the "Create a new site" option, then click "Continue".
  3. Enter your website's name. This can be anything you want. Then click "Continue".
  4. Keep the "Preferred" option selected and press "Continue".
  5. For the username and password, use something simple that you'll remember (such as admin) for both the username and password. (When creating live WordPress websites, do make sure you set the username to something than admin and choose a strong password with letters, numbers and special characters.)
  6. Once you're done, click "Add Site".

Local will now create a local WordPress website. If you get any notifications about privileges being required (usually titled "Host Redirection"), just click on them and press "Yes".

Once the website is set up, select the "WP Admin" button (circled below:)

image

Then enter your username and password. You'll then be redirected to this page. Hover over "Appearance", then click on "Themes".

image

Next to the "Themes" heading, click the "Add New" button:

image

Then next to the "Add Themes" heading, click the "Upload Theme" button: image

Click Browse, then select the your-wp-theme.zip file we downloaded earlier and upload it. image

You should see something that looks like this. Click "Activate" to activate the theme onto your website. image

Go to the front page of your website where you should see a blank white screen. Don't worry about it! (there's a white screen because there isn't any PHP code in our theme yet!)

To get to your theme's code, open Locals and click the "Open Site Folder" button, as shown below:

image

Then navigate to the app/public/wp-content/themes/your-wp-theme folder.

Note: If you're using Windows, you can get straight to the folder by clicking the list of folders at the top of your screen then copying the path above (app/public/...). Or you can click through to the directory - up to you!

The basics of WordPress themes

WordPress is built using PHP and mySQL, but in recent years it has used React for the editor used to change posts and pages.

All WordPress themes must have these two files: index.php and style.css.

We will need more files than just these two, but the files we need are in the theme we just uploaded.

Next up, we'll be looking at the CSS of the theme and how you can customise it.

CSS

Open the theme's style.css file. At the top of the file, you'll see a comment that looks like this:

/*
Theme Name: Your WordPress Theme
Theme URI: http://yourwebsite.com/
Author: Your Name
Author URI: http://yourwebsite.com/
Description: This is your WordPress theme.
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: LICENSE
Text Domain: your-wp-theme
*/

The above CSS comment has to appear at the top of the theme's style.css file. It tells WordPress information about the theme and the people that made it. Feel free to change any of the default information.

Note: If you change the text domain, make sure to replace your-wp-theme with your own text domain in this tutorial.

This theme is designed so you can change the colours and fonts it uses easily just by changing a few lines of the CSS code. We're going to do this using CSS variables. We'll define them like this:

:root {
    --font-family: 'Arial', sans-serif;
    --background-colour: white;
    --main-colour: #111111;
    --paragraph-colour: #111111;
    --link-colour: blue;
}

You'll see how this comes in handy as we build our WordPress theme.

Setting up the theme's functionality

Before we start writing the theme files, we need to let WordPress know what features our theme supports. To do this, we need to create a your_wp_theme_setup() method in functions.php like this (you don't have to write the comments if you don't want to:)

<?php
function your_wp_theme_setup() {
		// Add default posts and comments RSS feed links to <head>
		add_theme_support( 'automatic-feed-links' );

		// Lets WordPress generate the <title> tag value for us
		add_theme_support( 'title-tag' );
		// Lets WordPress know that our theme allows us to add a featured image for each post/page
		add_theme_support( 'post-thumbnails' );
		// This theme uses wp_nav_menu() in one location.
		register_nav_menus(
			array(
				'menu-1' => esc_html__( 'Primary', 'your_wp_theme' ),
			)
		);
		// Adds support for HTML5 elements
		add_theme_support(
			'html5',
			array(
				'search-form',
				'comment-form',
				'comment-list',
				'gallery',
				'caption',
				'style',
				'script',
			)
		);
		add_theme_support('responsive-embeds');
		add_theme_support( 'customize-selective-refresh-widgets' );
		// Lets WordPress add CSS styling for Gutenberg block elements in our theme
		add_theme_support( 'wp-block-styles' );
		add_theme_support('custom-header');
	}
	add_action( 'after_setup_theme', 'your_wp_theme_setup' );

Now we've done that, let's tell WordPress how to display our content!

Displaying the content

First, we need to tell WordPress how we want to display content on the following page types:

  • blog posts
  • static pages
  • home page
  • search results

So let's get started!

Header and Footer

Firstly, we need to display the header and footer on all our pages. There are two built-in functions that allow us to do this: get_header() (which will get our theme's header.php file and output it's contents) and get_footer() (which will get our theme's footer.php file and output it's contents.) In all of your theme's .php files (except for functions.php, header.php and footer.php) enter this code into your files:

<?php get_header(); ?>

<?php get_footer(); ?>

Extra info: If you want to have multiple headers or footers in your theme (such as a different header for your home page or a different footer for your about page), you could declare your header function as get_header('home') which would get the header-home.php file if it existed and the default header file (header.php) if if didn't.

Then go into your header.php file and enter this code:

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="<?php echo get_stylesheet_directory_uri(); ?>/style.css">
<script src="<?php echo get_stylesheet_directory_uri(); ?>/script.js" type="text/javascript"></script>
<?php wp_head(); ?>
</head>
<body>
	<nav id="site-navigation" class="main-navigation">
			<button class="menu-toggle" aria-controls="primary-menu" aria-expanded="false">Menu</button>
			<?php
			wp_nav_menu(
				array(
					'theme_location' => 'menu-1',
					'menu_id'        => 'primary-menu',
				)
			);
			?>
	</nav>

The wp_head() function acts as a hook for plugins and core WordPress functions to add stylesheets and scripts to the website.

The wp_nav_menu() function gets the items in the primary menu.

Now go into your footer.php file and enter this code:

<footer>
<?php dynamic_sidebar('footer'); ?>
<p>&copy; <?php bloginfo('name'); ?> 2023 All Rights Reserved</p>
<?php wp_footer(); ?>
</footer>
</body>
</html>

Here's what the functions in this code are doing:

  • the wp_footer() function is similar to the wp_head() function, except it's for the footer. It should always be placed before the </body> tag.
  • the bloginfo('name') function gets the website's name.
  • the dynamic_sidebar('footer') function gets the footer widget and displays it here

We just need to register the footer widget we just created in our functions.php file within our your_wp_theme_setup method, like this:

	register_sidebar(
		array(
			'name' => esc_html__('Footer','your_wp_theme'),
			'id' => 'footer-widgets',
			'description' => esc_html__('Add footer blocks here', 'your_wp_theme'),
			'before_widget' => '<section id="%1$s class="widget %2$s">',
			'after_widget' => '</section>',
			'before_title' => '<h2 class="widget-title">',
			'after_title' => '</h2>',
		)
	);

Once you've saved that, at the top of your website, click the "Customize" button, which should take you to a screen that looks like this:

image

Click the "Widgets" option and then click the square + button to add a block. There are a wide variety of blocks you can add - pick a few and see what they do!

The Loop

If you're creating a blog, you'll want all your blog posts to be displayed on the front page of the website. The code that displays each blog post is called The Loop. Below is an example of a list of blog posts being displayed on a WordPress website:

image

To do this, go to index.php and on the line after the get_header() function, create an if statement like this:

<?php
<?php get_header(); ?>
<h1 class="site-title align-center">Welcome to <?php bloginfo('name'); ?>!</h1>
<h2 class="site-tagline align-center"><?php bloginfo('description'); ?></h2>
<?php
if ( have_posts() ) :
    while ( have_posts() ) :
        the_post();
?>
<div class="post">
    <h2 class="post-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
    <p class="post-excerpt"><?php the_excerpt(); ?></p>
    <a class="button" href="<?php the_permalink(); ?>">Read more...</a>
</div>
<?php endwhile; ?>
<?php endif; ?>
<?php get_footer(); ?>

There's several functions in The Loop. Here's what each of them do:

  • have_posts() checks to see if there are any posts
  • the_post() iterates the post ID that's being displayed in the loop
  • the_title() gets the post's title
  • the_excerpt() gets a preview of the blog post (usually the first 50 characters, but you can manually change the excerpt of a post if you wanted to)
  • the_permalink() gets the blog post's URL

Next up, we're going to be displaying individual posts and pages on our website.

Extra info: index.php is the default file used if WordPress can't find a template for what it's displaying in your theme (such as a blog post or page).

Posts and Pages

To display posts and pages differently, we'll need to use two different templates: single.php and page.php. The single.php template dictates how a blog post will be displayed. The page.php template dictates how pages are displayed.

Extra info: If there isn't a page.php template but there is a single.php template, it will use single.php to display the page.

In the single.php file, write this code on the line after the get_header() function:

<?php
    while ( have_posts() ):
      the_post();
?>
<h1 class="post-title"><?php the_title(); ?></h1>
<p align="center"><?php echo get_the_date(); ?> | <?php the_category(', '); ?></p>
<?php the_content(); ?>
<?php endwhile; ?>
<?php the_post_navigation(); ?>

Here's what each of those functions that we haven't seen already do:

  • the_content() gets the post or page's content
  • get_the_date() gets the date the blog post was published
  • the_category() gets all the categories that the blog post is part of and separates them with a comma and a space (', ')
  • the_post_navigation() displays links to the previous and next posts

The code in page.php is roughly the same as above, but with a few minor changes, as you'll see below:

<?php
    while ( have_posts() ):
      the_post();
?>
<h1 class="page-title"><?php the_title(); ?></h1>
<p align="center"><?php echo get_the_date(); ?></p>
<?php the_content(); ?>

Home Page

On some websites, for whatever reason, you want a custom home page rather than a list of blog posts. WordPress allows you to define this in your theme relatively easily in the front-page.php file!

image

image

image

image

Search Results

For our search results page, we'll use the same code as we did for index.php. The only difference will be that we'll display "Here's what we found for (search query)" if we find any results and "We couldn't find anything for (search query)" if we didn't.

Go into the search.php file and enter this code:

<?php get_header(); ?>
<?php
if ( have_posts() ) : ?>
<h1 class="page-title">Here's what we found for "<?php the_search_query(); ?>"</h1>
<?php
    while ( have_posts() ) :
        the_post();
?>
<div class="post">
    <h2 class="post-title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
    <p class="post-excerpt"><?php the_excerpt(); ?></p>
    <a class="button" href="<?php the_permalink(); ?>">Read more...</a>
</div>
<?php endwhile; ?>
<?php else: ?>
    <h1 class="page-title">We couldn't find anything for "<?php the_search_query(); ?>".</h1>
    <p class="align-center">Consider changing your query and trying again.</p>
    <?php get_search_form(); ?> 
<?php endif; ?>
<?php get_footer(); ?>

Customisation

And that's it, you've built your first WordPress theme! Feel free to change the default colours and font using the CSS variables at the top of style.css.

If you want to do some more work on your WordPress theme, have a look at the extension tasks below:

Extension 1: Install some plugins

There are over 60,000 WordPress plugins that you can install! Have a look and install some plugins that you like the look of (but don't install anything with WooCommerce in the name just yet, we'll be doing that next!)

Note: When you're creating your own WordPress websites, only install and activate plugins that are absolutely necessary. The more plugins you have, the slower your website will be and the more security vulnerabilities there could be in your website.

Extension 2: Try to make your WordPress theme release-ready

Most WordPress themes that are used on websites are on the WordPress Theme Directory. Using the WordPress Theme Developers Handbook and other resources, try to make your theme ready to be released into the WordPress Theme Directory.