How to Create a WordPress Theme: 5-Step Process with Code

How to Create a WordPress Theme: 5-Step Process with Code

A WordPress theme lets you have a consistent layout for your web pages and posts, changing the entire website’s appearance. That said, installing a pre-made WordPress theme might prevent you from having complete control over its functionality and design. 

Luckily, you can build a WordPress theme from scratch to fully customize your WordPress website as you wish. Additionally, creating a WordPress theme from scratch helps reduce code clutter in the theme files and improve site performance.

However, you will need to have some coding basics to make your own theme, as it has to be written in PHP, HTML, CSS, and Javascript. Thus, this tutorial will show you how to create a WordPress theme using HTML5 and CSS3. 

Download Complete HTML Cheat Sheet

Step 1. Create and Store the Template Files
Step 2. Set Up the Initial CSS Stylesheet
Step 3. Make the WordPress Theme Functional
Step 4. Build a Layout for Your Custom Theme
Step 5. Improve Your Design on the CSS Stylesheet

HTML5 is the latest version of the HTML web markup language that helps display content consistently on any computer, tablet, or mobile phone. 

Furthermore, HTML5 offers a viewport meta tag feature that controls the display of your website on every browser with the <meta> tag inside the <head></head> tag.

To make a fully responsive custom WordPress theme, you can also use the CSS3 media queries feature. It sets specific rules and controls how your site will behave on various screen sizes.

Consider installing WordPress locally when developing a theme. This is a great way to experiment with WordPress themes without worrying about damaging your live website. You also don’t need to have a domain name or web hosting until you want to go online.

With that out of the way, let’s get into the steps of making a custom WordPress theme. We will apply both the viewport meta tag and the media queries while building it.

1. Create and Store the Template Files

Generally, WordPress themes can be created using just two template files in the theme directory: 

  • index.php – prepares a template for the theme to display its content.
  • style.css – manages the visual appearance of the theme.

However, WordPress theme development will also require several supporting files to add more flexibility when customizing. Those template files include:

  • header.php – contains any HTML that goes at the top of your pages, starting from <!DOCTYPE html>.
  • footer.php – holds the HTML that goes at the bottom of your website, including </html>.
  • functions.php – adds functionality to the theme, from menus and colors to scripts and stylesheets.
  • sidebar.php – generates sidebar elements.
  • single.php – displays a single post from a particular page.
  • page.php – shows the content of a single page.

As the theme developer, you’re free to customize each template file. WordPress will then choose and generate templates based on the template hierarchy. It will browse through it until a matching file is found, and display the page accordingly.

With that in mind, create a new folder for the components within your WordPress themes folder before building a WordPress theme from scratch.

Pro Tip

The folder’s name shouldn’t be the same as another theme’s name. Additionally, if you plan to share your work, check that there’s no theme with the same name on the WordPress.org Theme Directory.

Once you have a folder to store the theme, create the essential WordPress template files. Each PHP template file must use the correct name as defined in the WordPress documentation.

Note that to make different layouts for your posts, pages, and other parts of your website, you have to create separate templates containing HTML5 and PHP that apply to each section.

Pro Tip

If you wish to use custom post types, you can create templates that only apply to posts of that type. However, if you want posts from a specific category to have different styles, use if-then statements inside the loop.

Now, onto the steps:

  1. Access the File Manager section on your hPanel. Then, head over to public_html -> wp-content -> themes folder.
  2. Create a new folder. Note that the folder should have a unique, descriptive, and short name. Don’t use numbers or spaces.
  3. We’ll use my-theme in this example. 
  4. We are going to create the custom templates first and focus on the content later on. The files include header.php, index.php, footer.php, functions.php, sidebar.php, single.php and page.php
Hostinger's File Manager, showing what the custom my-theme folder looks like inside, containing the custom PHP template files

Now that you have all of the PHP template files ready, let’s move on to setting up the CSS stylesheet.

2. Set Up the Initial CSS Stylesheet

CSS stylesheets control the visual design and layout of website pages. Every WordPress theme needs a stylesheet in order to display elements such as fonts and colors. Without a CSS file, WordPress won’t recognize your custom theme as a valid one.

