Do’s and Don’ts of WordPress Theme Development
Ulrich Pogson
Theme Reviewer on WordPress.org
Development Envoirment
Enable WP_DEBUG
style.css
/*
Theme Name: _s
Theme URI: http://underscores.me/
Author: Automattic
Author URI: http://automattic.com/
Description: Hi. I'm a starter theme called <code>_s</code>,
or <em>underscores</em>, if you like. I'm a theme meant for
hacking so don't use me as a <em>Parent Theme</em>. Instead
try turning me into the next, most awesome, WordPress theme
out there. That's what I'm here for.
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: _s
Tags: black, blue, brown, gray, three-columns, featured-images,
accessibility-ready, translation-ready
*/
Readme/License
Don't...
...release a theme without a license
Do...
...define the theme license
...make a note of the resources used in the theme.(License of assets - Fonts, CSS, JS, Images, PHP, etc)
PHP Prefixing
PHP function names
function _s_setup() { }
PHP class names
class _s_Setup { }
PHP global variables
global $_s_variable;
PHP constants
_S_VERSION
WordPress Prefixing
Action/Filter hooks
apply_filters( '_s_content_width', 640 );
Script/Style handles
wp_enqueue_style( '_s-style' );
Image size names
add_image_size( '_s-large', '800', '400' );
Breaking the rules
- Third-party script/style handles
- Third-party PHP scripts/libraries
- Standard Image sizes
// Scripts
wp_enqueue_script( 'jquery-fitvids', get_template_directory_uri()
. '/js/jquery.fitvids.js', array( 'jquery' ), '1.1.1', true );
// Function and Classes
class TGM_Plugin_Activation { ... }
// Custom image size
add_image_size( '910x460-crop', 910, 460, true );
Settings
Don't...
...save every single option as a single row
Do...
...a single array for all the options
...use sane defaults
Sanitizing
// Customizer
$wp_customize->add_setting(
'twitter_url',
array(
'default' => 'https://twitter.com/grapplerulrich',
'transport' => 'postMessage',
'sanitize_callback' => 'esc_url_raw',
)
);
// Settings API
register_setting(
'_s_options_group',
'_s_options',
'_s_sanitize_settings'
);
Escaping
// Insecure
echo get_theme_mod( 'twitter_url' );
// Secure
echo esc_url( get_theme_mod( 'twitter_url' ) );
$_s_options = get_option( '_s_options' );
echo esc_url( $_s_options['twitter_url'] );
Use Core Features
Use the functions, actions and filters that WordPress core provides
Don't reinvent the wheel
Plugin Territory
Themes are presentation not functionality
Functionality
Chose a theme on it's design not it's features
Contact forms
SEO Settings
Small improvements to WordPress
Content
Where is my content after switching themes?
Shortcodes
Custom Post Types
Non presentational metadata
Content
Don't...
...include custom widgets that save content
...save content in the theme settings
Do...
...use WordPress features like Sidebars, Pages and Menus
Internationalization
Create a POT file
Define the Text Domain in the Style.css
Use the same text domain as the theme slug
Checklist
- Have I defined the licences correctly?
- Is my code prefixed correctly?
- Are you saving the settings correctly?
- Is my code fully sanitized and escaped?
- Is there a WordPress method that I could use instead?
- Is my code translation-ready?
- Is my theme only presentational?
Resources
Do’s and Don’ts of WordPress Theme Development
By Ulrich Pogson
Do’s and Don’ts of WordPress Theme Development
- 3,183