Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

The best way to create a new WordPress theme in 2026 is usually to start with a block theme: its templates use block markup, its design system is defined with theme.json, and users can edit templates through the Site Editor. Classic PHP themes remain valid for legacy sites and PHP-heavy projects.

Before writing code, decide whether you actually need a new theme. A child theme is safer when you only want to modify an existing theme, while the Site Editor may be enough for visual changes to an existing block theme.

Should you build a new theme?

Choose a new theme when you control the design and markup, need a reusable design system, are starting from a Figma specification, or want a deliberately small codebase. Choose a child theme when a maintained parent theme already provides most of the layout and features you need. For primarily visual changes, customize an existing block theme in Appearance → Editor before considering a rebuild.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A theme should primarily control presentation: templates, styles, navigation presentation, layout, patterns, and global design settings. Put durable functionality such as custom post types, business logic, forms, ecommerce features, SEO data, and migrations in a plugin. Otherwise, switching themes can remove important site functionality.

Block theme or classic theme?

Concern Block theme Classic theme
Main templates HTML files containing block markup PHP template files
Global design settings theme.json and the Site Editor CSS, Customizer, theme supports, and optionally theme.json
Full-site editing Core capability Limited or unavailable, depending on the theme
Example main template templates/index.html index.php
Reusable layout pieces Template parts and patterns PHP includes and get_template_part()
Best fit New projects and block-first workflows Legacy sites and PHP-heavy customization

Block themes have been part of WordPress since 5.9 and are documented in the Theme Developer Handbook. Classic themes remain supported and appropriate for existing codebases; they are not obsolete.

What you need before creating a theme

  • A local or staging WordPress installation; avoid developing directly on a production site.
  • A code editor and basic HTML and CSS knowledge.
  • PHP knowledge if you are building a classic theme.
  • Browser developer tools and WordPress debugging.
  • Git or another version-control system for serious projects.
  • Backups before activation, migration, or deployment.

A manually installed theme normally belongs in wp-content/themes/. The official getting-started documentation covers development tools and setup.

Create a basic block theme

1. Create the theme folder

Create a uniquely named folder such as my-first-theme inside wp-content/themes/. Avoid generic names such as theme or custom.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The smallest useful block-theme example contains:

my-first-theme/
├── style.css
├── theme.json
└── templates/
    └── index.html

This is a minimal learning theme, not a production-ready design. A practical project will usually add template parts, more templates, patterns, styles, assets, accessibility work, and testing.

2. Add style.css

/*
Theme Name: My First Theme
Author: Your Name
Description: A small block theme built from scratch.
Version: 1.0.0
Text Domain: my-first-theme
*/

The Theme Name field lets WordPress identify the theme in the dashboard. The text domain should normally match the theme slug and is used for translations. Read the documentation for the main stylesheet when adding additional header fields.

3. Add theme.json

theme.json is the configuration layer for a modern block theme. It can define color palettes, typography, spacing, layout widths, appearance tools, block settings, presets, and global styles.

{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "settings": {
    "layout": {
      "contentSize": "700px",
      "wideSize": "1200px"
    },
    "color": {
      "palette": [
        { "slug": "ink", "color": "#222222", "name": "Ink" },
        { "slug": "paper", "color": "#ffffff", "name": "Paper" },
        { "slug": "accent", "color": "#1769aa", "name": "Accent" }
      ]
    },
    "typography": { "fluid": true }
  },
  "styles": {
    "color": {
      "text": "var:preset|color|ink",
      "background": "var:preset|color|paper"
    },
    "elements": {
      "link": {
        "color": { "text": "var:preset|color|accent" }
      }
    }
  }
}

The schema and supported properties can change. Use the current global settings and styles reference when building a real theme rather than treating this sample as permanently authoritative.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

4. Create the first template

Create templates/index.html:

<!-- wp:template-part {"slug":"header","tagName":"header"} /-->

<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
  <!-- wp:query {"query":{"inherit":true}} -->
  <div class="wp-block-query">
    <!-- wp:post-template -->
      <!-- wp:group {"layout":{"type":"constrained"}} -->
      <div class="wp-block-group">
        <!-- wp:post-title {"isLink":true} /-->
        <!-- wp:post-featured-image {"isLink":true} /-->
        <!-- wp:post-excerpt /-->
      </div>
      <!-- /wp:group -->
    <!-- /wp:post-template -->
    <!-- wp:query-pagination -->
      <!-- wp:query-pagination-previous /-->
      <!-- wp:query-pagination-numbers /-->
      <!-- wp:query-pagination-next /-->
    <!-- /wp:query-pagination -->
  </div>
  <!-- /wp:query -->
</main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->

These comments are not ordinary HTML comments. They delimit blocks that WordPress parses and renders. A missing or mismatched block delimiter can produce invalid or broken output. See the official templates documentation for template hierarchy and block-template rules.

