In this article, we will be exploring how WordPress theme files work, how WordPress treats them, and the basic functions
to work with the theme files.
Note: to follow through this guide, you must at least know beginner HTML and CSS. If you are unfamiliar with the
two technologies mentioned, read my beginner HTML guide and beginner CSS guide.
As you may already know, a WordPress theme changes your website's appearance, but what exactly is a WordPress theme, and
how do you make one?
WordPress Theme Files
At its barest form, you only need three entities:
- The folder where your theme files live: The folder's name should reflect your theme's name (e.g. twentytwentythree, vws-bs-starter).
- The index.php file: The file that renders the HTML file.
- The style.css file: The file that contains your theme information.
PHP and HTML files
PHP is a programming language used by WordPress as part of its technology stack. You can embed HTML inside
PHP files (.php). Using PHP to write complex scripts can enhance your website's functionalities, making it
a dynamic website.
The index.php
file
Think of the index.php
file as an entry point to your website. That is, if a user enters your site in their browser,
they will see whatever your index.php
file renders. Even if the file only contains HTML tags, it is still a valid
PHP page that WordPress can render.
The style.css
file
This file contains all of your theme's information and CSS styles. You only need the header part which contains all the
theme's information— even without any CSS styles —to make your theme valid.
Here's an example of the header part of a style.css
file in WordPress:
/*
Theme Name: Twenty Twenty
Theme URI: https://wordpress.org/themes/twentytwenty/
Author: the WordPress team
Author URI: https://wordpress.org/
Description: Our default theme for 2020 is designed to take full advantage of the flexibility of the block editor. Organizations and businesses have the ability to create dynamic landing pages with endless layouts using the group and column blocks. The centered content column and fine-tuned typography also makes it perfect for traditional blogs. Complete editor styles give you a good idea of what your content will look like, even before you publish. You can give your site a personal touch by changing the background colors and the accent color in the Customizer. The colors of all elements on your site are automatically calculated based on the colors you pick, ensuring a high, accessible color contrast for your visitors.
Tags: blog, one-column, custom-background, custom-colors, custom-logo, custom-menu, editor-style, featured-images, footer-widgets, full-width-template, rtl-language-support, sticky-post, theme-options, threaded-comments, translation-ready, block-styles, wide-blocks, accessibility-ready
Version: 1.3
Requires at least: 5.0
Tested up to: 5.4
Requires PHP: 7.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: twentytwenty
This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you've learned with others.
*/
You can read more about what each of the properties does in this WordPress article.
As simple as it may seem, that's all you need to start making a custom WordPress theme.
WordPress Template Files Introduction
As you have learned previously, the index.php
file is the main entry point for users visiting your site, but that is
only true if that is the only template file present in your theme.
A template file, like index.php
, is what WordPress displays based on what page the user is currently at.
Consider the following scenario:
- You created an About, Contact, and Services page.
- You published a couple of blog posts.
- A user visits your Contact page.
WordPress knows a user is viewing your Contact page, but how does it display the contents of your Contact page to the user?
That is where template files come in.
If you only have the index.php
template file present in your theme, WordPress will display the contents of
index.php
no matter which page the user is currently at.
Types of Template Files
There are a lot of template files available, but we will be only covering a few. At least few enough to be an effective
WordPress developer.
As you have already discovered, there are two types of Post Types in WordPress: the inconveniently named Post and Page.
Posts (blog posts) appear on your home page (blog list) when you first install WordPress. Pages, like About and Contact,
don't appear on your blog list, and don't have the ability to set categories, but can be hierarchical.
- The template file for the Post post type is
single.php
.
- while the template file for Page post type is
page.php
.
If you put both template files with distinct contents in your theme, you should see how WordPress automatically determines
which template file is displayed based on whether you're in a blog post or a page.
But what happens to the index.php
template? It becomes the fallback template file. If you remove single.php
for
example, WordPress will use the index.php
template when viewing a blog post.
As you can see, WordPress maintains a template hierarchy to determine which template to load when you're in a specific
page. In the end, everything falls back to the main template file which is index.php
, and that is the reason why
it is required.
You can read more about the WordPress Template Hierarchy here.
WordPress Template Files is just a glorified file organization system
We can create a fully functional theme that renders different page templates with only the index.php
file.
As absurd as it may sound, it is possible with the help of conditional rendering with PHP. Basically, it's just a series
of decision-making:
- If a user is in a Post post type, display this code.
- Else, if a user is in a Page post ype, display this code instead.
- Else, if a user is in a blog list, display this code that lists all my blog posts.
- And so on...
But why do that and produce thousands of lines of code in one file if you can organize your code nicely through template
files.
Special Theme Files
Apart from the template files, WordPress has essential and non-essential theme files. Essential in a sense that it is
required if you're planning to release your theme in the WordPress theme repository.
Here are some of the commonly used theme files:
header.php
- You can add all the header-related code inside this file.
footer.php
- Similar to header.php, you can add all the footer-related code inside this file.
sidebar.php
- If your website design includes a sidebar, you may add all the sidebar code here.
comments.php
- WordPress supports comments, this file contains all the comments-related code (the form and the list).
searchform.php
- Aside from comments, WordPress has its own search function, you can customize the default search form with this file.
These files act like template files, but unlike template files where WordPress automatically selects and loads depending on context,
theme files are only loaded when a related function is manually called.
You have probably figured out by now that these files are used to avoid repeating code throughout your template files.
To elaborate, instead of adding the header-related and footer-related code to every template file you use, why not write
the code once in one file and call a one-liner function to render the code on where the function is called.
As an example, assuming you already have the header.php, footer.php, and sidebar.php in your theme, you can easily call
them like this:
<!-- page.php -->
<?php get_header(); ?>
<main>
<h1>This is the page title</h1>
</main>
<?php get_sidebar(); ?>
<?php get_footer(); ?>
WordPress then finds the correct theme file and includes it within your template file. This is what makes PHP and WordPress
incredibly powerful. Without much experience with PHP, you're able to figure out what it does.
The three WordPress-specific functions above are wrapped in PHP tags; this is how you embed PHP scripts inside PHP files.
There are more things to uncover to help enhance your theme and improve your development skills, which we will be exploring
next through the use of starter themes.
WordPress Starter Themes
These special types of WordPress themes help speed up the development process by setting up the necessary files and
helpful functions, getting rid of a lot of overhead. To fully understand WordPress theme development,
you need to at least know the basics of PHP.
Without overcomplicating this guide by covering PHP, I'll put you up to speed by learning PHP through
WordPress the hard way.
Forget PHP for now, let us explore a sample starter theme first and set it up to make it our own.
If you search the internet for "wordpress starter themes" you'll find hundreds of them, but my favorite is Underscores.
Download an Underscores' base theme by generating one. This will set up the starter theme with the details you submit.
If you have downloaded another starter theme, be sure to follow their instructions on how to set up their theme as yours,
but it usually goes like this:
- Rename the starter theme folder.
- Change the Theme Name attribute in the style.css header.
Now that you have your starter theme somewhere on your computer, you can start using it by uploading it to your WordPress site, here's a video on how to do that.
Starter Theme Files
If you check the starter theme files, you will find the template and theme files we covered previously, which you're
already familiar with.
Here is the file structure of an Underscores-based theme named "sample-starter".
sample-starter
├── 404.php
├── LICENSE
├── README.md
├── archive.php
├── comments.php
├── composer.json
├── footer.php
├── functions.php
├── header.php
├── inc
│ ├── custom-header.php
│ ├── customizer.php
│ ├── jetpack.php
│ ├── template-functions.php
│ └── template-tags.php
├── index.php
├── js
│ ├── customizer.js
│ └── navigation.js
├── languages
│ ├── readme.txt
│ └── sample-starter.pot
├── package.json
├── page.php
├── phpcs.xml.dist
├── readme.txt
├── screenshot.png
├── search.php
├── sidebar.php
├── single.php
├── style-rtl.css
├── style.css
└── template-parts
├── content-none.php
├── content-page.php
├── content-search.php
└── content.php
It's overwhelming seeing a lot of files to work with, but we won't be covering all of them. You only need to understand
the files in a higher-level.
To easily make sense of all the files, let's categorize the files starting from what we already covered previously:
template files, and theme files.
WordPress maintains a template hierarchy to determine which template to load when you're in a specific
page.
Template Files
File name |
What is it used for? |
404.php |
The template loaded by WordPress when a visitor reaches a page that doesn't exist: Error 404. |
archive.php |
The template used when a user visits an archive page: date, author, category, tag. |
index.php |
The main template file, which all template files fall back into. |
page.php |
Used when a user visits a Page post type. |
search.php |
If a user searches for something using a search form, this template is loaded to display the search results. |
single.php |
Used when a user visits a Post post type. |
Moving on with the theme files.
Unlike template files where WordPress automatically selects, theme files are only
loaded when a related function is manually called.
Theme Files
File name |
What is it used for? |
comments.php |
This template is loaded in a location where the comments_template() function is called. |
footer.php |
Loads the template when the get_footer() function is called. |
header.php |
Loads the template when the get_header() function is called. |
sidebar.php |
Loads the template when the get_sidebar() function is called. |
Before we move forward to the remaining files, let us explore how there are two types of template files.
Template Files, Dynamic Content and the WordPress Loop
Looking at a higher-level, we now see that there are two types of template files:
- Singular templates
- List templates
To put it plainly, singular templates are used when a user visits a singular WordPress page; that is, when a user visits
one of the pages you made (Contact, About) or a blog post you published.
In contrast, list templates are used for pages that list something. The most obvious example for this is the home page
when you first install WordPress, which is actually a blog list page. Other pages that use the list templates are the
archive ("show me a list of posts from this author/date/category/tag") and search results page.
We have only covered template loading with static content in mind. For example, if your page.php
file only contains
the following code, you will get the same content no matter what page you're viewing.
<h1>Welcome to my page</h1>
To display the page title and content dynamically, you will need the WordPress Loop.
<?php
while(have_posts()) // PHP while loop
{ // Opens the code block
the_post(); // Sets up the post/page's data
the_title(); // Displays the post/page's title coming from the data loaded
the_content(); // Displays the post/page's content body
} // Closes the code block
?>
Here we have a PHP script that displays the title and the content of a page (assuming we're in one). You will see a
variation of this code everywhere, especially in template files, which is commonly called the WordPress Loop.
Let's go through it line-by-line.
while( have_posts() )
- The while( condition ) control flow statement is a PHP loop that runs the contents of its code block infinitely, unless the condition resolves to false.
have_posts()
- The have_posts() inside the while() statement is a WordPress function that returns a condition. Specifically, this function checks if a post (or page) exists, returning either true or false.
the_post()
- This function sets up the post's data for the loop-specific functions to work correctly.
the_title()
- This function displays the post's title. This is a loop-specific function, that is, functions that will only work correctly inside the loop.
the_content()
- Another loop-specific function. This function displays the formatted post's content.
Whether you're in a singular or in a list template, the same WordPress Loop is used. Think of it as WordPress providing
the data (post or list of posts) to a page through the Loop, and it is up to you what to make of it.
Function and Template Parts
Back to the remaining theme files, if we remove what we have already covered, this is what is left:
sample-starter
├── LICENSE
├── README.md
├── composer.json
├── functions.php
├── inc
│ ├── custom-header.php
│ ├── customizer.php
│ ├── jetpack.php
│ ├── template-functions.php
│ └── template-tags.php
├── js
│ ├── customizer.js
│ └── navigation.js
├── languages
│ ├── readme.txt
│ └── sample-starter.pot
├── package.json
├── phpcs.xml.dist
├── readme.txt
├── screenshot.png
├── style-rtl.css
└── template-parts
├── content-none.php
├── content-page.php
├── content-search.php
└── content.php
We can further clean it up by skipping the files we're not covering in this guide. The theme would still work without
the files, as long as any references to them in the code are removed.
Here are the skipped files:
sample-starter
├── LICENSE // Theme license information - if you intend to distribute your theme.
├── README.md // Readme text used by git repositories like github.
├── composer.json // Used by a PHP package manager called Composer to install PHP packages.
├── languages // Language-related, so your theme could be translated. functions.php file has a reference to this folder, be sure to remove it when removing this folder.
│ ├── readme.txt
│ └── sample-starter.pot
├── package.json // Used by a JavaScript package manager called NPM to install JavaScript packages. Like Composer mentioned above.
├── phpcs.xml.dist // PHP Code Sniffer related file. Used to validate PHP coding standards. This is mainly used to assist you with the WordPress-specific PHP formatting standards, especially if you're planning to release your theme to WordPress.
├── readme.txt // Used by WordPress to display your theme's information.
├── screenshot.png // Used by WordPress to display your theme's thumbnail.
├── style-rtl.css // Styles for right-to-left languaged websites. This is not required, but some languages like Arabic is read from right to left, so it's logical to place the logo on the right side instead of the left which is common for English websites.
And this is what's left:
sample-starter
├── functions.php
├── inc
│ ├── custom-header.php
│ ├── customizer.php
│ ├── jetpack.php
│ ├── template-functions.php
│ └── template-tags.php
├── js
│ ├── customizer.js
│ └── navigation.js
└── template-parts
├── content-none.php
├── content-page.php
├── content-search.php
└── content.php
Functions
functions.php
in WordPress acts like a plugin for your theme. It is where all the theme setups are initiated like setting up
the WordPress menu locations, sidebars, and loading additional CSS styles and JavaScript.
Aside from the theme setups, theme developers add custom PHP functions inside this file, and it will be available through all
the files in your theme.
In the case of the Underscores starter theme, they've added all the functions they think are necessary to help you speed
up theme development with the goal of releasing your theme to WordPress. They have also categorized these functions into
individual files, which can be found inside the inc
folder.
Function Files.
File name |
What is it used for? |
functions.php |
Main functions file, where you can find all the necessary functions in setting up your theme. |
custom-header.php |
Functions to set up WordPress custom header: a feature that enables customizing the header of your theme via a GUI in the backend. |
customizer.php |
A boilerplate function to help you add customizer-specific code to improve the WordPress Customizer screen. |
jetpack.php |
Functions to enable or assist you with Jetpack-specific features. Jetpack is a WordPress theme that enhances your website's features. |
template-functions.php |
Functions which enhance the theme by hooking into WordPress. Hooks are a more advanced feature of WordPress development. |
template-tags.php |
Custom functions specific to the theme. One example is a function you can call to output the "posted by {author}" directly. |
*Non-emphasized file names are a bit advanced and can be skipped for now.
If you know enough PHP, going through each file would give you at least an idea of what the functions do, which is also
easier with the help of code comments.
Scripts
Inside the js
folder in the Underscores theme root, you'll find the following JS scripts that are loaded by default:
customizer.js
- Used in conjunction with inc/customizer.php
to improve WordPress Customizer experience.
navigation.js
- Script to improve the menu experience in mobile and accessibility.
Template Parts
Template Parts is another way to organize code which can be used to dynamically load files.
You can render whatever PHP file in your theme with a single WordPress function:
get_template_part();
Say if you want to render the contents of template-parts/content-page.php
you can do it like this.
get_template_part('template-parts/content-page')
// OR
get_template_part('template-parts/content', 'page')
Note how we omitted the .php file extension.
The first example loads content-page.php
as is, if it can't find the file, it will render nothing.
The second example loads content-page.php
, but if it can't find the file, it will fall back to content.php
which should
also be inside the template-parts
folder.
In the case of Underscores, the authors created four template files inside the template-parts
folder.
- content-none.php - Template to load when there are no posts found. Mainly used in blog lists, archive, and search results pages.
- content-page.php - Template for loading a Page's content.
- content-search.php - The template loaded for each post in a search results page.
- content.php - Template loaded for both the blog list and Single post, and is also the fallback file for all template parts.
Summary
In this article, we've explored the essentials of theme development by delving into the basics of how theme files function.
While we haven't delved deep into the code, grasping WordPress's approach to theme files provides a strong foundation for entering the world of theme development.