Want to create a brand-new WordPress theme from scratch? Feel overwhelmed by the information in the WordPress Codex? In this article, we simplify the process and break it down into easy to follow steps.
For this tutorial, we assume that you already have a working installation of WordPress and a basic understanding of HTML and CSS. If you’re brand new to WordPress development, and you need help setting up a development environment, we recommend checking out this roundup of your best options.
If you’re looking for books on WordPress, check out The 5 Best WordPress Books for 2020: From Beginner to Advanced
Let’s get started.
1. Create a folder for your new theme
Go to your installation of WordPress, and create a folder for your new theme in the wp-content/themes/ folder. You’ll know when you’re in the right place because you’ll see the folders for WordPress’s default themes (twentyfifteen, twentyfourteen, etc.). All themes must be placed here, just like all plugins must be placed in wp-content/plugins/.
Give the folder the name you want to give your theme. We recommend using lowercase, and if your theme name is more than a single word, connect the words with hyphens. For example, the the resulting folder for a theme named My New Theme could be: wp-content/themes/my-new-theme/
2. Create an empty file named style.css in your new theme folder, and provide WordPress with information about your theme
You can do this with a simple text editor like Notepad, or a more sophisticated text editor like Sublime Text, which we highly recommend.
Once you create style.css, you need to add what’s referred to as the stylesheet header at the top of the file.
This provides WordPress with all the necessary information about your theme, including its name, its author, and its license.
Below is an example of a basic stylesheet header. You can copy and paste this into your own style.css, but be sure to change the details to reflect your unique theme name, your WordPress.org username, and your website (if you have one). Note that no two themes can share the same stylesheet header.
/* Theme Name: My New Theme Theme URI: https://your-website.come/my-new-theme/ Author: Your WordPress.org Username (or Real Name) Author URI: https://your-website.com/ Description: A basic WordPress theme Version: 1.0 License: GNU General Public License v2 or later License URI: http://www.gnu.org/licenses/gpl-2.0.html Tags: basic, blog, right-sidebar Text Domain: my-new-theme */
3. Create another empty file with your text editor and name it index.php.
The most basic WordPress themes require only two files to function, style.css and index.php.
Once you’ve created index.php, assuming you’ve completed the previous steps, you can visit the Appearance tab on your WordPress dashboard, navigate to the ‘themes’ section, and Activate your newly created theme.
But, because we haven’t added anything to index.php yet, after activating the new theme, you’ll be greeted with a blank, white screen when visiting the homepage. Don’t worry! That’s what we expected!
4. Give the browser something to render by adding some basic markup to index.php.
Copy and paste the following into your own index.php.
<!DOCTYPE html> <html <?php language_attributes(); ?> class="no-js"> <head> <meta charset="<?php bloginfo( 'charset' ); ?>"> <meta name="viewport" content="width=device-width"> <link rel="profile" href="http://gmpg.org/xfn/11"> <link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>"> <link rel="stylesheet" type="text/css" media="all" href="<?php bloginfo( 'stylesheet_url' ); ?>" /> <?php wp_head(); ?> </head> <body <?php body_class(); ?>> <header class="site-header"> <div class="site-name"> <a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a> </div> <div class="site-description"> <?php bloginfo( 'description' ); ?> </div> </header> <div class="site-content"> More to come with the loop. </main> <footer class="site-footer"> Copyright 2015 </footer> <?php wp_footer(); ?> </body> </html>
In the above code, you’ll notice little bits of PHP called template tags. They look like:
<?php bloginfo( 'description' ); ?>
Template tags are an essential part of theme development that allow WordPress to dynamically access information. They tell WordPress which information you want to access from the database and, sometimes, what to do with it. You don’t need to a sophisticated understanding PHP to use them.
There are dozens of template tags. A comprehensive list of available template tags can be found on the Codex.
Go to your browser, load the homepage of your WordPress install, and instead of a white, blank window you should now a plain rendering of the site name, site description, the text “More to come with the loop”, and the copyright notice.
5. Divide index.php into header.php, footer.php, and index.php.
WordPress templates are modular, which provides a lot of flexibility and makes WordPress theme development much easier. You’re unlikely to find a theme that crams all of its markup and code into a single file. Almost every WordPress theme breaks down index.php into at least three individual files. We’ll create them now by cutting and pasting the code we already added to index.php during step 4.
Create a new file called header.php. Cut the following code out of index.php, and paste it into header.php:
<!DOCTYPE html> <html <?php language_attributes(); ?> class="no-js"> <head> <meta charset="<?php bloginfo( 'charset' ); ?>"> <meta name="viewport" content="width=device-width"> <link rel="profile" href="http://gmpg.org/xfn/11"> <link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>"> <link rel="stylesheet" type="text/css" media="all" href="<?php bloginfo( 'stylesheet_url' ); ?>" /> <?php wp_head(); ?> </head> <body <?php body_class(); ?>> <header class="site-header"> <div class="site-name"> <a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a> </div> <div class="site-description"> <?php bloginfo( 'description' ); ?> </div> </header>
Next, create a new file called footer.php. Cut the following code out of index.php, and paste it into footer.php:
<footer class="site-footer"> Copyright 2015 </footer> <?php wp_footer(); ?> </body> </html>
Important: The function wp_footer() should always be called just before the closing </body> tag in footer.php. Omitting it will cause you nothing but pain and suffering (and break a lot of the javascript on your site won’t work correctly).
Now you should be left with a very sparse-looking index.php compared to what you had before. It should look like this:
<div class="site-content"> More to come with the loop. </main>
The next step is to add template tags to index.php that will load the contents of header.php and footer.php whenever index.php is loaded. Make the following additions to index.php:
<?php get_sidebar(); ?> <div class="site-content"> More to come with the loop. </main> <?php get_footer(); ?>
Now when you refresh the homepage in your browser, none of the information or the way it’s displayed will have changed. That’s exactly what we expected and wanted.
6. Add the Loop
The loop is the code used to display WordPress posts. There’s not much point of using the WordPress platform without it. For the purpose of this tutorial, we’re going to add a basic implementation of it to index.php. For now, we just want it to display the following information:
- The post title
- The post date
- The author of the post
- The content of the post
- The category of the post
Open up index.php and edit it to match the code below, adding the loop. If you want, you can copy the code below, pasting it over all of your existing code in index.php. Then we’ll take a closer look at what’s happening.
<?php get_header(); ?> <div class="site-content"> <!-- Start the Loop. --> <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <div class="post"> <!-- Display the Title as a link to the Post's permalink. --> <h2><a href="<?php the_permalink(); ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a></h2> <!-- Display the date (November 16th, 2009 format) and a link to other posts by this posts author. --> <small><?php the_time('F jS, Y'); ?> by <?php the_author_posts_link(); ?></small> <!-- Display the Post's content in a div box. --> <div class="entry"> <?php the_content(); ?> </div> <!-- Display a comma separated list of the Post's Categories. --> <p class="postmetadata"><?php _e( 'Posted in' ); ?> <?php the_category( ', ' ); ?></p> </div> <!-- closes the first div box --> <!-- Stop The Loop (but note the "else:" - see next line). --> <?php endwhile; else : ?> <!-- The very first "if" tested to see if there were any Posts to --> <!-- display. This "else" part tells what do if there weren't any. --> <p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p> <!-- REALLY stop The Loop. --> <?php endif; ?> </main> <?php get_footer(); ?>
Here’s what’s happening. First, the loop checks to see if any posts exist. If posts do exist, WordPress is instructed to summon the data associated with each post (title, content, author, date, etc.), and make that data available to us (via template tags) so that we can work with it and manipulate it. We can then use HTML markup to build a common structure for each post and provide the necessary classes to styling.
When no more posts are found, the loop ends. And in the instance that no posts exist, the loop ends and informs you that no posts were found. In it’s basic form, the loop is simple and elegant.
7. Add some basic styling
At this point, we’ve created a bare bones (but totally useable) theme. You could activate it on your site, start writing blog posts, and visitors could read those posts. In the second part of this tutorial, we’ll take a look at adding features that increase usability, like a navigation menu and widgetized sidebar.
But we’ll end this tutorial by adding bit of styling. Open up style.css, and copy and paste the following CSS beneath the stylesheet header we created in step 2.
body { line-height: 1.5em; font-family: Arial, Helvetica, sans-serif; margin: 0; padding: 0; } a { color: #000; } .site-header { color: #ccc; background-color: #333; padding: 30px; text-align: center; } .site-name a { display: inline-block; color: #fff; font-size: 3.0em; font-weight: bold; text-decoration: none; text-shadow: 3px 3px #000; } .site-content { color: #555; background-color: #eee; padding: 30px; } .site-content h2 a { text-decoration: none; } .post { background-color: #fff; padding: 30px; margin-bottom: 30px; } .site-footer { color: #ccc; font-size: 0.8em; text-align: center; text-transform: uppercase; background-color: #333; padding: 30px; }
Now when you refresh your WordPress homepage in your browser, you’ll find something a bit more pleasant to look at.
Anyway, that’s a wrap for now. See you next time!
Hi
A small typo, I came across:
Where you said : “Now when you refresh the homepage in your browser, none of the information or the way it’s displayed will have changed” – I believe it is meant to be not
Thanks for the tut, was quite informative.
Exactly what I was looking for, thank you!