5. Add header and footer template parts

Create parts/header.html:

<!-- wp:group {"align":"full","layout":{"type":"constrained"}} -->
<div class="wp-block-group alignfull">
  <!-- wp:site-title /-->
  <!-- wp:navigation /-->
</div>
<!-- /wp:group -->

Create parts/footer.html:

<!-- wp:group {"align":"full","layout":{"type":"constrained"}} -->
<div class="wp-block-group alignfull">
  <!-- wp:paragraph -->
  <p>© Your Site</p>
  <!-- /wp:paragraph -->
</div>
<!-- /wp:group -->

The slug in wp:template-part must match the filename. Template parts are reusable structural pieces; patterns are generally better for reusable content layouts.

6. Install and activate the theme

For a ZIP installation, compress the theme folder so the archive has this shape:

my-theme.zip
└── my-theme/
    ├── style.css
    ├── theme.json
    └── templates/

In WordPress, open Appearance → Themes → Add New → Upload Theme, select the ZIP file, install it, and activate it. You can also copy the folder to wp-content/themes/ and activate it from the Themes screen. The official installation documentation describes both approaches.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

After activation, the site should render through templates/index.html, and a block theme should expose Appearance → Editor.

Expand the block theme

Use the template hierarchy

Add only the templates your site needs:

templates/
├── index.html
├── home.html
├── single.html
├── page.html
├── archive.html
├── search.html
└── 404.html
  • index.html: fallback template.
  • home.html: blog posts index.
  • single.html: individual posts.
  • page.html: static pages.
  • archive.html: category, tag, author, date, and other archives.
  • search.html: search results.
  • 404.html: not-found pages.

These files are not all mandatory. WordPress uses the most specific matching template and falls back when one is absent. That is why a page can still render with only index.html.

Add patterns

Patterns are reusable block layouts for sections such as heroes, calls to action, and feature grids. They can be supplied by a theme or plugin. A theme pattern may live in:

patterns/
├── hero.php
├── call-to-action.php
└── feature-grid.php

PHP pattern files use registration metadata, including a namespaced pattern name and optional categories. Escape dynamic output, translate user-facing text, and avoid filling a site with demo content that is difficult to remove. Put a pattern in a plugin when it represents a reusable business feature rather than a theme-specific presentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Add style variations and CSS

The default design system belongs in theme.json. Alternative designs can be exposed as JSON style variations:

styles/
├── dark.json
└── high-contrast.json

Use CSS for behavior or styling that cannot reasonably be expressed with blocks and global styles. Excessive custom CSS can undermine Site Editor controls and create conflicts with user-saved styles.

Use a realistic structure

my-first-theme/
├── style.css
├── theme.json
├── functions.php
├── templates/
├── parts/
├── patterns/
├── styles/
└── assets/
    ├── css/
    ├── js/
    └── images/

A block theme may include functions.php for setup or asset loading, but do not treat it as a replacement for a plugin. Keep content-critical functionality outside the theme.

Create a classic WordPress theme

Use this route when maintaining a classic site, depending on PHP template logic, or working with a mature codebase built around the Customizer, widgets, or classic menus.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

1. Create the files

The minimum functional classic theme can contain:

my-classic-theme/
├── style.css
└── index.php

A practical theme commonly adds:

functions.php
header.php
footer.php
sidebar.php
single.php
page.php
archive.php
search.php
404.php
comments.php
assets/

2. Add style.css and index.php

/*
Theme Name: My Classic Theme
Author: Your Name
Description: A basic classic WordPress theme.
Version: 1.0.0
Text Domain: my-classic-theme
*/
<?php get_header(); ?>

<main id="primary" class="site-main">
  <?php if ( have_posts() ) : ?>
    <?php while ( have_posts() ) : the_post(); ?>
      <article <?php post_class(); ?>>
        <h2>
          <a href="<?php echo esc_url( get_permalink() ); ?>">
            <?php echo esc_html( get_the_title() ); ?>
          </a>
        </h2>
        <div class="entry-content">
          <?php the_excerpt(); ?>
        </div>
      </article>
    <?php endwhile; ?>
    <?php the_posts_pagination(); ?>
  <?php else : ?>
    <p><?php esc_html_e( 'No content found.', 'my-classic-theme' ); ?></p>
  <?php endif; ?>
</main>

<?php get_footer(); ?>

have_posts() and the_post() form the basic Loop. Template tags retrieve WordPress content, while functions such as esc_url() and esc_html() escape output in the appropriate context. The fallback index.php should remain usable even after more specific templates are added.

3. Add the required document hooks

In header.php:

<!doctype html>
<html <?php language_attributes(); ?>>
<head>
  <meta charset="<?php bloginfo( 'charset' ); ?>">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>

