Back to Top

Organizing Theme Files

Previous Post:

Organizing Theme Files

As a developer and also an end-user, I have been bothered by the same question again and again: How should I organize files within my theme’s root and which themes can be considered as well-structured?

If you have read another article named WordPress Themes’ Problems and How to Find Good Ones on BetterWP.net, you would know that WordPress Themes have many potential problems and one of which is about theme files’ organization. Each theme you download will probably have a different file structure, for example LightWord and Arras, two of the most popular free themes on WordPress.org, use different structures and different naming mechanisms.

A WordPress theme is nothing similar to what we used to think about themes and templates in the past. It works just like a ‘special’ plugin because in theme files you can simply do anything you want without limitation. It can actually turn into a separate project with its own classes, functions, and well, plugins, and that’s why theme developers often come up with different file structures, to suit the functionality provided by the theme. It is, therefore, such a hard task to write an official guide on how to organize your theme files so that end-users and especially other developers find it easy to read and customize. This article is not intended to provide one either because it is simply impossible, I just want to write about some tips (not spoiler-free) that you can use when organizing your theme’s files.

The “unspoken Rules”

There are some “unspoken rules” that many theme developers adhere to, for example images files are put inside a folder named ‘images‘ and Javascript files are put inside another folder named ‘js‘ or ‘javascripts‘ (‘js’ is preferred). ‘Images’ and ‘js’ folders are then put in your theme’s root. If you have more than one CSS files (not including style.css), they should be put inside a separate folder named ‘css‘ in your theme’s root, too.

Normally if you use a structure like this:

.theme_root
/css
/css/mycss.css
/css/images
/css/images/image.gif
/js

using image.gif as a background image can be done rather easily in mycss.css:

.class {
	background-image: url('images/image.gif');
}

In case the ‘images’ folder is not inside the ‘css’ folder, however, you might run into a common problem regarding relative paths in CSS files. This part: background-image: url('images/image.gif'); will not work anymore as your browser will look for image.gif inside root/css/images/ while we need it to look inside root/images/ instead. To work around this, you simply need to change the mentioned rule to: background-image: url('../images/image.gif'); (basically .. means ‘up one directory before searching’).

If your CSS files are categorized in sub-folders like this:

.theme_root
/css
/css/index
/css/index/sidebar.css
/css/page
/css/page/sidebar.css
/images
/images/image.gif

you only need to add an appropriate number of .. to the above CSS rule, each of which indicates one folder to move up, like so: background-image: url('../../images/image.gif');. This allows the browser to correctly locate our image file wherever the CSS file is located.

There are some cases when you can not apply those rules above for your media files, especially when you are using third party scripts or libraries. For example when you use a Javascript popup image viewer you will notice that it comes with its own folders of images and CSS files. If you move those images elsewhere you will have to modify the CSS files as well, which makes updating the Javascript viewer uneasy. In these cases you should, in my opinion, leave the third party library’s structure alone and put the whole package inside the ‘js’ folder, so your structure might look like this:

.theme_root
/css
/images
/js
/js/jsViewer.js
/js/jsViewer
/js/jsViewer/images
/js/jsViewer/css

If your theme supports internationalization1 you might as well create a folder named ‘languages‘ (or ‘lang’) and put all those .po and .mo files (plus a .pot file if possible) inside. Once again it is suggested that you put the ‘languages’ folder in your theme’s root.

Other (optional) files, such as the theme’s license, readme, etc., should all be put inside theme’s root. It is also recommended that you use plural names for your folders (except for ‘js’ and ‘css’ of course).

If you follow this article from the beginning, your theme’s structure will probably look like this:

.theme_root
/css
/images
/js
/languages
/license.txt
/readme.txt
/screenshot.png
/style.css
... other files

What about those PHP files, the actual magic behind themes? I’m afraid that there aren’t any rules that can apply to PHP files’ organization (look at Joomla!, Drupal or even WordPress and see how each project organizes their PHP files, you will understand what I mean). For such reason, we will move to the next section where I can freely describe my ideas that might contain major spoilers :P.

The Ideas

There are some theme’s PHP files we can not touch because the core WordPress needs them to function correctly, such as functions.php, index.php, etc. (you can see a full list here: http://codex.wordpress.org/Theme_Development) so we will have to leave them as-is (unless you use some template filters2, of course). What we should organize here is our custom PHP files which can be any classes or any third party PHP libraries that our theme needs. They should be put inside one single folder named either ‘library‘ or ‘includes‘. That folder will then be put in theme’s root. In fact ‘library’ has a broader meaning than ‘includes’ as it indicates that the folder can contain other type of files rather than PHP files. Choosing the name is a matter of personal taste but I do prefer ‘includes’ (and I will use ‘includes’ for the rest of this article if you don’t mind).

Inside ‘includes’ you should put files that provide global functions, e.g.functions_post_contents.php, functions_external_links.php, etc. You can also put single-file classes, i.e. class that span no more than one PHP file. For third party libraries (such as plugins) or other classes that span more than one PHP files you should create sub-folders for each of them. In such cases you might use Zend Framework’s naming convention3 for easier file management. You can look at phpBB‘s organization of PHP files for an example of this approach.

Another approach you can take is creating WordPress-related sub-folders such as ‘templates‘, ‘functions‘, ‘comments‘, etc. to store PHP files. Hybrid, a popular theme framework, uses this structure and I think it’s pretty clever. However I have to say that having many folders like that might eventually confuse you later on when you’re adding many functions to your theme (trust me, because I use Hybrid’s structure for this website ;)).

When you organize your PHP files keep in mind that relative paths can (again) cause a fatal PHP error if you don’t use include_once() or require_once() the right way. For example if you have a structure like this:

.theme_root
/css
/images
/js
/includes
/includes/function.php
/includes/class
/includes/class/function1.php
/includes/class/function2.php

with function.php being:

include_once('class/function1.php');

and function1.php being:

include_once('./function2.php');

you will be greeted with a fatal PHP error that tells you the parser can not find function2.php. The reason is the first include_once() in function.php will look for function2.php in root/includes instead of root/includes/class, it is simply the way relative path works. The safest way o fix this is change include_once('./function2.php'); into include_once(dirname(__FILE__) . '/function2.php');. Problem solved!

The Bottom Line

Organizing theme files so that it is easy for end-users as well as developers to customize is not an easy task. There is no strict rules nor perfect guides that you should follow but what really matters in my opinion is the consistency of your theme. I hope you will find this article useful and develop amazing themes! Thanks for reading!

References

  1. http://codex.wordpress.org/I18n_for_WordPress_Developer ... Developers []
  2. http://codex.wordpress.org/Plugin_API/Filter_Reference# ... te_Filters []
  3. http://framework.zend.com/manual/en/coding-standard.nam ... tions.html []

Take Social Sharing to
the Next Level with Monarch!

Take Social Sharing to the Next Level with Monarch!
Print Article Trackback Trackback to this Article   Subscribe to Comments RSS Subscribe to Comments RSS

Speak Up Your Mind!

An asterisk (*) indicates a required field and must be filled.




  • Web page and e-mail addresses turn into links automatically.
  • Wrap codes in: <code lang=""></code> or <pre lang="" extra="">
  • Lines and paragraphs break automatically.

Next Post: