Creating a WordPress theme from scratch lets you build a unique website look and feel. It gives full control over design and features without relying on pre-made themes.
Theme from scratch setup in Wordpress
/* Theme Name: My Custom Theme Author: Your Name Description: A simple theme built from scratch. Version: 1.0 */ // index.php <?php get_header(); ?> <main> <h1>Welcome to My Custom Theme</h1> <?php if (have_posts()) : while (have_posts()) : the_post(); ?> <article> <h2><?php the_title(); ?></h2> <div><?php the_content(); ?></div> </article> <?php endwhile; endif; ?> </main> <?php get_footer(); ?>
The comment block at the top of style.css defines your theme details.
index.php is the main template file that loads content.
/* Theme Name: Simple Theme */ /* style.css */ body { font-family: Arial, sans-serif; background-color: #f0f0f0; }
<?php
// functions.php
function simple_theme_setup() {
add_theme_support('title-tag');
}
add_action('after_setup_theme', 'simple_theme_setup');
?><?php // header.php ?><!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <?php wp_head(); ?> </head> <body> <header><h1>My Site Header</h1></header>
This is a complete minimal WordPress theme with style.css, index.php, header.php, and footer.php files. It shows posts and basic navigation.
/* Theme Name: Scratch Theme Author: Your Name Description: A theme built from scratch. Version: 1.0 */ /* style.css */ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #ffffff; color: #333333; margin: 0; padding: 0; } /* index.php */ <?php get_header(); ?> <main> <h1>Welcome to Scratch Theme</h1> <?php if (have_posts()) : while (have_posts()) : the_post(); ?> <article> <h2><?php the_title(); ?></h2> <div><?php the_content(); ?></div> </article> <?php endwhile; else: ?> <p>No posts found.</p> <?php endif; ?> </main> <?php get_footer(); ?> /* header.php */ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title><?php wp_title('|', true, 'right'); ?></title> <?php wp_head(); ?> </head> <body> <header> <nav> <ul> <li><a href="<?php echo home_url(); ?>">Home</a></li> </ul> </nav> </header> /* footer.php */ <footer> <p>© <?php echo date('Y'); ?> Scratch Theme</p> </footer> <?php wp_footer(); ?> </body> </html>
Always include wp_head() in header.php and wp_footer() in footer.php for plugins and scripts to work.
Use semantic HTML tags like <main>, <header>, and <footer> for better accessibility.
Test your theme by activating it in WordPress and checking different pages.
Building a theme from scratch gives full control over your site's look.
Start with style.css and index.php files, then add header.php and footer.php.
Use WordPress functions like get_header() and have_posts() to load content dynamically.
Practice
Solution
Step 1: Understand WordPress theme basics
A WordPress theme must have a style.css file to be recognized by WordPress.Step 2: Identify the minimum files
While index.php is also needed for templates, style.css is the absolute minimum to register the theme.Final Answer:
style.css -> Option AQuick Check:
Minimum theme file = style.css [OK]
- Thinking functions.php is mandatory for a basic theme
- Confusing header.php as required initially
- Assuming footer.php is needed to start
Solution
Step 1: Recall WordPress template functions
WordPress provides get_header() to load the header.php template properly.Step 2: Compare with PHP includes
Using include or require bypasses WordPress hooks and is not recommended.Final Answer:
get_header(); -> Option DQuick Check:
Use get_header() to load header template [OK]
- Using PHP include instead of get_header()
- Trying to call a non-existent load_header() function
- Using require which skips WordPress hooks
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h2><?php the_title(); ?></h2> <?php endwhile; else : ?> <p>No posts found.</p> <?php endif; ?>
What will be displayed if there are no posts?
Solution
Step 1: Understand the have_posts() check
The code checks if posts exist with have_posts(). If none, it runs the else block.Step 2: Identify the else block output
The else block outputs <p>No posts found.</p> when no posts exist.Final Answer:
No posts found. -> Option CQuick Check:
No posts triggers else output [OK]
- Assuming no output if no posts
- Expecting an error message instead
- Thinking titles show even if no posts
Solution
Step 1: Check theme registration requirements
WordPress requires style.css with a proper header comment to recognize the theme.Step 2: Understand blank page cause
If style.css is missing or header comment is absent, WordPress won't load the theme, showing a blank page.Final Answer:
Missing style.css file with theme header comment -> Option AQuick Check:
Missing style.css causes blank theme page [OK]
- Thinking get_footer() usage causes blank page
- Assuming duplicate get_header() breaks theme
- Believing functions.php is mandatory for theme to load
Solution
Step 1: Use conditional tags correctly
is_front_page() checks if the current page is the homepage to show the custom message.Step 2: Show posts only on other pages
Else block runs the loop to list post titles on non-homepage pages.Step 3: Verify code structure
<?php if ( is_front_page() ) : ?> <p>Welcome to my custom homepage!</p> <?php else : if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h2><?php the_title(); ?></h2> <?php endwhile; endif; endif; ?> nests the else with have_posts() loop correctly, showing message only on homepage.Final Answer:
The nested if-else code snippet -> Option BQuick Check:
Conditional homepage message + posts elsewhere = <?php if ( is_front_page() ) : ?> <p>Welcome to my custom homepage!</p> <?php else : if ( have_posts() ) : while ( have_posts() ) : the_post(); ?> <h2><?php the_title(); ?></h2> <?php endwhile; endif; endif; ?> [OK]
- Putting posts loop inside homepage condition
- Showing message only when no posts exist
- Not separating homepage and other pages logic
Ready to prove it?
Pass the test and this pattern moves unknown