With this in mind, create a stylesheet file in the same theme folder. Add the necessary information, including the theme’s name, version, description, and author at the top of the style.css file. WordPress will display these details in the admin control panel.

The information must be written as a multi-line CSS comment, each header in its own line, starting with a keyword. Find the full list of header keywords for themes on the WordPress Codex – File Header page. 

Here is an example:

/*
Theme Name: My Theme
Author: Hostinger
Author URI: http://www.hostinger.com/tutorials
Description: My first responsive HTML5 theme
Version: 1.0
License: GNU General Public License v3 or later
License URI: http://www.gnu.org/licenses/gpl-3.0.html
*/

Pro Tip

The last two lines are required if you wish to share your theme on WordPress.org. If you’re going to use the theme for your own WordPress website, you don’t need to include them.

At this point, your theme will already be visible on your WordPress dashboard. Go to Appearance -> Themes and you will see My Theme with a white and gray checker box image. 

WordPress dashboard theme selection menu with the new custom theme highlighted

However, you will get a blank homepage if you activate the theme. This is because your index.php file is empty and there are no templates available. 

Add a single rule to the CSS file that changes the background color of the page. Insert a blank line after the comment closure */ on the 10th line. Then, paste the following code below it:

 * {
  box-sizing: border-box;
}

body {
    background-color: #f9f9f9;
    font-family: Helvetica;
}

Let’s understand this code by breaking it down. 

The first entry is an important part of responsive styling. <*>, or the asterisk symbol, matches every single element in the HTML document. It states that the final width and height of every item on the page should include content, padding, and border. Hence, this rule effectively adds the padding inside the box instead of outside it.

Meanwhile, the second element changes the background color to white and sets the default font that will be used in the theme.

Keep in mind that the above code only adds basic elements to your custom theme. We will go back to the style.css file once we have configured the other files and the overall website structure is ready.

3. Make the WordPress Theme Functional

Prior to the WordPress theme development process, we recommend adding a few pieces of code to your functions.php and sidebar.php files to enhance the theme’s flexibility. For example, add widgetized areas or create post thumbnails and featured images on specific pages.

functions.php

Each browser has different default settings for elements like page margins and padding. Because of this, you need to do a CSS normalization to ensure your theme has the same style and behavior across all browsers. 

To achieve this, include a CSS file named normalize.css in your functions.php file. This file will allow browsers to consistently display your site regardless of those elements.

To create one, insert the following code into functions.php:

<?php
// This function enqueues the Normalize.css for use. The first parameter is a name for the stylesheet, the second is the URL. Here we
// use an online version of the css file.
function add_normalize_CSS() {
   wp_enqueue_style( 'normalize-styles', "https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.min.css");
}

add_action('wp_enqueue_scripts', 'add_normalize_CSS');

This code will prompt WordPress to pick the normalize.css file from the attached source

Next, enable the sidebar widgets by adding the following code after the previous function:

// Register a new sidebar simply named 'sidebar'
function add_widget_support() {
               register_sidebar( array(
                               'name'          => 'Sidebar',
                               'id'            => 'sidebar',
                               'before_widget' => '<div>',
                               'after_widget'  => '</div>',
                               'before_title'  => '<h2>',
                               'after_title'   => '</h2>',
               ) );
}
// Hook the widget initiation and run our function
add_action( 'widgets_init', 'add_widget_support' );

Important! If you omit this code snippet, the widgets menu link will not be visible in the admin control panel, and you won’t be able to add any widgets.

Then, register a custom navigation menu to enable the Appearance -> Menu feature. Add the following code:

 // Register a new navigation menu
function add_Main_Nav() {
  register_nav_menu('header-menu',__( 'Header Menu' ));
}
// Hook to the init action hook, run our navigation menu function
add_action( 'init', 'add_Main_Nav' );

Once done, Save & Close the file.

sidebar.php

The next thing to take care of when creating a WordPress theme is displaying the sidebars. To do so, use the get_sidebar() function – it allows the sidebar and widgets to appear wherever in your theme. 

Insert the code below into the sidebar.php file. Then, save the changes.

