iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Themes

A WordPress theme is the presentation layer — templates, styles, scripts, theme.json. Modern WP supports both classic PHP themes and block (FSE) themes that edit visually in the Site Editor.

Classic vs block, anatomy, theme.json

EXAMPLE
<?php
/*
 * Theme Name: My Theme
 * Description: Custom theme for example.com
 * Author:      Ada Lovelace
 * Version:     1.0.0
 * Text Domain: my-theme
 * Requires at least: 6.5
 * Requires PHP: 8.1
 */

// === 1. functions.php — theme bootstrap ===
add_action('after_setup_theme', function () {
    add_theme_support('post-thumbnails');
    add_theme_support('title-tag');
    add_theme_support('html5', ['search-form','comment-form','comment-list','gallery','caption','script','style']);
    add_theme_support('responsive-embeds');
    add_theme_support('wp-block-styles');
    add_theme_support('align-wide');
    add_theme_support('editor-styles');
    add_editor_style('assets/css/editor.css');

    register_nav_menus([
        'primary' => __('Primary', 'my-theme'),
        'footer'  => __('Footer',  'my-theme'),
    ]);
});

add_action('wp_enqueue_scripts', function () {
    $ver = wp_get_theme()->get('Version');
    wp_enqueue_style(
        'my-theme',
        get_stylesheet_uri(),
        [],
        $ver,
    );
    wp_enqueue_script(
        'my-theme-app',
        get_stylesheet_directory_uri() . '/assets/js/app.js',
        [],
        $ver,
        true,    // in footer
    );
});

// === 2. Template hierarchy (classic) ===
// WP picks templates in this order. First match wins.
//   single-product.php → single.php → singular.php → index.php
//   page-about.php     → page-{slug}.php → page.php → singular.php → index.php
//   category-news.php  → category.php → archive.php → index.php
//   404.php
//   front-page.php (homepage)
//   home.php       (blog index, if front page is static)

// === 3. The Loop — classic ===
// archive.php
get_header(); ?>
<main class="main">
    <?php if (have_posts()) : ?>
        <ul class="posts">
            <?php while (have_posts()) : the_post(); ?>
                <li>
                    <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
                        <h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
                        <p class="meta"><?php the_time('F j, Y'); ?> by <?php the_author(); ?></p>
                        <div class="excerpt"><?php the_excerpt(); ?></div>
                    </article>
                </li>
            <?php endwhile; ?>
        </ul>

        <?php the_posts_navigation(); ?>
    <?php else : ?>
        <p>No posts found.</p>
    <?php endif; ?>
</main>
<?php get_footer();

// === 4. Block themes (FSE) — templates in /templates and /parts ===
// theme structure:
//   /templates/index.html
//   /templates/page.html
//   /templates/single.html
//   /templates/404.html
//   /parts/header.html
//   /parts/footer.html
//   theme.json
//   functions.php
//   style.css

// templates/single.html
// <!-- wp:template-part {"slug":"header","tagName":"header"} /-->
// <!-- wp:group {"tagName":"main"} -->
//   <main>
//     <!-- wp:post-title {"level":1} /-->
//     <!-- wp:post-featured-image /-->
//     <!-- wp:post-content /-->
//   </main>
// <!-- /wp:group -->
// <!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->

// === 5. theme.json — global styles + settings ===
// theme.json
{
    "$schema":   "https://schemas.wp.org/wp/6.5/theme.json",
    "version":   2,
    "settings": {
        "color": {
            "palette": [
                { "name": "Primary", "slug": "primary", "color": "#0ea5e9" },
                { "name": "Text",    "slug": "text",    "color": "#0b0f1a" },
                { "name": "BG",      "slug": "bg",      "color": "#ffffff" }
            ],
            "customDuotone": false
        },
        "typography": {
            "fontSizes": [
                { "name": "Small", "slug": "small", "size": "0.875rem" },
                { "name": "Base",  "slug": "base",  "size": "1rem" },
                { "name": "Large", "slug": "large", "size": "1.5rem" }
            ],
            "fontFamilies": [
                { "name": "Inter", "slug": "inter", "fontFamily": "Inter, system-ui, sans-serif" }
            ]
        },
        "layout": {
            "contentSize": "680px",
            "wideSize":    "1024px"
        },
        "spacing": {
            "units": ["px","em","rem","vh","vw","%"],
            "spacingScale": { "steps": 7 }
        }
    },
    "styles": {
        "color": {
            "background": "var(--wp--preset--color--bg)",
            "text":       "var(--wp--preset--color--text)"
        },
        "typography": {
            "fontFamily": "var(--wp--preset--font-family--inter)",
            "fontSize":   "var(--wp--preset--font-size--base)"
        }
    }
}

// === 6. Asset organisation ===
// /assets/css/main.css
// /assets/js/app.js
// /assets/img/...
// /assets/fonts/...

// === 7. Sanitise + escape EVERYTHING ===
<?php echo esc_html($title); ?>             // text content
<?php echo esc_attr($css_class); ?>         // attribute
<?php echo esc_url($url); ?>                // href / src
<?php echo wp_kses_post($rich_html); ?>     // limited HTML

// === 8. Child theme — extend a parent without modifying it ===
// Create:
//   /wp-content/themes/twentytwentyfive-child/style.css   (header below)
//   /wp-content/themes/twentytwentyfive-child/functions.php
//
// style.css header:
/*
  Theme Name:    My Twenty Twenty-Five Child
  Template:      twentytwentyfive
  Version:       1.0.0
*/
//
// functions.php — enqueue parent + child styles
add_action('wp_enqueue_scripts', function () {
    wp_enqueue_style('parent-style', get_template_directory_uri() . '/style.css');
    wp_enqueue_style(
        'child-style',
        get_stylesheet_directory_uri() . '/style.css',
        ['parent-style'],
        wp_get_theme()->get('Version'),
    );
});

// === 9. Internationalisation ===
add_action('after_setup_theme', function () {
    load_theme_textdomain('my-theme', get_template_directory() . '/languages');
});

// Use:  __('Hello', 'my-theme')  /  _e('Hello', 'my-theme')

// === 10. Best practices ===
//   • Pin minimum PHP + WP versions in style.css header
//   • Always escape on output
//   • Use wp_enqueue_* (never echo <script> tags)
//   • Block theme + theme.json — visually editable, future-proof
//   • Page templates: register via Template Name comment
//   • Custom block patterns: /patterns/*.php with block markup
//   • CSS files served with versioned URL — bypass browser cache

Why it matters

Modern WordPress = block themes + theme.json. Classic PHP themes still work, but FSE lets clients edit visually without touching code — vastly less “please change this header” ticket flow.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Theme = look + templates.
// wp-content/themes/your-theme/style.css declares it.
Try it Yourself »

Discussion

Loading…