Partial To Perfect: When Is A WordPress Theme Complete?

WordPress is not just a blogging product: it’s a platform for creating websites, online stores and more. This distinction means that it’s not just the website owners who need a good user experience: somewhere along the way, actual programmers need to interact with its internals.

As Lee Cohick explains, the quality of this interaction influences the quality of the platform as a whole:

When a product transitions into being a platform, it takes on a new type of user: the third-party developer. When developers build their own products on a platform, they are in effect users of that platform. But they are a special type of user, one that behaves as an intermediary between end users and the platform product.

An end user’s experience with a platform product, such as the iPhone, includes the experience of using third-party apps. Every app is a use case that should reflect the user experience of the principal product. Platform product owners must be concerned with assisting developers in accomplishing this if end users are to have a good user experience overall. Attention to these details is called developer experience (DX), and enabling app developers to be successful through better DX will create a more successful UX for the platform product.

One equivalent of third-party apps for WordPress is themes. The Developer Experience for themes sets a low barrier of entry — which of course can result in many low-quality themes.

Clearly it takes very little to make a working WordPress theme. But how much extra effort is it to make a complete theme?

To answer this question, we’ll create one from scratch and — through multiple successive levels — see how comprehensive it gets before one would consider it a functionally complete theme.

Sam's Skateboards Logo
Skater icon by Nora Valadez from the Noun Project

To show off the capabilities of each level discussed in this post, we’ll apply the theme to an imaginary website called Sam’s Skateboards.

With each successive feature introduced, we can see how a WordPress website can be built to make use of that feature. We’ll call the theme Kickflip.

Level 1: The Minimum Required

The absolute minimum that WordPress requires to even recognise a theme is:

  • A stylesheet called style.css
  • A template file called index.php

This will add a new option in the Themes Administration Panel for selection:

The basic Kickflip theme option available for selection
The basic Kickflip theme option available for selection next to the default Twenty Sixteen theme.

At this point, the theme can be activated, but it certainly won’t do much. We should add some code in index.php:

Now, the page’s content will actually print out to the screen:

The homepage for Sam’s Skateboarding generated by WordPress with just the basic markup.
The Contact Us page generated from the same markup

With just the code in index.php we have a functional (albeit ugly) website.

  • The page’s title in the <title> tag
  • The page’s title in a <h1> at the top of the page
  • The content of the page in the body

As a valid document complete with working hyperlinks, this is basically a complete implementation of Tim Berners-Lee’s original World Wide Web dream. But to stand up as a worthwhile site on the modern web, we can do better.

Level 2: Styles, Favicons And Other Basics

The current best practice for adding style to webpages is through CSS. Since WordPress believes “options are bad”, the decision for how to include CSS on the page has already been made for us: using style.css.

Adding Styles

The official way to include the style.css file on the page is to enqueue it in a special file called The Functions File. This file does all the theme-wide heavy lifting and generally has the same capabilities as WordPress plugins do, but only executes when its theme is active.

So now we create a Functions File called functions.php and enqueue our main stylesheet from there:

Once we’ve done that, we can start styling our page by filling out the contents of style.css:

This will load the stylesheet and give our page a bit of personality!

The home page with some basic styles
The home page with some basic styles

Adding A Favicon

As of WordPress 4.3, theme authors should not write any code to display favicons or site app icons — WordPress now does it natively from the Customizer. If you have an existing theme that does this, you should migrate to using the WordPress core’s in-built functionality.

Proper Site Title

Right now the <title> for each page is simply set to display the title of the current post. This is not ideal since WordPress has many powerful title features that it can’t put to good use if the theme is dictating the page’s title. Also, many plugins may modify the title, so it’s best to let the WordPress core handle it.

Since WordPress 4.1, this is done by adding a simple one-liner into the Functions File:

Now we can safely remove the hard-coded <title> tag from index.php:

Now the page title will be handled by WordPress internally, according to whatever plugins and settings the theme’s users have enabled:

The dynamic page title generated by WordPress

Theme Metadata

If we look at our theme in the Theme Chooser, it’s obvious that there’s a bit of information missing:


Clearly we want to fill this out a bit.

Theme Thumbnail

To fill that empty rectangle with a picture of our theme, we just need to place a picture called screenshot.png into the theme’s root directory. Doing that will automatically make it show up.

Theme Details

WordPress themes have several different detail fields that authors can fill out. There are many optional fields, but at a minimum you should put:

  • Theme Name
  • Author
  • License

You add these fields to the File Header of style.css. Then, WordPress will automatically parse that information and show it where necessary.

After filling out the theme details and creating a theme thumbnail, your theme should look much more complete:

A well-completed theme summary
A well-completed theme summary

Is The Theme Complete Yet?

Right now we have a functional website running a valid theme that has the following features:

  • Dynamic title
  • Valid HTML5
  • Dynamic body content
  • Fully-completed metadata