In footer.php:

<?php wp_footer(); ?>
</body>
</html>

Do not omit wp_head(), wp_footer(), or wp_body_open(). Plugins, scripts, styles, analytics, accessibility features, and WordPress integrations may depend on them.

4. Configure the theme in functions.php

<?php

function my_classic_theme_setup() {
  add_theme_support( 'title-tag' );
  add_theme_support( 'post-thumbnails' );
  add_theme_support( 'html5', array(
    'search-form',
    'comment-form',
    'comment-list',
    'gallery',
    'caption',
  ) );

  register_nav_menus( array(
    'primary' => __( 'Primary Menu', 'my-classic-theme' ),
  ) );
}
add_action( 'after_setup_theme', 'my_classic_theme_setup' );

function my_classic_theme_assets() {
  wp_enqueue_style(
    'my-classic-theme-style',
    get_stylesheet_uri(),
    array(),
    '1.0.0'
  );
}
add_action( 'wp_enqueue_scripts', 'my_classic_theme_assets' );

Use wp_enqueue_style() and wp_enqueue_script() rather than hard-coding asset links. Use unique function names and handles. The classic-theme handbook covers setup, hooks, filters, and theme supports.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Test before calling the theme finished

Functional checklist

  • Homepage and blog index.
  • Individual posts and static pages.
  • Category, tag, author, and date archives.
  • Search results and the 404 page.
  • Pagination, featured images, navigation, and comments if supported.
  • Long titles, empty content, missing featured images, and deeply nested navigation.
  • Wide and full-width blocks, mobile layouts, and every style variation.

Technical checklist

  • Validate JSON and check PHP syntax.
  • Enable WordPress debugging in development and inspect browser-console errors.
  • Test keyboard navigation, color contrast, headings, landmarks, and responsive layouts.
  • Test with substantial content as well as an empty site.
  • Confirm styles and scripts are enqueued correctly.
  • Test common plugins and theme switching.

The handbook lists tools including WordPress Coding Standards for PHP_CodeSniffer, WPThemeReview standards, Theme Check, Create Block Theme, and theme-generation tools. Theme Check can identify issues related to review expectations, but it is not a complete security or quality audit. Check the current theme review requirements before submitting to WordPress.org.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Common theme problems and fixes

The theme does not appear

  • Confirm style.css is in the theme root.
  • Check that the stylesheet header is valid.
  • Confirm the folder is inside wp-content/themes/.
  • Check file permissions.
  • Inspect the ZIP for an extra nested directory.

The block theme is blank or broken

Check that templates/index.html exists, block comments are correctly paired, JSON is valid, and template-part slugs match filenames. Confirm that the theme is activated and that another, more-specific template is not overriding the file you edited.

Site Editor changes do not match files on disk

The Site Editor can save customized templates in the database. Those saved customizations may take precedence over files in the theme. If a file change appears to have no effect, reset or clear the customized template in the Site Editor before testing again. The file on disk is not always the active source of rendered markup.

CSS changes are invisible

Clear browser, plugin, and CDN caches. Then check the stylesheet path, theme.json selectors and presets, CSS specificity, and user-saved global styles. In a classic theme, increment the asset version when appropriate.

Classic assets do not load

Confirm the asset is enqueued on the correct hook, the handle is unique, the path uses the correct theme URI, and the markup is not hard-coded in header.php. Also verify that wp_head() and wp_footer() are present and inspect the browser console.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A parent-theme update overwrites changes

This normally means files were edited directly in the parent theme. Use a child theme or a maintained fork instead.

Content disappears after switching themes

Custom post types, shortcodes, metadata, and business logic should not live only in a theme. Move content-critical functionality to a plugin so it remains available when the presentation layer changes.

Package and maintain the theme

For private distribution, package the correctly structured theme folder as a ZIP, document installation and customization, use version control, and define how updates will be delivered. For WordPress.org submission, review current licensing, security, accessibility, localization, coding, and metadata requirements; automated checks do not guarantee approval.

A two-file classic theme or three-file block theme proves that WordPress recognizes the project. It does not provide accessibility, responsive design, archive handling, localization, performance work, security review, or an update strategy. Treat the minimal example as a starting point.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What should you use?

  • Learning theme development: use a local or staging WordPress installation and the official handbook.
  • Custom client project: build a custom block theme, or a child theme when a suitable parent already exists.
  • Fast launch: consider an existing block theme or products such as Kadence or GeneratePress, after checking current pricing and licensing.
  • Budget live hosting: compare introductory and renewal pricing carefully; Bluehost lists both separately.
  • Managed agency hosting: WP Engine may suit teams that value staging, support, security, and operational tooling.
  • Learning only: do not buy hosting merely to practice; a local development environment may be sufficient.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.