Skip to main content

Course Progress

Loading...

Theme Requirements and Standards

Duration: 50 minutes
Module 5: Session 1.2

Learning Objectives

  • Understand WordPress.org theme directory requirements
  • Learn WordPress coding standards for themes
  • Master security best practices for theme development
  • Understand accessibility requirements
  • Learn about licensing and GPL compliance

Introduction

Creating a WordPress theme that meets professional standards requires following established guidelines for code quality, security, accessibility, and licensing. Let's explore the requirements that ensure your theme is robust, secure, and ready for distribution.

💡
Why Standards Matter
Following WordPress standards ensures your theme is compatible with WordPress core, plugins, and future updates while providing a consistent experience for users and developers.

Minimum Theme Requirements

Every WordPress theme must have at least these two files:

1. style.css - The Main Stylesheet

/*
Theme Name: Twenty Twenty-Five
Theme URI: https://wordpress.org/themes/twentytwentyfive/
Author: the WordPress team
Author URI: https://wordpress.org/
Description: Our default theme for 2025 is designed to be flexible, versatile and applicable to any website.
Requires at least: 6.0
Tested up to: 6.4
Requires PHP: 7.4
Version: 1.0
License: GPL v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: twentytwentyfive
Tags: blog, custom-background, custom-colors, custom-logo, custom-menu, editor-style, featured-images, footer-widgets, block-patterns, rtl-language-support, sticky-post, threaded-comments, translation-ready, accessibility-ready
*/

2. index.php - The Main Template File

<?php
/**
 * The main template file
 *
 * This is the most generic template file in a WordPress theme
 * and one of the two required files for a theme (the other being style.css).
 */

get_header();
?>

<main id="primary" class="site-main">
    <?php
    if ( have_posts() ) :
        // Start the Loop
        while ( have_posts() ) :
            the_post();
            
            // Include the Post-Format-specific template
            get_template_part( 'template-parts/content', get_post_format() );
        endwhile;
        
        // Posts navigation
        the_posts_navigation();
    else :
        // If no content, include the "No posts found" template
        get_template_part( 'template-parts/content', 'none' );
    endif;
    ?>
</main>

<?php
get_sidebar();
get_footer();

WordPress Coding Standards

WordPress has specific coding standards for PHP, HTML, CSS, and JavaScript:

PHP Coding Standards

<?php
// ✅ CORRECT: Using WordPress coding standards

// Naming Conventions
function my_theme_enqueue_scripts() {  // snake_case for functions
    $theme_version = '1.0.0';          // snake_case for variables
    
    // Proper spacing around operators
    if ( is_single() && ! is_attachment() ) {
        wp_enqueue_script( 
            'my-theme-single',          // kebab-case for handles
            get_template_directory_uri() . '/assets/js/single.js',
            array( 'jquery' ),           // Dependencies
            $theme_version,
            true                         // Load in footer
        );
    }
}
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_scripts' );

// ❌ INCORRECT: Not following standards
function myThemeEnqueueScripts(){      // Should use snake_case
    $themeVersion="1.0.0";              // Missing spaces
    if(is_single()&&!is_attachment())  // Missing spaces
    {                                   // Brace should be on same line
        wp_enqueue_script('my_theme_single',...); // Should use kebab-case
    }
}

HTML Standards

<!-- ✅ CORRECT: Semantic HTML5 -->
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
    <header class="entry-header">
        <?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
        
        <div class="entry-meta">
            <time datetime="<?php echo get_the_date( 'c' ); ?>">
                <?php echo get_the_date(); ?>
            </time>
        </div>
    </header>
    
    <div class="entry-content">
        <?php the_content(); ?>
    </div>
</article>

<!-- ❌ INCORRECT: Non-semantic HTML -->
<div class="post">
    <div class="title"><?php the_title(); ?></div>
    <div class="content"><?php the_content(); ?></div>
</div>

CSS Standards

