This guide is for anyone interested in making the best possible WordPress themes. Each public theme on WordPress.com is tested against these guidelines to ensure the highest quality. This includes security, plugin compatibility, and support for a wide variety of user-generated content.
Escaping
- All dynamic data must be escaped with
esc_attr()before rendered in an html attribute. - All dynamic urls must be escaped with
esc_url(). - If dynamic data is rendered as the attribute of a html script element, it must be escaped with
esc_js(). - SQL queries containing dynamic data must be escaped with
$wpdb->prepare().
Internationalization
- All user-facing text must be prepared for translation.
- Avoid HTML inside strings passed to gettext functions wherever possible.
- The output of
sprintf()must be escaped in text strings used in attributes. printf()placeholders must be escaped before included in HTML attributes.- Provide context where appropriate.
- Avoid common anti-patterns.
Queries
- Raw SQL queries should be avoided. It is better to use a new
WP_Queryobject whenever possible. - Unbounded queries may not be used. Basically this means that the
posts_per_pageparameter ofWP_Querymay not be set to-1. Also, thenumberpostsparameter ofget_posts()(and similar functions) must also have a positive value. - Expensive queries should be transient cached.
query_posts()is not allowed. If you need to modify the main query it is best to use thepre_get_postsfilter. If you need to retrieve posts in addition to the main query it is best to use a newWP_Queryobject.- Empty values may not be passed to the
post__inargument used to create a newWP_Queryobject. If you are using a dynamic value that could be empty it is important to check for empty before using the value in the query. Code example. - Term queries should be tested on an installation with 10,000 terms.
Enqueues
- All 3rd party, bundled files must be GPL compatible.
- Ensure the correct protocol is used for enqueuing 3rd-party files.
- Ensure that the approprite hooks are used to enqueue scripts and styles.
Scripts
- Use core-bundled scripts if they exist.
- Custom scripts should not be minified.
- Bundled 3rd party scripts may be minified but must include this information.
Styles
- The main stylesheet (style.css) must be enqueued during the
wp_enqueue_scriptsaction. overflow:hiddenshould never be used to contain floats. The micro clearfix is a better alternative.- The
!importantkeyword should not be used where specificity would suffice. - When enqueuing a Google font with multiple character sets, conditionally include the sets with gettext.
- Style attributes on HTML tags are not permitted.
Plugin Conflicts
The WordPress.com environment is super-charged with an extensive set of plugins that provide functionality that is shared across all themes. To provide our users with the most consistent experience we ask that functionality that duplicates our plugins not be included on the theme level.
- Advertising options are handled via WordAds.
- Custom color options are handled by the Custom Colors plugin.
- Custom fonts options are handled by the Custom Fonts plugin.
- Favicons are handled via Blavatar plugin.
- HiDPI support for user-provided images
- Infinite Scroll is handled by Jetpack.
- Open Graph Protocol
- Twitter meta tag support
- Various widgets
Data Portability
Ensuring that a user’s content does not change when they switch themes is very important. The following features of WordPress core, while awesome in their own right, can cause a user’s content to change or become unreachable if implemented on the theme level.
- Public Custom Post Types
- Public Custom Taxonomies
- Custom Fields AKA Post Meta
- Shortcodes
Theme Options
If your theme includes custom options, we strongly suggest that the Customizer be used instead of a custom admin screen. Doing so has many benefits:
- Users can immediately see their changes as they adjust the UI.
- There is much less code to write.
- Built in user interface modules for the most common situations.
In the event that your theme needs to provide a custom options screen in the admin here are the requirements:
- Must be a child of the Appearance menu with a title “Theme Options”.
- Use of the WordPress Settings API is required.
- All options must be stored as a single serialized array.
- Default options may not be inserted into the database upon installation or http request.
- All values must be sanitized before saved to the database.
- Core functionality must be used for any file uploads.
Most, if not all of these requirements are illustrated in this Theme Options Starter File.
Miscellaneous
- Full loops must be used in all templates. Just calling the_post() in a template like single.php or page.php is not enough.
- The $content_width global must be set correctly.
- Visible links to feeds should not appears in themes. We suggest that site owners use the Follow Blog Widget on WordPress.com to allow their visitors to subscribe.
Usability Guidelines
The WordPress.org Theme Unit Test Data is comprised of multiple posts and pages designed to push your theme to the limits. Please download the data and import to your test server. Running your theme through all of the provided tests can help ensure that your theme will be flexible enough to handle a wide variety of actual user data.
Resources
- These guidelines are intended to be used alongside the WordPress Theme Review guidelines.
- WordPress Codex, the online manual for WordPress and a living repository for WordPress documentation.
- The ThemeShaper WordPress Theme Tutorial: 2nd Edition
- We recommend the _s theme, also known as Underscores.
- Developer is a plugin that will prompt you to install a number of plugins that are helpful during development, including Theme Check, VIP Scanner, and Monster Widget.