<?php if ( is_active_sidebar( 'sidebar' ) ) : ?>
  <aside id="primary-sidebar" class="primary-sidebar widget-area" role="complementary">
    <?php dynamic_sidebar( 'sidebar' ); ?>
  </aside>
<?php endif; ?>

The first line tells WordPress that if there is no sidebar, it should not be displayed. The second sets the attributes of the element containing the widgets. Meanwhile, the third line is the WordPress function to display the sidebar.

4. Build a Layout for Your Custom Theme

Now we will move on to creating the layout of your WordPress theme by modifying the header.php, index.php, footer.php, single.php, page.php, style.php files using media queries.

header.php

The header.php file will define the top of your document. It should have:

  • The DOCTYPE declaration – tells your web browser how to interpret the document.
  • language_attributes() function – enters the code for the language you picked during installation on the opening of the <html> tag.
  • HTML head elements <head></head> – it’s where you store metadata. They are the <title></title>, <meta></meta>, <link></link> tags, the is_front_page() tag together with the bloginfo() functions within it, and the wp_head() action hook.
  • body_class() function – gives your body the default CSS classes as set by WordPress.
  • wp_nav_menu () – displays the page navigation menu on your site’s header.

There are a lot of techniques to make a responsive WordPress theme. One of them involves using meta tags. Insert the following meta tag under your post title to make your website automatically adjust to smaller screen sizes and viewports:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

Once added, you’ll have a cross-browser compatible and mobile responsive site.

The final header.php file will look like this:

<!DOCTYPE html>
<html <?php language_attributes(); ?>
 <head>
   <title><?php bloginfo('name'); ?> &raquo; <?php is_front_page() ? bloginfo('description') : wp_title(''); ?></title>
   <meta charset="<?php bloginfo( 'charset' ); ?>">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>">
   <?php wp_head(); ?>
 </head>
 <body <?php body_class(); ?>>
   <header class="my-logo">
   <h1><a href="<?php echo esc_url( home_url( '/' ) ); ?>"><?php bloginfo('name'); ?></a></h1>
 </header>
 <?php wp_nav_menu( array( 'header-menu' => 'header-menu' ) ); ?>

If you want to use a logo as the header, replace <?php bloginfo(‘name’); ?> with the image code inside the <header> tags.

index.php

The index.php file defines the homepage. It’ll also be used as the default layout if specific templates such as single.php and page.php are not found.

Use template tags, such as get_header, get_sidebar, and get_footer, to make sure the header, sidebar, and footer code is included on your homepage. You’ll also need to insert the HTML5 semantic elements <section>, <main>, <header> and <article>.

Some of the elements will have classes assigned to them, which will be written in the style.css file.

Important! Header tags can be used multiple times on any page and do not specifically refer to the page header. Sections and articles should have the header elements if there’s text inside h1, h2, etc. If there is no header text in a section or article, these tags can be left out.

To display a list of posts and their excerpts with more template tags, you’ll need to use the WordPress loop. Doing this will also call the latest posts to the homepage. 

Thus, the final syntax of the index.php file will look like this:

<?php get_header(); ?>
<main class="wrap">
  <section class="content-area content-thin">
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
      <article class="article-loop">
        <header>
          <h2><a href="<?php the_permalink(); ?>" title="<?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2>
          By: <?php the_author(); ?>
        </header>
        <?php the_excerpt(); ?>
      </article>
<?php endwhile; else : ?>
      <article>
        <p>Sorry, no posts were found!</p>
      </article>
<?php endif; ?>
  </section><?php get_sidebar(); ?>
</main>
<?php get_footer(); ?>

In the code above, the loop starts at <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> and ends at <?php endif; ?>.

For more details, take a look at the following template tags used inside the loop:

  • <?php the_permalink(); ?> – outputs the correct URL of the actual post.
  • <?php the_title_attribute(); ?> – displays the title of the post in a safe format for the title attribute of the link.
  • <?php the_title(); ?> – shows the title of the post.
  • <?php the_author(); ?> – outputs the name of the author.
  • <?php the_excerpt(); ?> – carries out the excerpt of the post, which will be auto-generated if you don’t write your own.

