Tutorial: WordPress: Modifying Themes
In WordPress: Beyond the Basics we talked up the power of WordPress themes, and how it makes sense to put time into finding and modifying an existing theme rather than designing one from scratch. But how do you modify a theme? In this tutorial we'll take a deeper dive, learning how themes are constructed and how to get your chosen theme to work exactly the way you want it to.
Theme modification is a great way to strengthen your HTML and CSS skills, and possibly PHP as well, depending on what you want to do. This tutorial assumes you have basic comfort with HTML, CSS, and file transfer via FTP. If you don't, you'll want to see these tutorials first:
While not strictly necessary, you may benefit from some PHP basics as well.
Theme Editing Basics
A WordPress "theme" is a collection of documents, generally consisting of:
- One or more CSS style sheets
- Any necessary images that comprise the theme graphics
- A collection of PHP/HTML "template" files
- A thumbnail image representing the theme in the Dashboard
A typical WordPress theme contains a dozen or more files, but only a few are technically required.
These files work together as a package to define the entire look and feel - and sometimes behavior - of a WordPress site. Themes are completely decoupled from site content, so in theory, a site owner can apply a new theme with the click of a button and have all content on their site take on a whole new appearance (in practice, site redesigns aren't quite this simple).
This collection of files is contained in a folder that lives in the
wp-content/themes directory on your web server. When an administrator visits the Appearance | Themes section of the WordPress Dashboard, all valid theme folders in that location will appear. Any valid theme can be applied to the site content by clicking the Activate link below its name.
Editing Template Files
In a minute we'll learn how to determine which files to edit, but before we can do that, you'll need access to them. To edit a theme's files, you've got two choices:
- Use the Dashboard's built-in editor (Appearance | Editor)
- Edit template files in a programmer's text editor and upload them via FTP
Using the Built-In Editor
The first method is the easiest, but is much less powerful. Since you'll be editing in a standard web form, you won't have the advantage of a proper editor, such as syntax highlighting, line numbering, tag completion, or any of the dozens of other crucial features found in modern programmer's editors.
Once in the theme editor, select one of the template files on the right, then look for an "Update" button below the text area. If you don't see an Update button and see this sentence instead:
You need to make this file writable before you can save your changes.
it means your template files are not editable by the process the web server runs as. To fix this, you'll need to log in via FTP or ssh and change the file permissions. The Codex has a full page of instructions on this.
In order to use the web-based theme editor, the theme folder will need to be writable by the web server. In this scenario, the server is running as user and group "nobody" and we're making the files writable by the group. We then click "Apply to enclosed" or similar so the change propagates to all files in that folder.
Editing via S/FTP
A much better solution is to log into your web host via S/FTP. You can either drag files to the desktop for editing in your favorite programmer's editor (we like TextMate) and then re-upload them, or configure your S/FTP client to edit files directly on the server. With this technique, the act of saving the document updates the file directly on the remote server. This is by far the easiest and most powerful way to work on WordPress themes, and we strongly recommend it.
Configuring preferences in the Transmit S/FTP client to launch double-clicked files in the TextMate editor. The Cyberduck client has a similar preference pane, as do many other S/FTP clients.
From here on, we'll assume you're editing files directly on the server via S/FTP configured to work with a good plain text editor (not a word processor).
Test Environments and Safety Nets
Since you'll be editing files live, you want to minimize the risk of making mistakes on a production web site. We recommend one or more of these techniques:
- Create a "dev" or "staging" subdomain at your web host to work on. This way you can fiddle to your heart's content without worrying about breaking things on the public/live site.
- Install a web server, MySQL database server, and PHP on your personal development machine.
For small nips and tucks where you have a high degree of confidence, it's generally OK to make live edits on a production site, but it's still a good idea to create a backup copy of the file you're about to edit before you touch it. If something goes really wrong, you can always re-install the last known working version of that file. In Transmit or Cyberduck, simply select the file you're about to edit and hit Cmd-D to create a backup copy in place.
To recap, a theme is a collection of files that live in a folder at
wp-content/themes on the web server. Each file in a theme serves a purpose, and must be named in a specific way in order to be called correctly by WordPress. A "valid" theme must have at least these three ingredients:
- A stylesheet file named
- At least one PHP file called
- One thumbnail file called
A CSS block at the top of the style sheet must include the theme name, version, author name, and possibly other information. If this block is missing, WordPress won't recognize the theme as valid for display in the Dashboard.
/* Theme Name: My Awesome Theme Theme URI: http: //example.com/ Description: Child of the Twenty Eleven theme Author: Your Name Here Author URI: http: //example.com/about/ Template: twentyeleven Version: 0.1.0 */
See the Codex for more about the CSS header.
How Does a Theme Work?
If you want to modify a theme, you need to know which templates to edit. And to know that, you need to know a bit about how WordPress determines which templates to invoke for a given page request.
Think of a web page as consisting of a set of blocks, some of which are the same from page to page, others of which are different. For example, most sites will have the same masthead/banner and footer and probably sidebar on every single page. But the guts of the page will of course be different - the homepage will show summaries of the latest posts, article pages will show just one post, and category views will show summaries of recent entries filed in that particular category.
The files in a theme correspond to these pieces of functionality. Intuitively, you'll find files called
sidebar.php. When a page is requested, WordPress looks at the URL of the page being viewed and determines what kind of page is being viewed. Is this the homepage? Is this an article page?
From this, WordPress can decide which templates will be needed to construct the page. For example, if a single article page is being requested, WordPress knows it will need to assemble the header, footer, sidebar, and the template that handles display of single articles, which is intuitively named
When a page is requested, WordPress determines which template files it will need to assemble the page. This lets common pieces of functionality be re-used throughout a site.
But how did WordPress know to use these four templates? The system starts by determining which template is the core of the current page. The core is determined via the WordPress template hierarchy (described next), but for now we'll go with the example above, where
single.php is the core. If you take a look at the code inside of
single.php, you'll probably see PHP function calls that look like this:
In other words, the core template "pulls in" the other template files it needs to complete the whole page. That's a fairly simple example, and most themes contain many more templates than these four, but the basic concept is always the same.
Basic Stylistic Changes
Many changes to the look and feel of a WordPress site can be handled through CSS alone, without ever touching the templates. This is why it's essential to have some basic CSS skills before attempting theme modification. Let's look at some CSS-only changes you can make to a theme before diving into template modification.
As you'll discover, CSS tweaking can be time-consuming, fiddly work for non-experts. There's no end to how many stylistic changes you can make to a theme, but be aware that you may hit a point of diminishing returns and wish you'd started with a theme that was already closer to your end goal. Time put into initial theme selection is generally better spent than time spent on endless tweaks and modifications.
As a general rule, it's very easy to modify colors, images, and typography, but it's much harder to modify column widths, and harder still to completely rearrange page layouts unless you have advanced CSS skills.
There's really nothing WordPress-specific about editing a WordPress style sheet - it's all standard CSS code, which you can learn elsewhere. The trickiest part is usually in determining which portion of the CSS needs to be tweaked. And for that, you'll need a good debugger, which will help you to examine the page contents and learn which lines of CSS code are controlling their appearance. If you use the Chrome or Safari web browsers, which are based on WebKit, you've already got an excellent debugger built in.
Enabling debug mode in Safari: Go to the Preferences, click the Advanced tab, and enable the option "Show Develop menu in toolbar." You can now debug any web page by pulling down Develop | Show Web Inspector (or hit Cmd-Opt-I).
Enabling debug mode in Chrome: The debugger is always available - just pull down View | Develop | Web Inspector (or hit Cmd-Opt-I) to bring it up.
Enabling debug mode in Firefox: Install the excellent Firebug extension. Once installed, click the small "bug" icon at the lower right corner of the browser.
Let's look at a couple of typical examples where CSS modification might be needed. Screenshots here show Web Inspector, but Firebug instructions would be very similar:
1) I want to change the background image of the theme. Let's say you like the Graphene theme but you don't like the background image that comes with it. Apply the theme, then bring up your debugger and click Elements. Next, click the magnifying glass icon at the bottom left.
To inspect elements on a page in the WebKit Inspector, click Elements, then use the Magnifying Glass to hone in on the element you're interested in.
Now click on the page background and look at the CSS code in the right-hand pane:
This tells us exactly what we need to know: The path to the background image file can be found on line 75 of the file
style.css. If you open
style.css in your text editor, you'll see that the entire line is:
So to change the background, upload a new background image to
wp-content/themes/[yourtheme]/images, and edit line 75 to match the new filename. Voila! No template changes needed.
2) How can I change the banner image that came with my theme? Start by debugging the same way we did with the background image example. You'll see the header image referenced, but not in a stylesheet. It's a trick! The way the header image is displayed will vary from theme to theme. While some themes might reference the header image in exactly the same way as above, others might hard-code it into the
header.php template file. Still others might provide a set of Dashboard controls for setting the banner image. Taking a look in
header.php for the Graphene theme, you'll see this:
In other words, the HTML in the header template defines an inline style to the image path. But rather than hard-coding the image path, it calls a custom function defined by the theme. That function knows how to reach into the WordPress database and figure out which image you've told it to use from the Dashboard. In other words, no code changes needed for this tweak - you can do it all with point and click. But now you know how the header image is getting there to begin with.
3) How can I change the color of the sidebar headers? So what if you don't like the white-on-blue of the sidebar headers? There's no Dashboard option for changing that in the Graphene theme, and if you look closely, you can see that there's actually a subtle gradient from a lighter blue to a darker blue. Fire up that debugger again, click on a sidebar header, and you'll see a whole bunch of rules starting on line 1560 of
style.css. Things get a little trickier here because using gradients on the web isn't yet a solidified web standard. Therefore, the theme author has set up four different ways of rendering gradients, to accommodate all web browsers:
The first line references an image file, which will work with the oldest browsers out there. So the first thing you should do is download that image, open it in Photoshop, change the gradient, save it, and upload it back to the server. With Photoshop open, grab the new starting color and the new ending color, and replace the references on the next three lines of the style sheet.
4) How do I change the fonts used on my site? By now you should have the hang of this. Launch the debugger, grab the magnifying glass, and click on some text. The debugger will tell you on which line of the style sheet the font is declared. Then all you have to do is tell it which new font to use. See the Fonts and Text section of our CSS tutorial for pointers. You might even want to experiment with custom typography from a service like Google Fonts or TypeKit.
The Template Hierarchy
The trick to modifying your theme is in knowing which files to edit. And to know that, you need to learn a bit about the WordPress template hierarchy.
When a request for a page on your site is received, WordPress first examines the URL and determines what type of page it is. For the sake of example, let's say a user has requested a specific category page on your site:
http://example.com/categories/books. From the URL, WordPress knows that it needs to display a category page. It also knows, internally, that a category is a type of an archive. It also knows that this isn't just any category page, it's a specific category page (the one that has "books" as a slug).
To determine which template file to use to display this particular category view, WordPress will step through a hierarchy of options, starting with the most specific template and falling back to the most general. WordPress will follow this chain of logic:
1) Because you might want to use a special template just to show the Books category, that's the most specific case, so WordPress will first look for a template called
category-books.php. When creating templates for specific categories like this, you can also name template files
category-5.php, where "5" is the ID of the category you want to customize. In other words, you can use either the category slug or its database ID when naming this template.
2) If that template file doesn't exist, WordPress will try to find the general-purpose category template, which is always named
category.php (this would be used for all category views).
3) If the current theme doesn't have a
category.php template, WordPress will think "Well, a category is a specialized form of archive," so it will look for a template file called
archive.php (in this case, the
archive.php template would be used for both category views and date-based views such as "All posts from March").
4) If there is no
archive.php template, WordPress will fall back to using the most generic possible template, which is
In other words, WordPress will traverse a logical hierarchy of options when deciding which template to use, starting with the most specific option and falling back to more generic options until it reaches
index.php. This is why it's possible (though not recommended) to have a theme that consists of nothing but a stylesheet and an
Other template-choosing decisions in WordPress are made in a similar way. For more examples, see the flow-chart below, which links to the Codex documentation on the Template Hierarchy:
So, if you want to modify the way search results are displayed on your site, you would look at the Template Hierarchy and determine that that view is handled by a template called
search.php. Then you would look in your theme for a file of that name. If it exists, edit it! If it doesn't, you'll see that you need to edit
index.php instead. And so on.
Once you open a file for editing, you'll be faced with a combination of standard HTML, basic PHP-language programming structures such as loops and tests, and WordPress function calls written in PHP. See the examples in this tutorial to see how it all fits together.
Common Theme Functions
Since template files are PHP documents, each template is capable of requesting information from the server. For example, the
header.php template will generally request the blog title and tagline from the database and insert those values at the right place. Meanwhile, the sidebar template will look to see which Widgets need to be displayed, and the
single.php template will grab the article body, byline, timestamp, and any comments from the database.
All of these calls for information from the database are handled by custom PHP "functions" specific to WordPress. For example, take a look in the
header.php template and you might find a line something like this:
In other words, the destination of the link is being replaced by the results of a call to a PHP function called
home_url(). That function isn't built into PHP itself - it's a function provided by WordPress. Its value is whatever is set as the homepage URL in the Dashboard's General Setting section. The cool thing about setting a link back to the homepage this way is that it makes the theme portable. If one WordPress installation is in the root domain of
example.com but another site has a blog at
example.org/blog, both sites can use the same theme, and the homepage links will resolve perfectly. By avoiding hard-coding as much as possible, the theme stays adaptable to many situations and applications.
But how did the theme author learn of the
home_url() function? By consulting the dictionary of WordPress Template Tags and the WordPress Function Reference, where dozens of such tags are documented. Let's take a look at a few common ones:
get_bloginfo(): You'll see this one referenced in header templates a lot. By giving it "arguments," you can obtain most of the settings from the Dashboard's General Setttings page. For example, try putting this in one of your templates:
The title of the site will be inserted in the template wherever you drop this tag. So what if you want to refer to an image that lives in an "images" subdirectory of the theme directory? You can do it like this:
Now the image will still work even if you later decide to rename your theme folder!
In addition to the dozens of template tags that come with WordPress, many plugins will provide you with additional ones as well. Themes can also define their own custom functions in
functions.php. If you see a function called from your theme that you can't find listed in the Codex, then you'll know it's either provided by a required plugin or from that theme's own custom functions.
Function or Template Tag?
There's one important thing to be aware of when working with these: Most functions have two versions - one for displaying the value immediately into the web page, and another that stores values in memory for further processing. You can distinguish between them by the presence of "
get_" in the name. For example,
bloginfo('name') will display the site's name directly, but
get_bloginfo('name') will not. The correct usage of the latter might be something like:
This would cause the value of the site's name to be stored in the variable
$sitename, then run through PHP's "lowercase" function. The result would be written to the page by the PHP
echo() function. For most non-programming purposes, stick to the Template Tags, not the Function Reference.
There are far too many template tags and functions to cover here, but you get the idea. If you come across an unknown function while working on a theme, just look up its name in the Codex to learn what it does and what kinds of options or arguments it takes. Template Tags are wonderfully powerful!
Remember: Avoid hard-coding values into your theme whenever possible.
Themes are, in essence, software. And software needs to be upgraded from time to time. You don't want to miss out on new features or bug fixes provided by the theme developer, right? But wait... you've modified the heck out of your theme -- if you upgrade it with a newer version, won't you lose all your changes?
Not if you go about theme modifications the right way. Recognizing this dilemma, the creators of WordPress introduced a concept called "Child Themes," which lets you make your changes "off to the side" where they won't be touched by future upgrades. It may sound like overkill, but the first time you find yourself locked out of a future upgrade by your own modifications, you'll wish you'd built a child theme. The good news is, it's easy!
For this exercise, let's work with the default 2010 theme that comes with WordPress. In practice, install whatever theme you want to work with in the usual way.
1) Create a new, empty folder in the
wp-content/themes directory on your server, using standard web conventions (no spaces or special characters in the name). The folder could be named something like "
jsmith_2010_child". Your child theme will live in this folder.
2) In that folder, create a blank
3) Open that
style.css and add the following lines:
You'll want to change most of the lines above to suit your needs. It's not critical what they say, as long as the Theme Name doesn't conflict with any theme you already have installed. The really important line is the
Template: line - this must match the exact name of the folder that contains the parent theme! Likewise, edit the
@import url line to match the path to the parent theme's stylesheet.
Save this bare-bones stylesheet file to the server, then go to the Dashboard's "Appearance" section and activate your new theme. Take a look at the live site and... nothing's changed! That's a good thing - at this point, all you've done is to activate a new theme that imports the entirety of the parent theme, with no changes.
Now let's try making a couple of changes, starting with the white background color of the content area. Note that this is a CSS tweak, not a template tweak - we're starting easy. According to our debugger, the white background color is defined on line 171 of
style.css in the parent theme. Taking a look, we see this CSS block:
Copy that rule into the bottom of the
style.css of your child theme, changing the background color to something else:
Save, refresh the page, and bingo! Your content area has a yellow background, even though you haven't touched the parent theme. The rules of CSS inheritance say that we can redefine an existing style, and wherever the rules conflict, the ones read in later will be used instead. Since the child theme's rules are read in after the parent theme's rules, the child theme wins that particular contest.
We can actually go even further. Trying using this instead:
That way, you still inherit the top margin and padding from the parent theme, overriding only the color.
It's only slightly more complicated for template overrides. Let's say you don't want to show the site description ("tagline") above the banner image. That tagline is referenced in the header template, not in the CSS. To get started, copy the
header.php template over from the parent theme into your child theme's folder. Now edit the new copy of
header.php, find this line:
and remove it. The same is true for any templates you want to override - copy that template into your child theme folder and edit it as needed. When WordPress detects a conflicting template file name in both the child and parent theme folders, it'll use the one found in the child theme. When the 2010 parent theme is next updated, your child theme will inherit all (or most) of its improvements and bug fixes, and you won't lose any of your customizations.
Yes, it's possible that there could be improvements to the templates you've decided to override, and you would miss those improvements in your upgrade. But that won't happen often, and you'll still benefit from changes to the rest of the theme. You can always copy changes over into your modified templates manually, if necessary.
Page Hacks / Custom Templates
Sometimes you have a need to create a highly customized page in WordPress. Sure, you can always create a new standard page and put whatever you like in the content area, but what if you want to do something that utilizes template tags? Those don't work in content fields - they only work in templates.
For example, let's say you've used the WordPress Links Manager and have built up more than 100 links. That's not going to work in your sidebar - too long! You need a way to create a custom page template that can utilize any of the Template Tags in the Codex.
First, let's get comfortable with the
wp_list_bookmarks() function, and use it to add links to our sidebar with it, rather than with a widget (this will give us a lot more customizability than a widget would). By calling
wp_list_bookmarks() manually, you'll have full control over the way links are displayed.
Let's say you want to show only the links in categories #2 and #3, but you want them mixed (not categorized), and you want the whole block wrapped in HTML <span> tags, and you want associated images to be displayed, but you don't want descriptions used, and you want them all sorted by URL. This code (in the
sidebar.php template) will do the trick:
Use a custom Page template instead
Since 100 links aren't going to fit into the typical sidebar, let's create a new Page called "Resources" with the slug "resources" (adjust the instructions below if you call your page something else). Don't add any text to the page body. Publish the page.
Log into your site via FTP and navigate to
wp-content/themes/[yourtheme]. Find the
page.php and duplicate/copy it. Give the new file the name
page-resources.php in a text editor. What you see in this template depends on the exact theme you're using, but basically, you want to find the code that causes the page content to be displayed and remove it. In the case of the default "2010" theme, it's a one-liner:
Replace this with the code you want to use to display your list of links exactly the way you want them, e.g.:
What we've done is to remove the guts of the page template - the part that pulls in article content - and replaced it with code that brings in our custom bookmarks list. Season to taste!
Note the trick we used above - to create a template that applies to just one page, create a template called
page-foo.php, where "foo" is the slug of the page you want to call the template. The same trick can be used if you need a certain category to utilize a custom template (but you'd use
You can use this technique to customize the view of any Page in your system with great flexibility!
Example: A Wider Content Area
Every site design has a "content area" with a given width, and this width determines the maximum size for media that can be embedded in that page. Try to embed media wider than the content area and it will either be clipped, or it will stomp all over the sidebar. But sometimes, you want the ability to let site authors say "For this post only, suppress the sidebar and give me a content area that's as wide as the site design itself." Setting this up will make your authors and editors really happy, and it's also a rewarding experiment in WordPress theme hacking.
We need the ability to:
- Let an author specify that a given post needs special treatment
- Detect that setting in the template
- Suppress inclusion of the sidebar
- Change the CSS width of the content area
Every WordPress Post view has an optional Custom Fields section. If you don't see it, click the Screen Options tab at the top of the Post writing view. Create a new test post, enable the Custom Fields section, and create a new custom field with the exact Name "full_width". Into the Value field enter the value "1". Save the post.
Now we need to know which template handles single post views, since this is where the action should take place. In most themes, this template will be
single.php. Open that template in a text editor and find the place where it invokes the sidebar:
We need to wrap this in a "conditional" that tests whether the current page is set to use the full width option. Replace that line with this:
This PHP says "Call the function
get_post_width() with an argument that is the ID of the post currently being viewed. If that function does NOT return true (i.e. if the author did not set this post to be full-width), pull in the sidebar." In other words, only pull in the sidebar if the author has not set the post to be full-width.
But wait, where did this
get_post_width() function come from? It's not a native WordPress function, and it's not provided by any plugin. We have to write it ourselves! Look to see whether your theme has a
functions.php file. If it doesn't, create it. Go to the end of that file and paste this code:
Now your theme becomes aware of this function that's been called from within the template. Save both files and access that post on your WordPress site. Voila! No more sidebar (but the sidebar is still present on all other Posts).
That gets us most of the way there ... but simply dropping the sidebar doesn't automagically make the content area wider. The content area width is defined in the stylesheet, not in the template, and we can't put programming logic into the stylesheet! True enough - all we can do in the template is to change the name of the containing div, and define an alternate div width in the stylesheet. So, back in
single.php, find the div that wraps around your post content, creating the content block (use your debugger to find it, if necessary!). It may look something like this:
Now we're going to wrap that in a conditional, just like we did with the sidebar inclusion. Replace the line above with this:
See what we did there? If the option "full_width" is enabled for that post, the containing div gets an alternate CSS ID. Otherwise it uses the usual one. To test that this is working, refresh the page and view source - you should see the alternately named div.
Finally, open up your stylesheet and define the rule for your alternate div. In this example, we already had this:
All we have to do is add another rule just below it, like this:
That should do it! Of course, every theme is different (uses different CSS techniques and naming conventions) - you'll need to tweak this to match the requirements of your own theme.
And that's it - a crash course on WordPress theme modification. We haven't covered all of the bases, but you should now understand how themes work, and where to look in the codebase to change the things you want changed. You'll need to rely on your HTML/CSS skills to make substantial changes, but you'll be surprised by how much you can accomplish with a bit of practice. Happy hacking!
About this Tutorial
This tutorial was written for participants in the Knight Digital Media Center's training programs, and also for students of the UC Berkeley Graduate School of Journalism, but should be useful to anyone interested in modifying WordPress themes.
This content may not be republished in print or digital form without express written permission from KDMC. Please see our Content Redistribution Policy at kdmc.berkeley.edu/license.