/* ✅ CORRECT: Following CSS standards */
.site-header {
    background-color: #ffffff;
    padding: 1.5rem 0;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.site-header .site-title {
    font-size: 1.875rem;
    font-weight: 700;
    margin: 0;
}

/* Media Queries */
@media screen and (min-width: 768px) {
    .site-header {
        padding: 2rem 0;
    }
}

/* ❌ INCORRECT: Not following standards */
.site-header{background:#fff;padding:1.5rem 0}  /* Everything on one line */
.site-header .site-title{font-size:30px}        /* Using px instead of rem */

Security Requirements

Security is paramount in theme development. Follow these essential practices:

🔐
Security First
Never trust user input. Always escape output and sanitize data to prevent XSS attacks and SQL injection.

Data Validation and Sanitization

<?php
// ✅ CORRECT: Escaping output
?>
<h1><?php echo esc_html( get_the_title() ); ?></h1>
<a href="<?php echo esc_url( get_permalink() ); ?>">Read More</a>
<div class="<?php echo esc_attr( $custom_class ); ?>">Content</div>

<?php
// Sanitizing input
$clean_email = sanitize_email( $_POST['email'] );
$clean_text = sanitize_text_field( $_POST['username'] );
$clean_html = wp_kses_post( $_POST['bio'] );

// ❌ INCORRECT: Direct output without escaping
?>
<h1><?php echo $title; ?></h1>  <!-- Unsafe! -->
<a href="<?php echo $url; ?>">Link</a>  <!-- Unsafe! -->

Nonce Verification

<?php
// Creating a form with nonce
function my_theme_render_form() {
    ?>
    <form method="post" action="">
        <?php wp_nonce_field( 'my_theme_form_action', 'my_theme_form_nonce' ); ?>
        <input type="text" name="user_data" />
        <button type="submit">Submit</button>
    </form>
    <?php
}

// Verifying nonce on submission
function my_theme_process_form() {
    if ( ! isset( $_POST['my_theme_form_nonce'] ) || 
         ! wp_verify_nonce( $_POST['my_theme_form_nonce'], 'my_theme_form_action' ) ) {
        wp_die( 'Security check failed' );
    }
    
    // Process the form data
    $user_data = sanitize_text_field( $_POST['user_data'] );
}

Accessibility Requirements

Themes should be accessible to all users, including those using assistive technologies:

graph LR A[Accessibility] --> B[Keyboard Navigation] A --> C[Screen Reader Support] A --> D[Color Contrast] A --> E[Focus Indicators] A --> F[ARIA Labels] A --> G[Semantic HTML] style A fill:#e3f2fd

Accessibility Best Practices

<!-- ✅ CORRECT: Accessible navigation -->
<nav id="site-navigation" class="main-navigation" role="navigation" 
     aria-label="<?php esc_attr_e( 'Primary Menu', 'textdomain' ); ?>">
    
    <button class="menu-toggle" aria-controls="primary-menu" 
            aria-expanded="false">
        <span class="screen-reader-text">
            <?php esc_html_e( 'Menu', 'textdomain' ); ?>
        </span>
        <span class="menu-toggle-icon" aria-hidden="true">☰</span>
    </button>
    
    <?php
    wp_nav_menu( array(
        'theme_location' => 'primary',
        'menu_id'        => 'primary-menu',
        'menu_class'     => 'nav-menu',
        'container'      => 'ul',
    ) );
    ?>
</nav>

<!-- Skip links for keyboard navigation -->
<a class="skip-link screen-reader-text" href="#content">
    <?php esc_html_e( 'Skip to content', 'textdomain' ); ?>
</a>

Color Contrast Requirements

/* ✅ CORRECT: Sufficient color contrast */
.entry-content {
    color: #212529;      /* Dark text */
    background: #ffffff; /* White background */
    /* Contrast ratio: 12.63:1 - Passes WCAG AAA */
}

.entry-content a {
    color: #0066cc;      /* Link color */
    text-decoration: underline;
    /* Contrast ratio: 8.59:1 - Passes WCAG AAA */
}

/* Focus indicators */
a:focus,
button:focus,
input:focus,
textarea:focus,
select:focus {
    outline: 2px solid #0066cc;
    outline-offset: 2px;
}

Internationalization (i18n)

Make your theme translation-ready from the start:

<?php
// ✅ CORRECT: Translation-ready strings

// Simple string
esc_html_e( 'Read More', 'my-theme-textdomain' );

// String with variable
printf(
    /* translators: %s: Post title */
    esc_html__( 'Leave a comment on %s', 'my-theme-textdomain' ),
    get_the_title()
);

// Plural forms
printf(
    /* translators: %s: Number of comments */
    esc_html( _n(
        '%s Comment',
        '%s Comments',
        get_comments_number(),
        'my-theme-textdomain'
    ) ),
    number_format_i18n( get_comments_number() )
);

// Context for translators
_x( 'Read', 'past participle: books I have read', 'my-theme-textdomain' );

// ❌ INCORRECT: Hard-coded strings
echo 'Read More';  // Not translatable
echo "Posted on $date";  // Not translatable

Loading Text Domain

<?php
/**
 * Load theme textdomain
 */
function my_theme_load_textdomain() {
    load_theme_textdomain( 
        'my-theme-textdomain', 
        get_template_directory() . '/languages' 
    );
}
add_action( 'after_setup_theme', 'my_theme_load_textdomain' );

Licensing Requirements

WordPress themes must be GPL-compatible:

📜
GPL License
All PHP and JavaScript in WordPress themes must be GPL v2 (or later) compatible. CSS and images can be under different licenses but should be clearly stated.

License Declaration

<?php
/**
 * My Theme functions and definitions
 *
 * @package My_Theme
 * @since 1.0.0
 * @license GPL v2 or later
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

WordPress.org Directory Requirements

If you plan to submit your theme to WordPress.org, additional requirements apply:

Required Theme Support Features

<?php
function my_theme_setup() {
    // Required: Automatic feed links
    add_theme_support( 'automatic-feed-links' );
    
    // Required: Title tag support
    add_theme_support( 'title-tag' );
    
    // Required: Post thumbnails
    add_theme_support( 'post-thumbnails' );
    
    // Required: Custom logo
    add_theme_support( 'custom-logo', array(
        'height'      => 100,
        'width'       => 350,
        'flex-height' => true,
        'flex-width'  => true,
    ) );
    
    // Required: HTML5 support
    add_theme_support( 'html5', array(
        'comment-form',
        'comment-list',
        'gallery',
        'caption',
        'style',
        'script',
        'navigation-widgets',
    ) );
    
    // Required: Block editor support
    add_theme_support( 'wp-block-styles' );
    add_theme_support( 'responsive-embeds' );
    
    // Recommended: Custom background
    add_theme_support( 'custom-background' );
    
    // Recommended: Editor styles
    add_theme_support( 'editor-styles' );
    add_editor_style( 'style-editor.css' );
}
add_action( 'after_setup_theme', 'my_theme_setup' );

Theme Standards Best Practices

  • Use Theme Check Plugin: Test your theme against WordPress standards
  • Follow PHP Standards: PSR-2 and WordPress-specific standards
  • Validate HTML: Use W3C validator for HTML5 compliance
  • Test Accessibility: Use WAVE or axe DevTools
  • Check Color Contrast: Ensure WCAG AA compliance minimum
  • Escape Everything: Never output raw data
  • Prefix Everything: Use unique prefixes for functions, classes, and globals
  • Document Your Code: Use PHPDoc for all functions and classes

Practice Exercise

Let's create a standards-compliant theme header file:

💻
Try It Now
Create a style.css file with proper theme headers that includes:
  1. All required header fields
  2. Proper licensing information
  3. Version requirements
  4. Appropriate tags for theme features
  5. Your theme's text domain
Then validate it using the Theme Check plugin.

Additional Resources