We’ll learn more about WordPress template tags and loops later.

footer.php

This file is where you should define the footer of every page. It closes any <body> and <html> tags that are still open from the header.php file. Without this PHP file, you will notice the admin bar is missing when you visit your homepage, posts, or pages.

Define your footer using the HTML5 semantic element <footer></footer>. To ensure any final WordPress and JavaScript code is added to the page, it must include the wp_footer() action hook as well.

<footer>
      <p>Copyright &copy; 2019</p>
    </footer>
    <?php wp_footer(); ?>
  </body>
</html>

Saving this file will close any open HTML tags in other template files.

We’ll talk more about action hooks later in this tutorial.

single.php

The single.php file dictates the layout of single posts on your website. It can be completely different from the index.php.

Here, we will use the_content() function to display the full post. However, we will not add the sidebar to the posts and will remove the link on the title as well.

The full PHP code should look like this:

<?php get_header(); ?>
<main class="wrap">
  <section class="content-area content-full-width">
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
      <article class="article-full">
        <header>
          <h2><?php the_title(); ?></h2>
          By: <?php the_author(); ?>
        </header>
       <?php the_content(); ?>
      </article>
<?php endwhile; else : ?>
      <article>
        <p>Sorry, no post was found!</p>
      </article>
<?php endif; ?>
  </section>
</main>
<?php get_footer(); ?>

Once saved, your posts will be displayed as a single page without a sidebar.

page.php

The page.php file describes the way pages are displayed. It can be different from the index and the post layout.

Pro Tip

Remember that if the page.php file doesn’t exist, the index.php template will be used instead. Additionally, your website pages will not use the same layout as the one used in the single.php file.

To make the differences more visible, we will once again add the sidebar to this layout, and make the page content take up 70% of the page width. 

Add the following code to the page.php file:

<?php get_header(); ?>
<main class="wrap">
  <section class="content-area content-thin">
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
      <article class="article-full">
        <header>
          <h2><?php the_title(); ?></h2>
          By: <?php the_author(); ?>
        </header>
        <?php the_content(); ?>
      </article>
<?php endwhile; else : ?>
      <article>
        <p>Sorry, no page was found!</p>
      </article>
<?php endif; ?>
  </section><?php get_sidebar(); ?>
</main>
<?php get_footer(); ?>

Once saved, you’ll have a dedicated layout for your pages.

5. Improve Your Design on the CSS Stylesheet

In the previous section, we have mentioned the CSS stylesheet. This file controls the design and layout of your website. Since we have already added some code to the file, now we are going to modify the design.

Do so by adding the following code to the bottom of the style.css file:

.my-logo,
footer {
  width: 100%;
  padding-left: 1%;
  margin-bottom: 8px;
  background-color: #78baff;
  border: 1px solid #78baff;
}

body > header > h1 > a {
  color: #ffffff;
  font-weight: 400;
}

article > header {
}

footer {
  margin-top: 4px;
}

a {
  text-decoration: none;
}

/* 'Margin: 0 auto' centers block content on the page */
.wrap {
  width: 99%;
  margin: 0 auto;
}

.content-area {
  display: inline-block;
}

.content-thin {
    width: 70%;
}

.content-full-width {
    width: 100%;
}

.content-area,
.primary-sidebar {
  display: inline-block;
}

.primary-sidebar {
  width: 25%;
  padding: 1%;
  vertical-align: top;
  background-color: #ececec;
}

.article-loop {
    width: 45%;
    text-align: left;
    margin: 5px;
    padding: 10px;
}

.article-full {
  width: 99%;
  padding: 1%;
}

.article-loop,
.article-full {
  display: inline-block;
  vertical-align: top;
  background-color: #FFF;
  border-radius: 4px;
  margin-bottom: 4px;
}

Once saved, this will make various boxes have a white background and blue border.

Pro Tip

Experiment by changing the CSS style and width to see how your theme responds to various situations. Do this by adding custom CSS to your website with a WordPress plugin or the theme customizer.