While this does give us a functional website and a valid theme that is a bit better than the barebones Level 1 theme, here’s some things that are still missing:

  • Responsive design
  • Specifically-designed page templates
  • Search page
  • 404 page
  • Widgets
  • Sidebars
  • Semantic content width registration
  • Automatic feed links
  • Custom backgrounds
  • Post thumbnails
  • Post formats
  • Editor style
  • HTML5 markup opt-in
  • Theme logo
  • Menus
  • Translations & multilanguage support

Clearly this theme is functional, but not complete. Let’s keep building!

Level 3: Responsive Design, 404 Page And Search Page

Enabling Responsive Design

At present, our theme is not very mobile-friendly. To make the page’s content look better on all devices (as well as boost SEO scores), we want to tell the browser to render the page as a proper mobile-friendly document, rather than emulate a desktop-sized browser.

To make this happen, we need to add the following line into the <head> of index.php:

And now mobile browsers will fit the content much more appropriately:

Left: the page as seen by default. Right: after telling the browser to display the page responsively.

Other Navigation Pages

404 Page

Eventually, some site visitor will trigger a 404 Page Not Found error on every site. If it happens on a site with a theme that does not handle this, the result is not very professional:

An unhandled 404 error.
An unhandled 404 error.

Notice there’s no indication of the error or what caused it, so the user can get frustrated and leave the site. We want our theme to be professional and complete, so we can fix this by creating a new page called 404.php. This is the file in the WordPress Template Hierarchy that will be loaded when the site needs to show a Page Not Found error.

To fill this page, base its content off what’s in our original page template, index.php but with a slightly different main section:

So now, this page will show any time that the requested post or page can’t be found:

A properly-handled 404 error

Roadblock: Duplicated Theme Code

Since the design of the index.php and 404.php are very similar, they necessarily share a lot of the same code, including everything in the <head> and <footer>.

Because it’s a good idea to follow the DRY principle, we should make use of WordPress’ built-in solution for splitting out headers and footers into their own partial template files.

Now we create a file called header.php and fill it with everything from the doctype declaration to the point where each page diverges into unique lines of code. And then we do the same for footer.php, except that gets filled with everything from the end of the divergent point to the closing </html> tag:

By using the get_header() and get_footer() hooks, we can keep all our shared header and footer code in their own separate files, and fill the page templates with only what they need specifically for that page.

Side note: there is a difference between wp_footer() and get_footer().

Search Page

The WordPress Template Hierarchy has a special page template for displaying search results, since we generally want to show a snippet of results instead of entire pages.

To create a search page, we add a new file called search.php to the theme’s directory and fill it with appropriate content. This should give us a reasonable search results page:

A well-built search page
A well-built search page

Is The Theme Complete Yet?

We’re starting to have a great theme for the purposes of showing webpages and handling related edge cases. But is this enough?

Many users will want to add in menus and widgets. In fact, WPBeginner says sidebars are an absolute must-have. Add that to the ubiquity of menus around the web and it would be hard to call a theme complete without them.

While there’s nothing technically wrong with the theme as it is, we still have to cater to user expectations for using this theme, and visitor expectations while consuming the theme-presented content.

Let’s keep building!

Level 4: WordPress-Specific Features

Dynamic Menu Areas

Any website worth its salt has at least one navigation menu. With WordPress, the theme can define menu areas that users can fill with their own customised menus.

Here we use the hook register_nav_menus() in the Functions File to create two menu areas: one in the header and one in the footer:

This gives the owners of the site the ability to use the WordPress Menu Panel to create custom dynamic menus:

WordPress now recognises two menu areas: a Header Menu and a Footer Menu
WordPress now recognises two Theme Menu Locations: a Header Menu and a Footer Menu

Header Search

While we created a proper search form earlier, there was no way to actually invoke a search short of typing your query into the URL bar.

Using the built-in get_search_form() hook, WordPress will print out a semantic, valid, working search form ready for use and styling:

A properly-implemented WordPress search form.

Sidebars & Widgets

As mentioned, sidebars are a very important part of the WordPress platform and users expect to be able to customise them and fill them with widgets.

Fortunately for theme authors, this is a simple matter. Using the register_sidebar() hook, we can register a dynamic sidebar area just like we previously did for menus.

Combined with creating a new file called sidebar.php, we can add this theme feature to the site in no time:

A page showing the new sidebar with some widgets activated.
A page showing the new sidebar with some widgets activated.

Some themes have other areas where widgets can be dynamically inserted by the site owner, like the footer or even the header. Each successive widget area is defined and implemented in the same way.

Other Page Templates

According to the WordPress Template Hierarchy, our theme can — in some capacity — display all the content and media that a site owner can throw at it:

  • Search pages are shown using search.php
  • The 404 page is shown using 404.php
  • Everything else is shown using index.php

While this is okay for most of the content, some site owners would like a bit more specialisation for various post types. We can do this by continuing to build out pages according to the hierarchy:

  • font-page.php for a custom homepage design
  • single.php for individual blog posts
  • page.php for individual pages
  • archive.php for cataloguing posts by date
  • home.php for cataloguing the latest posts

Sidenote: for websites without blog posts (like static brochureware sites), many of these blog-specific pages might not be necessary. But it’s still a good idea to build them out anyway.

