A theme is a collection of code and resources that help render our content to a web page. In this article we will dive into the essentials of developing a theme.
Two types of themes
Themes were introduced with WordPress version 1.5, back in 2005, making the templating system more robust and flexible. Theme authors could implement different PHP templates for different parts of the site, and template parts made it easy to reuse common code.
Fast forward to 2022, version 5.9 introduced a new theme system. Templates no longer had to be PHP files but rather HTML, and with the introduction of blocks, full site editing was eventually possible. Since the old system is still supported, we refer to themes developed the old way as classic themes, as opposed to the new block themes.
Whatever way you choose to develop your theme, you will have to include at least two files: the main stylesheet and the default template.
The main stylesheet
When WordPress needs to discover the installed themes, it scans all folders in wp-content/themes
for files named style.css
that contain a special header. If it finds a file like that, the folder is considered the root of a theme. The header is a comment block containing at least a Theme Name
field, as illustrated below:
/*
Theme Name: Tutorial
*/
CSSThere are many other fields that you can add to the header. Below is a list of all other possible fields:
- Description: a desctiption of the theme
- Version: the theme’s version
- Theme URI: a URI that leads to more information about the theme
- Author: the theme’s author
- Author URI: a URI that leads to more information about the author
- License: the license under which the theme is released
- License URI: a URI to the full license text
- Tested up to: the last WordPress version the theme was tested against
- Requires at least: the minimum WordPress version the theme requires to function
- Requires PHP: the minimum PHP version the theme requires to function
- Text Domain: the string used for the textdomain for translations
- Domain Path: a path relative to the theme’s root that contains translations, if it’s different than
languages
- Tags: tags designating the theme’s features, separated with commas, preferably from this list
There is also a Template
field, but you should only include that in child themes.
The default template
Before we begin we have to note that, in classic themes, templates are PHP files located in the theme’s root folder. On the other hand, in block themes, templates are HTML files located in a templates
subfolder.
Now, when WordPress has to decide what template is most suitable for the content at hand, it utilizes a predefined template hierarchy. The ultimate fallback in that hierarchy is the default template, index.php
for classic themes or templates/index.html
for block themes. That’s why when developing a theme it is essential to include a default template.
A static example of a default template for a block theme would be the following:
<header>
<h1>Hello everyone</h1>
<p>This is my first theme.</p>
<hr>
</header>
<main>
<p>Welcome!</p>
</main>
HTMLIn order to achieve a similar result for a classic theme, we would create an index.php
with the following content:
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="profile" href="//gmpg.org/xfn/11">
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>">
<?php wp_head(); ?>
</head>
<body <?php body_class();?>>
<?php wp_body_open(); ?>
<header>
<h1>Hello everyone</h1>
<p>This is my first theme.</p>
<hr>
</header>
<main>
<p>Welcome!</p>
</main>
<?php wp_footer(); ?>
</body>
</html>
PHPIn both cases, WordPress will render the same HTML no matter what kind of content we are trying to access, because it will always use the same template. But before we start differentiating our templates, let’s take a look at another major feature.
The Functions File
Every theme needs some kind of unique functionality. This is where functions.php
comes into play. It is executed for every request before any content is rendered. However, it is not a mandatory file.
To start demonstrating functions.php
‘s use, let’s make some changes to our main stylesheet. Let’s suppose we want the header to align at the center, and also be blue:
/*
Theme Name: Tutorial
*/
header {
color: blue;
text-align: center;
}
CSSIf we refresh our page, we will notice that nothing changed. That’s because WordPress does not include the main stylesheet by default. And that’s true for both classic and block themes. Now, let’s create a functions.php
file in the root folder of our theme with the following content:
<?php
function tutorial_enqueue_scripts(){
wp_enqueue_style('tutorial-style',get_stylesheet_uri());
}
add_action('wp_enqueue_scripts','tutorial_enqueue_scripts');
PHPNow, if we refresh our page, we will see that our style is applied. Of course, this is not the only use of this file. It essentially contains the whole logic of the theme, outside of templates.
Template Parts
As we mentioned above, our example template renders the same content no matter what part of the site we are visiting. Let’s move forward a bit and diversify our templates. For example, let’s say we want to show the title and content of a post or page, and fall back to the Welcome! paragraph in all other cases. The <header>
part will be visible across the site.
It is obvious that now we need two different templates with a common header. Let’s do that using template parts, for both classic and block themes.
For classic themes
As you might have noticed, in our classic version of the default template we included all the HTML/PHP needed to render our content. That means that we have common parts across templates, both above and below the <main>
section. Consequently, we have to create two template parts in the root folder of our theme.
A header.php
:
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="profile" href="//gmpg.org/xfn/11">
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>">
<?php wp_head(); ?>
</head>
<body <?php body_class();?>>
<?php wp_body_open(); ?>
<header>
<h1>Hello everyone</h1>
<p>This is my first theme.</p>
<hr>
</header>
<main>
PHPAnd a footer.php
:
</main>
<?php wp_footer(); ?>
</body>
</html>
PHPOur index.php
will now look like this:
<?php get_header(); ?>
<p>Welcome!</p>
<?php get_footer(); ?>
PHPAnd finally we need to create a singular.php
in the theme’s root folder:
<?php get_header(); ?>
<h1><?php the_title(); ?></h1>
<div><?php the_content(); ?></div>
<?php get_footer(); ?>
PHPFor block themes
Evidently, in a block theme we don’t have to include all the HTML needed, so we will only need a header template part and two templates. Template parts are stored in a special parts
folder, so a parts/header.html
file would look like this:
<h1>Hello everyone</h1>
<p>This is my first theme.</p>
<hr>
HTMLOur modified templates/index.html
would be the following:
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<main>
<p>Welcome!</p>
</main>
HTMLLastly, we would have to create a templates/singular.php
like so:
<!-- wp:template-part {"slug":"header","tagName":"header"} /-->
<main>
<!-- wp:post-title {"level":1} /-->
<!-- wp:post-content /-->
</main>
HTML
1 thought on “Developing a Theme – The Essentials”