How to Create a Classic WordPress Theme from Scratch: Complete Beginner Tutorial 2026
4 weeks ago

Want complete control over your WordPress website design in 2026? Learning how to create a classic WordPress theme from scratch gives you unlimited customization, better performance, and deeper understanding of WordPress — without depending on bloated page builders, block themes, or expensive premium themes.
This ultimate step-by-step beginner guide (updated for WordPress 6.7+ in 2026) teaches you exactly how to build a clean, fast, responsive classic WordPress theme — perfect for blogs, portfolios, business websites, personal brands, or client projects in Bandung, Jakarta, or anywhere else.
No advanced coding experience required — just basic HTML, CSS, and PHP knowledge. By the end of this 3000+ word tutorial, you’ll have a fully functional custom theme ready to activate, extend, or sell.

Why Build a Classic WordPress Theme in 2026? (Updated Reasons)
- Performance & Speed — Classic themes are lightweight → better Core Web Vitals scores (LCP < 2.5s, INP < 200ms, CLS < 0.1) and higher Google rankings.
- Full Customization — No restrictions from Full Site Editing (FSE) or block patterns.
- Learning Power — Master the WordPress template hierarchy, The Loop, hooks, template tags, and functions.php — skills still in high demand for freelance and agency work.
- No Bloat — Avoid loading unnecessary Gutenberg blocks or third-party builder scripts.
- Future-Proof — Classic themes remain fully supported in WordPress 6.7+ and are easier to maintain than complex block themes for many use cases.
- Monetization — Sell your theme on ThemeForest, create client-specific designs, or offer theme customization services (average freelance rates Rp 5–15 million per project in Indonesia 2026).
Prerequisites: What You Need to Build a WordPress Theme
Before coding, prepare this:
- Basic HTML & CSS (structure + responsive design)
- Basic PHP (functions, loops, conditionals, arrays)
- Local WordPress development environment (2026 recommendations):
- LocalWP (free, fastest setup, best for beginners)
- DevKinsta (free, Kinsta-powered, excellent staging/push features)
- Laragon or XAMPP (free, classic stack with PHP 8.3)
- Code editor: Visual Studio Code (free) + extensions:
- PHP Intelephense
- WordPress Snippets
- Bracket Pair Colorizer 2
- Latest WordPress (download from wordpress.org – aim for 6.7+)
Quick Setup:
- Install LocalWP → Create new site → Install WordPress.
- Enable debug mode in wp-config.php:
PHP
define( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true ); define( 'WP_DEBUG_DISPLAY', false );
Now you’re ready to code.
Step 1: Create Your Theme Folder & Mandatory Files
All themes live in /wp-content/themes/.
-
Create folder: my-classic-theme-2026 (lowercase, hyphens only)
-
Inside the folder, create these two required files:
- style.css → Theme metadata + styles
- index.php → Main fallback template
style.css – Theme Header (Must-Have Metadata 2026)
CSS
/* Theme Name: My Classic Theme 2026 Theme URI: https://yourdomain.com/my-classic-theme Author: Bersimu Author URI: https://yourdomain.com Description: Clean, fast, responsive classic WordPress theme built from scratch – beginner tutorial updated for 2026. Perfect for blogs, portfolios, and custom projects. Version: 1.0.0 Requires at least: 6.5 Tested up to: 6.7 Requires PHP: 8.1 License: GNU General Public License v2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html Text Domain: my-classic-theme-2026 Tags: blog, custom-logo, custom-menu, featured-images, threaded-comments, translation-ready, right-sidebar */
Security First Line (add to top of every PHP file):
PHP
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
Save → Go to Appearance → Themes → Your new theme should appear!
Pro Tip: Add a screenshot.png (1200×900 px) in the root folder — it shows as preview image in the Themes panel.
Step 2: Understand WordPress Template Hierarchy (2026 Quick Reference)
WordPress uses a template hierarchy to decide which file renders a page:
- Home/Blog → index.php (fallback)
- Single post → single.php → singular.php → index.php
- Static page → page.php → singular.php → index.php
- Header everywhere → header.php
- Footer everywhere → footer.php
- Custom functions → functions.php
We’ll create the most important ones first.
Step 3: Build the Header (header.php)
PHP<!DOCTYPE html> <html <?php language_attributes(); ?>> <head> <meta charset="<?php bloginfo( 'charset' ); ?>"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="profile" href="https://gmpg.org/xfn/11"> <?php wp_head(); ?> </head> <body <?php body_class(); ?>> <header class="site-header"> <div class="container"> <!-- Site Branding --> <div class="site-branding"> <?php if ( has_custom_logo() ) { the_custom_logo(); } else { ?> <h1 class="site-title"> <a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"> <?php bloginfo( 'name' ); ?> </a> </h1> <?php } $description = get_bloginfo( 'description', 'display' ); if ( $description || is_customize_preview() ) : ?> <p class="site-description"><?php echo $description; ?></p> <?php endif; ?> </div> <!-- Primary Navigation --> <nav class="main-navigation" role="navigation"> <?php wp_nav_menu( array( 'theme_location' => 'primary', 'menu_id' => 'primary-menu', 'container' => false, 'fallback_cb' => false, ) ); ?> </nav> </div> </header>
Enable features in functions.php:
PHP
function my_classic_theme_setup() {
// Custom logo support
add_theme_support( 'custom-logo', array(
'height' => 80,
'width' => 300,
'flex-height' => true,
'flex-width' => true,
));
// Dynamic title tag
add_theme_support( 'title-tag' );
// Navigation menus
register_nav_menus( array(
'primary' => esc_html__( 'Primary Menu', 'my-classic-theme-2026' ),
));
// Post thumbnails
add_theme_support( 'post-thumbnails' );
// HTML5 support
add_theme_support( 'html5', array(
'search-form',
'comment-form',
'comment-list',
'gallery',
'caption',
'style',
'script',
));
}
add_action( 'after_setup_theme', 'my_classic_theme_setup' );
Step 4: Enqueue Assets Correctly (functions.php)
PHPfunction my_classic_theme_enqueue_assets() { // Main stylesheet wp_enqueue_style( 'my-classic-theme-style', get_stylesheet_uri(), array(), '1.0.0' ); // Google Fonts (optional) wp_enqueue_style( 'google-fonts', 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap', array(), null ); // Custom JS (create /assets/js/main.js later) wp_enqueue_script( 'my-classic-theme-script', get_template_directory_uri() . '/assets/js/main.js', array('jquery'), '1.0.0', true ); // Comment reply script (for threaded comments) if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) { wp_enqueue_script( 'comment-reply' ); } } add_action( 'wp_enqueue_scripts', 'my_classic_theme_enqueue_assets' );
Step 5: Create a Simple Footer (footer.php)
PHP<footer class="site-footer"> <div class="container"> <p class="copyright"> © <?php echo date_i18n( 'Y' ); ?> <?php bloginfo( 'name' ); ?>. <?php esc_html_e( 'All rights reserved.', 'my-classic-theme-2026' ); ?> </p> <p class="credits"> Built with <a href="https://wordpress.org">WordPress</a> • Theme by Bersimu </p> </div> </footer> <?php wp_footer(); ?> </body> </html>
Step 6: Build the Homepage/Blog Loop (index.php)
PHP
<?php get_header(); ?>
<main class="site-main container">
<?php if ( have_posts() ) : ?>
<header class="page-header">
<?php if ( is_home() && ! is_front_page() ) : ?>
<h1 class="page-title"><?php single_post_title(); ?></h1>
<?php endif; ?>
</header>
<div class="posts-grid">
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class( 'post-card' ); ?>>
<?php if ( has_post_thumbnail() ) : ?>
<div class="post-thumbnail">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail( 'medium_large', array( 'loading' => 'lazy' ) ); ?>
</a>
</div>
<?php endif; ?>
<header class="entry-header">
<?php the_title( sprintf( '<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h2>' ); ?>
</header>
<div class="entry-meta">
<span class="posted-on"><?php echo get_the_date(); ?></span>
<span class="byline"> by <?php the_author_posts_link(); ?></span>
</div>
<div class="entry-summary">
<?php the_excerpt(); ?>
</div>
<a href="<?php the_permalink(); ?>" class="read-more">Read More →</a>
</article>
<?php endwhile; ?>
<?php the_posts_pagination( array(
'mid_size' => 2,
'prev_text' => __( '← Previous', 'my-classic-theme-2026' ),
'next_text' => __( 'Next →', 'my-classic-theme-2026' ),
) ); ?>
</div>
<?php else : ?>
<section class="no-results">
<h2>No posts found</h2>
<p>Sorry, nothing matched your criteria.</p>
</section>
<?php endif; ?>
</main>
<?php get_footer(); ?>
Step 7: Single Post Template (single.php)
PHP
<?php get_header(); ?>
<main class="site-main container">
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<?php if ( has_post_thumbnail() ) : ?>
<div class="post-featured-image">
<?php the_post_thumbnail( 'full', array( 'loading' => 'lazy' ) ); ?>
</div>
<?php endif; ?>
<?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
<div class="entry-meta">
Posted on <?php echo get_the_date(); ?> by <?php the_author_posts_link(); ?>
</div>
</header>
<div class="entry-content">
<?php the_content(); ?>
</div>
<footer class="entry-footer">
<?php
// Categories & tags
the_category( ', ' );
the_tags( '<span class="tags-links">Tags: ', ', ', '</span>' );
?>
</footer>
</article>
<?php
// Comments template
if ( comments_open() || get_comments_number() ) :
comments_template();
endif;
?>
<?php endwhile; ?>
</main>
<?php get_footer(); ?>
Step 8: Static Page Template (page.php)
PHP
<?php get_header(); ?>
<main class="site-main container">
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
</header>
<div class="entry-content">
<?php the_content(); ?>
</div>
</article>
<?php endwhile; ?>
</main>
<?php get_footer(); ?>
Step 9: Add Custom CSS & Responsive Design (style.css)
CSS/* ============================================== My Classic Theme 2026 – Core Styles ============================================== */ /* Reset & Base */ * { margin:0; padding:0; box-sizing:border-box; } body { font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; line-height: 1.7; color: #333; background: #fff; } /* Container */ .container { max-width: 1200px; margin: 0 auto; padding: 0 20px; } /* Header */ .site-header { background: #1a1a1a; color: #fff; padding: 1.5rem 0; position: sticky; top: 0; z-index: 1000; } .site-branding h1.site-title a { color: #fff; text-decoration: none; font-size: 1.8rem; } .main-navigation ul { list-style: none; display: flex; gap: 2rem; } .main-navigation a { color: #fff; text-decoration: none; } /* Posts Grid */ .posts-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 2.5rem; margin: 3rem 0; } .post-card { background: #fff; border-radius: 12px; overflow: hidden; box-shadow: 0 6px 20px rgba(0,0,0,0.08); transition: transform 0.3s ease; } .post-card:hover { transform: translateY(-8px); } .post-thumbnail img { width: 100%; height: 200px; object-fit: cover; } .entry-title a { color: #1a1a1a; text-decoration: none; } .read-more { display: inline-block; margin-top: 1rem; color: #0066cc; font-weight: 600; } /* Responsive Design */ @media (max-width: 768px) { .main-navigation ul { flex-direction: column; gap: 1rem; } .posts-grid { grid-template-columns: 1fr; } } /* Add more styles: colors, typography, footer, single post layout, etc. */
Step 10: Test, Debug, Package & Deploy
Testing Checklist 2026:
- Activate theme → Appearance → Themes
- Create 5–10 test posts/pages
- Check mobile view (Chrome DevTools)
- Validate speed (PageSpeed Insights – aim 90+ mobile)
- Check accessibility (WAVE tool)
- Test menus, logo, featured images, pagination
Debug Common Issues:
- Styles not loading → Check enqueue function
- White screen → Enable WP_DEBUG & check debug.log
- Missing menu → Register and assign menu in Appearance → Menus
Deployment:
- Zip entire folder → my-classic-theme-2026.zip
- Upload: Appearance → Themes → Add New → Upload Theme
- For live sites: Use staging (DevKinsta push, Kinsta staging, or manual SFTP)
Bonus: Extend Your Classic Theme (Next-Level Ideas)
- Add sidebar (sidebar.php + get_sidebar())
- Customizer support ($wp_customize)
- Comments template (comments.php)
- Breadcrumbs
- Pagination styling
- Child theme for safe future updates
Final Summary
You’ve just built a complete, modern classic WordPress theme from scratch in 2026 — fast, clean, customizable, and ready for real projects. This skill opens doors to freelance work, client projects, or even selling themes online.
Start now: Create your folder, add the header, and build one section at a time. Experiment, break things, fix them — that’s how mastery happens.
Classic WordPress Theme Development FAQ: Common Questions Answered for Beginners (2026)
Here are the most frequently asked questions by beginners who are learning how to create a classic WordPress theme from scratch in 2026. These answers reflect current best practices (WordPress 6.7+, PHP 8.1+, Core Web Vitals focus) and help you avoid common mistakes.
1. What is a classic WordPress theme, and how is it different from a block theme?
A classic WordPress theme uses traditional PHP template files (like index.php, header.php, single.php) and the old template hierarchy to build the site structure and layout. A block theme (introduced with Full Site Editing in WordPress 5.9+) uses theme.json, HTML templates with blocks, and the Site Editor for drag-and-drop editing without PHP templates.
Classic themes are still very popular in 2026 because:
- They offer more precise control over code and performance
- Easier for developers who prefer PHP
- Better compatibility with older plugins
- Faster to build simple, lightweight sites
2. Do I need to know coding to create a classic WordPress theme?
Yes — you need basic to intermediate knowledge of:
- HTML (structure)
- CSS (styling & responsive design)
- PHP (loops, conditionals, template tags like the_title(), get_header())
You do not need to be an expert. Most beginners learn by copying/pasting and modifying examples. No JavaScript or advanced backend skills are required for a basic theme.
3. What are the minimum files required for a WordPress theme to work?
Only two files are strictly required:
- style.css (with valid theme header metadata)
- index.php (main template fallback)
Everything else (header.php, footer.php, functions.php, etc.) is optional but highly recommended for real-world use.
4. Why doesn’t my new theme appear in Appearance → Themes?
Common reasons:
- Missing or incorrect theme header in style.css (especially Theme Name: line)
- Theme folder name contains spaces or uppercase letters (use lowercase + hyphens)
- PHP syntax error in any file → enable WP_DEBUG and check debug.log
- File permissions issue (rare on local setups)
Fix: Double-check header, save files, refresh Themes page.
5. How do I add a custom logo, menu, or featured images to my theme?
Add theme support in functions.php using add_theme_support():
PHPadd_theme_support( 'custom-logo', array( 'height' => 80, 'width' => 300, 'flex-height' => true, 'flex-width' => true, ) ); add_theme_support( 'post-thumbnails' ); register_nav_menus( array( 'primary' => __( 'Primary Menu', 'my-theme' ), ) );
Then use template tags like the_custom_logo(), the_post_thumbnail(), wp_nav_menu() in your templates.
6. Why should I use wp_enqueue_style() and wp_enqueue_script() instead of hardcoding <link> and <script> tags?
Hardcoding breaks:
- Child theme overrides
- Plugin compatibility (many enqueue their own assets)
- Version caching & dependency management
- Conditional loading
Always enqueue assets in functions.php with proper dependencies and version numbers.
7. How do I make my theme responsive/mobile-friendly?
Use:
- Viewport meta tag: <meta name="viewport" content="width=device-width, initial-scale=1">
- CSS media queries: @media (max-width: 768px) { ... }
- Flexible units: rem, %, vw/vh, clamp()
- Responsive images: srcset + sizes (built-in with the_post_thumbnail())
Test with Chrome DevTools device toolbar or Google Mobile-Friendly Test.
8. My styles are not loading — what’s wrong?
Common causes:
- Wrong enqueue handle or path (get_stylesheet_uri() is correct for style.css)
- Cache — clear browser cache or use hard refresh (Ctrl + F5)
- functions.php syntax error — check debug log
- Theme not activated
Quick fix: Add version number to enqueue: wp_enqueue_style( 'theme-style', get_stylesheet_uri(), array(), '1.0.1' );
9. Should I create a child theme even if I’m building from scratch?
If you’re modifying an existing theme → yes, use a child theme. If you’re building completely from scratch → no need for child theme (it’s your original theme).
Once your theme is live and you want to make safe updates later, create a child theme of your own theme.
10. How do I add sidebar support, pagination, comments, or customizer options?
- Sidebar: Create sidebar.php + get_sidebar() + register_sidebar() in functions.php
- Pagination: Use the_posts_pagination() or the_posts_navigation()
- Comments: Create comments.php + comments_template()
- Customizer: Use add_action( 'customize_register', 'your_callback' )
Start simple — add these one by one after your basic theme works.
11. Can I sell or submit my classic theme to marketplaces in 2026?
Yes — both are possible.
- ThemeForest / CodeCanyon: Premium classic themes still sell well (clean, fast, customizable)
- WordPress.org repository: Free themes only — must follow strict guidelines (GPL license, no external links, accessibility, security)
Most developers start by building for clients or personal use, then sell later.
12. What are the biggest mistakes beginners make when creating a theme?
- Not using wp_enqueue_* properly
- Hardcoding paths (use get_template_directory_uri())
- No security checks (esc_url(), esc_attr(), wp_kses_post())
- Ignoring mobile/responsiveness
- Not testing with real content (many posts, long titles, comments)
- Missing wp_head() and wp_footer() hooks
- No text domain or translation support
13. Where can I learn more after building my first classic theme?
Excellent 2026 resources:
- Official WordPress Theme Handbook: developer.wordpress.org/themes
- “_s” (Underscores) starter theme: underscores.me
- YouTube: “Ferdy Korpershoek”, “WPCrafter”, “Create a Theme from Scratch” playlists
- Books: “Professional WordPress: Design and Development” (updated editions)
- Communities: Reddit r/Wordpress, WordPress.org forums, Facebook “WordPress Indonesia”
14. Is it still worth learning classic themes when block themes and Full Site Editing exist?
Yes — absolutely. Many developers and clients still prefer classic themes because:
- Faster to build simple sites
- Better performance on budget hosting
- More plugin compatibility
- Easier to maintain custom code
- Not everyone wants/needs block editor for everything
Classic + block hybrid themes are also rising in 2026.

Leave a Reply