There are other secondary page templates that get increasingly more specific to the type of post or page being shown, but the templates we have created here cover the whole spectrum of WordPress’ information-display capabilities.

Editor Style

WordPress has a great feature that enhances the content creation experience: a custom Editor Style:

Apart from affecting the post content appeareance in the editor, this will make the CSS class definitions from the file available in the Styles list box of the TinyMCE editor and able to be assigned to the content.

To make our theme’s styles visible in the editor, we need to do two things:

  • Create a stylesheet called editor-style.css with all the typographic styles that can be used
  • Enqueue that stylesheet for use in the editor using the add_editor_style() hook

This instantly makes the editor a better analogue for how the content will ultimately appear when published:

The TinyMCE Editor without a custom Editor Style
The TinyMCE Editor without a custom Editor Style
The TinyMCE Editor with a custom Editor Style added to reflect the eventual page appearance.
The TinyMCE Editor with a custom Editor Style added to reflect the eventual page appearance.

Is The Theme Complete Yet?

Let’s take stock of what features this theme boasts now:

  • Dynamic title
  • Valid HTML5
  • Dynamic body content
  • Fully-completed metadata
  • Responsive design
  • Specifically-designed page templates
  • Search page
  • 404 page
  • Widgets
  • Sidebars
  • Menus
  • Editor style

This feature set would almost certainly be appropriate for authors who are developing a niche site with somewhat controllable ranges of content. If created for free or as an internal project, our theme should be basically sufficient for most site owners’ needs — and should cater to most basic site visitors.

At this point, many WordPress developers could categorise this theme as complete. But it is not sufficient for all purposes.

To be better than good enough, we should go further and add in features that would make our theme hold its own next to a professionally custom-coded website with all the bells and whistles. After all, that is the point of using a CMS like WordPress: to get the benefits of having a high-quality website without having to actually make it from scratch.

Level 5: Bells And Whistles


Since themes are general-purpose pieces of software, they need to be able to handle all the different needs of different users around the globe. This means we need to support left-to-right text encodings as well as other languages.

RTL Support

Adding right-to-left text support is easy. All we need to do is add a file called rtl.css to our theme’s directory. This will automatically get enqueued when the page is loaded by a visitor whose browser language displays text from left-to-right.

The contents of this file should include direction-specific overrides:

This should make the website appear more or less correctly in the reverse direction:

Explicitly defining RTL styles will almost always give better results than making the browser try to handle it by itself.
Explicitly defining RTL styles will almost always give better results than making the browser try to handle it by itself.

Adding Translation Support

The 2012 WordPress Survey revealed that more than two-thirds of WordPress users live outside the USA, so it is a good idea to add i18n and l10n functionality to any WordPress theme.

The process can be quite long, so read about it in the following article:

How To Localize A WordPress Theme by Raelene Morey

Print Stylesheet

Like RTL support, adding support for print-specific styles is done with a dedicated stylesheet, called print.css.

We add that to the theme’s root directory and then add a snippet to the Functions File to enqueue the stylesheet, but only use it for printing:

HTML5 Markup Opt-In

The web is always forwards-compatible by design, but that doesn’t mean that best practices don’t evolve. WordPress allows theme authors to opt-in to using newer HTML5-based features like special markup for search forms, comment forms, comment lists, gallery and caption.

To activate these extra features, we inform the WordPress engine through the Functions File that our theme is willing to accept HTML5-specific markup for various sections and features:

You should opt-in to as many of the new HTML5-specific features as possible so browsers can leverage these new technologies in the best ways they can. This gives the end-user a better browsing experience and your theme becomes that much better for it.

Sidenote: the generated markup might be different to your original content, so be sure to check that your styles still apply correctly and make any adjustments to the new markup and content as needed.

Is The Theme Complete Yet?

In Level 4, we created a fairly comprehensive theme with many useful features, but could still fall flat when faced with the complexities of real-world usage.

Now however, our theme boasts the following extras:

  • Specific styles and appearance for printers and RTL users
  • i18n and l10n support for non-English-speaking site owners
  • More semantic, modern HTML5-based widgets and forms

This distinction makes the theme suitable for almost any website and should be the benchmark for WordPress theme developers to attain for any professionally produced work.

This is what it takes to produce a WordPress theme that is commercially satisfactory, for all users in all countries, on all devices. If you’ve created a theme that meets or exceeds this level of comprehensiveness, you can confidently consider it complete!



Bonus Level: Distribution Compliance

If you want to let other people use a theme you’ve created, you can submit it to a registry or store. The WordPress theme gallery is the best place to submit your theme if it can be used for free, but beware that successful submissions must follow the guidelines.

Additionally, if you wish to sell your theme, some theme sellers like ThemeForest have even stricter acceptance criteria than the WordPress theme gallery, so ensure that your theme meets or exceeds these requirements.

Together with the features presented in this case study, any theme you create can be a great example of how complete any WordPress theme can truly be.

Leave a Reply

Your email address will not be published. Required fields are marked *