Now that you have the stylesheet and all of the necessary templates ready, you can easily navigate through your posts and pages. Your new custom theme should look like this:

WordPress new custom theme customize menu

Using Media Queries

Media queries are useful to modify your WordPress website appearance depending on a device’s type, screen resolution, or browser viewport width. The media queries feature in your CSS stylesheet defines the page presentation when the viewport is changed. 

Let’s say you have two side-by-side text boxes that take up 50% of the screen. As the browser window gets smaller, the boxes automatically adjust to take up 50% of the window instead of disappearing off the side.

If the browser window gets too small to display all the text in those boxes properly, you can make them take up 100% of the window size and show one on top of the other.

Since our basic layout has two inline boxes on the front-page, we can easily change the way they behave when the browser window is too small to display the text.

So, we will change the width of the posts when the browser window is below 800px. Instead of having two side-by-side posts, each one will have its own line.

For this purpose, we’ll use some media-feature rules, such as:

  • max-width – defines the maximum width of the browser’s viewable area.
  • min-width – determines the minimum width of the visible area.
  • orientation – checks whether the screen is in a portrait or a landscape mode.

See the full list of media features on the Mozilla Developer Network website.

We will first write a media query that affects the .article-loop class. It’ll state that if the width of the browser window is smaller than 800px, the .article-loop class should use 99% of the available space. 

Thus, the media query should only affect screens and browser windows that are 800px or less in width.

At the end of the .article-loop class, add the following:

@media screen and (max-width: 800px) {
  .article-loop {
    width: 99%;
  }
}

After you save the changes, go to the homepage of your website. Change the size of your browser, and as it passes 800px in width, you will see the boxes for each post change and drop one below the other.

We will add the next media query similarly. It will instruct the main content and the sidebar to take 100% of the available space. This will make the sidebar drop below the main content if the browser window is smaller than 400px wide. 

Here’s what the code should look like:

@media screen and (max-width: 400px) {
  .content-area,
  .primary-sidebar {
    width: 100%;
  }
}

Pro Tip

You can place media queries anywhere in the stylesheet, or write specific media queries to particular items right below the original definition. However, if they affect different classes that are in different places, we recommend placing it at the bottom of the stylesheet.

Important! Change the rules for the media queries to fit your needs, and see if there are better rules that can be defined.

What Is a Responsive Design?

Devices usually have different screens, and each of them varies in resolution, functionality, and color. Some work in landscape, while others – in portrait. Additionally, many devices can switch between these modes.

For this reason, it is paramount to create a custom WordPress theme that is responsive to various screen resolutions.

Responsive design refers to displaying your website in the best format for visitors based on their screen size. The page layout responds to the available space, and the content is placed correctly – nothing is cut off, overflowing, and your website looks as clean as possible.

To measure a responsive alignment for your design, you should think of your website’s layout as a series of grids rather than pixels (px). Then, divide the grids’ width for every content section in percentages (%).

For images, you can set them to max-width: 100% of their actual size and the height to auto. The width and height of the image will be automatically adjusted when the screen size is narrowed. So, if you place a 200px width image inside a div that takes up 100% of the screen, it will remain displayed in its actual width.

Here’s an example of good vs. bad syntax to build a responsive design:

/* GOOD WIDTH */
.inline-text-box {
  width: 50%;
}

/* BAD WIDTH */
.inline-text-box {
  width: 800px;
}

/* GOOD IMAGE */
img {
  max-width: 100%;
  height: auto;
}

/* BAD IMAGE */
img {
  width: 100%;
  height: auto;
}

With this in mind, let’s apply these responsive web design principles to create a WordPress theme with HTML5 and CSS3.

What Are WordPress Template Tags, Loop, and Action Hooks

You will have to use template tags, loops, and action hooks to fully integrate your theme with WordPress. Below we will break down each of these elements to help you understand how they work.

Template Tags

Template tags, also known as template functions, are PHP functions provided by WordPress to easily include template files from your theme in another file or to show some information from the database.

If you want to show the footer on the home page but not on any other page, add get_footer() at the bottom of the index.php file but not in the page.php file. Keep in mind that some template tags must be used in a WordPress loop to work properly.

Below are two short lists of some essential template tags to give you an idea of which ones are available.

Template tags that include PHP files:

  • get_header() – includes the header.php template.
  • get_sidebar() – calls the sidebar.php template.
  • get_footer() – addresses the footer.php template.
  • get_search_form() – includes the searchform.php template.

Template tags that display information from the database:

  • bloginfo() – displays information requested in the parameter, such as bloginfo(“name”) that shows the name of your website.
  • single_post_title() – presents the title of the currently viewed post when used in the single.php file. 
  • the_author() – shows the author of the currently viewed post.
  • the_content() – outputs the main text of a post or page.
  • the_excerpt() – displays an excerpt of any posts or pages.

For the full list of WordPress template tags, check out the official WordPress codex.

WordPress Loop

WordPress loop is a set of code that retrieves any requested posts. The HTML code within the loop will display every requested post on one single page – it’ll be either a single post or all of your published posts. 

The loop is a multi-line shorthand if-then statement made up of four lines of code. The first line states that if a post is found, the following code will be used to display the post. If no matching post is found, you can define a replacement message instead.

The default WordPress example looks like this, and the commented line is where your HTML and template tags are written:

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
// HTML and template tags here to define the layout, and what is shown from the post
<?php endwhile; else : ?>
  <p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>
<?php endif; ?>

If you want to display one post, use the the_content() template tag inside the loop to show the content of the post. Meanwhile, if you want to display a list of all published posts, you can use the_excerpt() inside the loop.

Action Hooks

WordPress hooks are PHP functions used to manipulate a process without editing the core files. There are two types of hooks available – action and filter. Filter hooks are used to modify existing code in the function.php file.

Meanwhile, action hooks are used to create new functions. They have some core WordPress functions that add other HTML code to pages. Additionally, action hooks allow WordPress plugins to attach their own functions as well.

In your theme’s header template, the wp_head() action hook is called to include the default HTML WordPress header inside the <head></head> tags. In your themes footer section, the wp_footer() action hook is called to include the default HTML and JavaScript, and run any functions attached to it by plugins.

If you do not use action hooks when you create a WordPress theme, some important source code will be missing, and plugins will not be able to function correctly.

For example, not calling wp_footer() in your footer.php template will stop the top Admin bar from appearing when you are logged in as an admin. 

This is because the core WordPress code that shows the admin bar is attached to the wp_footer() action hook. Hence, the related functions can’t run without it.

Conclusion

Whether you have a personal or business website, there is a wide range of options in WordPress theme directories. 

Although installing a pre-defined theme is easier, your website will likely look similar to other websites using the same theme. To create a unique appearance and include advanced functionality, you will need to build a new theme of your own.

This article has gone through the five fundamental steps of creating a responsive theme for your WordPress website. Once you have successfully built your own theme, we recommend creating a child theme for it. Doing so will allow you to preserve all the customization after updating the parent theme.

All in all, we hope this article has helped you with the theme creation process. Should you have any questions or suggestions, feel free to leave them in the comment section below.

How to Create a WordPress Theme FAQ

This section will cover some of the most frequently asked questions on how to create a WordPress theme.

Is It Hard to Create Your Own WordPress Theme?

Developing a WordPress theme from scratch is relatively easy if you have some knowledge of HTML, CSS, and PHP. However, creating a WordPress theme can be tedious.
An excellent alternative to custom themes is using a starter theme like Underscore or WP Rig.

Can You Make Money From WordPress Themes?

Yes – most WordPress theme developers sell their creations at around $59 per license. There are several marketplaces you can join to make money from WordPress themes (eg. Envato, Theme Forest, and Code Canyon). For example, the average annual sales for Theme Forest alone are around $17,355.

How Long Does It Take to Build a WordPress Theme?

Generally, custom WordPress theme development takes around 2-3 weeks, depending on the complexity of the code. For example, a WordPress theme developer will need more time to add page builder functionality than to build a responsive layout.

Author
The author

Liam C.

Liam is a WordPress fanatic that loves to write about web development and coding. When he's not working, he likes to help people create websites and applications. In short, his job is also a hobby!