WordPress is a free CMS and almost 30% of websites are designed by WordPress (WP). WordPress itself is CMS to manage content, but WordPress themes are responsible for the look of the website. In this quick reference, we will develop a sample WordPress theme to learn how to create a custom WordPress theme.
WordPress theme development needs basic knowledge of HTML, CSS, JavaScript, and PHP.
Structure
Every WordPress theme lives in “wp-content/themes“. If you visit this folder of your website, you can see there is at least one theme.
WordPress themes are hosted in this folder. Every theme has its own folders and files. Some files are WP pre-reserved files like “header.php, footer.php, etc”.
Every theme to function needs two files. The files are “index.php” and “style.css“. In style.css we will introduce our theme to WordPress and in index.php we will display our content with PHP codes.
Start WordPress theme development step by step
Go to the “wp-content/themes” of your WordPress website.
Create a new folder and name it “hs-sample“.
Go to the folder and create “style.css” and “index.php” inside the “hs-sample” folder.
Open the style.css file and add the following code.
/*
Theme Name: Honar Systems Sample Theme
Theme URI: https://www.honarsystems.com/hs-sample
Author: Honar Systems
Author URI: https://www.honarsystems.com/
Description: Honar Systems Sample is a free theme.
Version: 1.0.0
Tested up to: 5.8
Requires PHP: 5.6
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Tags: two-columns, three-columns, left-sidebar, right-sidebar, custom-background, custom-header, custom-menu, editor-style, post-formats, rtl-language-support, sticky-post, theme-options, translation-ready
Text Domain: hs-sample
This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you've learned.
== Copyright ==
Honar Systems Sample WordPress Theme, 2022 WordPress.org
Honar Systems Sample is distributed under the terms of the GNU GPL.
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.
*/
- Theme Name (Required): Name of the theme.
- Theme URI: URI of the theme on your website
- Author: Author name of the theme (Person name or Company name)
- Author URI: The author’s website
- Description: Description of the theme
- Version: Version of the theme
- Tested up to: The minimum PHP version that we tested the theme
- Requires PHP: The minimum PHP Version that the theme needs to run correctly
- License: License of the theme. Every WordPress themes have a GPL license. If you are creating a premium theme, you have to add a license in the theme root folder.
- License URI: URl of the license
- Text Domain: This is a text domain to tell WordPress to translate static texts in the theme.
- Tags: The tags tell WordPress that we are using these features. If you upload your theme to WordPress.org, the theme will show when the user types the tags.
Go to “Appearance -> Themes” in your website Dashboard. Now you can see there is a “Honar Systems Sample Theme” theme in the section. If you click the theme you will see the details of the theme.
You have just created a WordPress theme. Now let’s go to develop the WordPress theme. Activate the theme.
index.php
Open the index.php file and add the following code.
<?php
get_header();
if (have_posts()) {
if (is_single()) {
get_template_part('template-parts/content', 'single');
} else {
get_template_part('template-parts/content');
}
} else {
get_template_part('template-parts/content', 'none');
}
get_footer();
In this code, we used some functions that are WordPress functions to develop themes.
- get_header: get header.php file content.
- have_posts: check if WordPress has posts to display.
- is_single: check if the client is seeing the post or not.
- get_template_part: include path codes.
- get_footer: get footer content.
If you go to the site you will see the below layout.
Now, let’s develop each file.
functions.php file
In WordPress, functions.php or the theme functions file is a template included in WordPress themes. It acts like a plugin for your WordPress site that’s automatically activated with your current theme. The functions.php file uses PHP code to add features or change default features on a WordPress site.
It can be used to hook into the core functions of WordPress to make your theme more modular, extensible, and functional.
Your WordPress functions.php file is key to adding code customizations to your WordPress site. It is especially useful if you are using a child theme and do not have access to the actual site files.
Create the functions.php file in the root folder of your theme and add the code below.
include('inc/hs_menu_walker.php');
if (!function_exists('hs_sample_enqueue_theme')) {
function hs_sample_enqueue_theme()
{
wp_enqueue_style('hss-style', get_stylesheet_uri());
}
add_action('wp_enqueue_scripts', 'hs_sample_enqueue_theme');
}
if (!function_exists('hs_sample_setup_header')) :
function hs_sample_setup_header()
{
register_nav_menus(
array(
'main-menu' => esc_html__('Main Menu', 'hs-sample'),
'mobile-menu' => esc_html__('Mobile Menu', 'hs-sample'),
)
);
$args = array(
'default-text-color' => '000',
'width' => 1000,
'height' => 250,
'flex-width' => true,
'flex-height' => true,
);
add_theme_support('custom-header', $args);
add_theme_support('custom-logo', array(
'height' => 100,
'width' => 400,
'flex-height' => true,
'flex-width' => true,
'unlink-homepage-logo' => true,
));
}
add_action('after_setup_theme', 'hs_sample_setup_header');
endif;
if (!function_exists('hs_sample_enqueue_header')) {
function hs_sample_enqueue_header()
{
wp_enqueue_style('hss-header', esc_url(get_template_directory_uri() . '/assets/css/header.css'), array(), '1.0.0');
wp_enqueue_script('hss-header-script', esc_url(get_template_directory_uri() . '/assets/js/header.js'), ['jquery'], '1.0.0', true);
}
add_action('wp_enqueue_scripts', 'hs_sample_enqueue_header');
}
This code is simple for the file and its functions. There are some codes in this example that we explain a little here and we will explain totally in their own section.
include('inc/hs_menu_walker.php');
This code includes the class of the menu walker.
hs_sample_enqueue_theme()
This function enqueues the CSS styles and JavaScript code files into WordPress. For more information about the enqueuing, read our tutorial: How to Include Properly CSS and JS Files in WordPress.
This function enqueues the style.css file to WordPress.
hs_sample_setup_header()
In this function, we added two menu locations, a custom header background, and a custom logo for your website.
hs_sample_enqueue_header()
This function enqueues the header’s style and JavaScript files.
header.php
“header.php” is a reserved file name in WordPress to develop and contain header content of the website like head tag, meta tags and etc. header file contains every content that will include on every page of the website like the main menu, website logo, etc.
Read More: How To Create Custom WordPress Header File
Create a “header.php” file in the root folder of the theme. Open the file and add the below code.
<!doctype html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="profile" href="http://gmpg.org/xfn/11">
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<div id='page' class='site'>
<a class='skip-link screen-reader-text' href='#content'>
<?php esc_html_e('Skip to content', 'sample'); ?>
</a>
<button class='to-top' onclick='window.scrollTo({top: 0, behavior: "smooth"});'>
<span class='dashicons dashicons-arrow-up-alt'></span>
</button>
<header class='site-header'>
<div class="logo">
<?php
if (has_custom_logo()) :
the_custom_logo();
else :
$blog_info = get_bloginfo('name');
$description = get_bloginfo('description', 'display');
$show_title = (false === display_header_text());
$header_class = $show_title ? 'site-title' : 'screen-reader-text';
?>
<?php if ($blog_info) : ?>
<?php if (is_front_page() && !is_paged()) : ?>
<h1 class="<?php echo esc_attr($header_class); ?>">
<?php echo esc_html($blog_info); ?>
</h1>
<?php elseif (is_front_page() && !is_home()) : ?>
<h1 class="<?php echo esc_attr($header_class); ?>">
<a href="<?php echo esc_url(home_url('/')); ?>">
<?php echo esc_html($blog_info); ?>
</a>
</h1>
<?php else : ?>
<h1 class="<?php echo esc_attr($header_class); ?>">
<a href="<?php echo esc_url(home_url('/')); ?>">
<?php echo esc_html($blog_info); ?>
</a>
</h1>
<?php endif; ?>
<?php endif; ?>
<?php if ($description && $show_title) : ?>
<p class='site-description'>
<?php echo esc_html($description); ?>
</p>
<?php endif; ?>
<?php endif; ?>
</div>
<div class="main-menu">
<?php if (has_nav_menu('main-menu')) : ?>
<a class='mobile-btn' tabindex='0'>
<span class='dashicons dashicons-menu-alt3'></span>
</a>
<div class='main-nav'>
<div class='close' tabindex='0'><span class='dashicons dashicons-no-alt'></span></div>
<?php wp_nav_menu(array(
'menu' => 'main-menu',
'theme_location' => 'main-menu',
'menu_class' => 'menu',
'container' => 'ul'
));
?>
</div>
<?php endif; ?>
</div>
<div class="search-box">
<?php get_search_form(); ?>
</div>
</header>
<main>
This code contains the head tag and website header. Website header contains website logo or name, Main menu, and search box.
<!doctype html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo('charset'); ?>" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="profile" href="http://gmpg.org/xfn/11">
<link rel="pingback" href="<?php bloginfo('pingback_url'); ?>">
<?php wp_head(); ?>
</head>
This code can be copied and pasted, because in almost every theme this code is the same.
You must add the wp_head()
function after all codes inside the head tag.
After WordPress 5.2 every theme must have wp_body_open()
function. This function is one of the most exciting features in WordPress is a simple function that fires an action. But this minor function has a huge impact on theme and plugin developers that inject code into WordPress themes.
Skip Link
Every standard theme should have the skip link for more accessibility to the content of the page.
<a class='skip-link screen-reader-text' href='#content'>
<?php esc_html_e('Skip to content', 'sample'); ?>
</a>
Here we use the esc_html_e()
function to make the text translatable to other languages. The “sample” word is the exactly same as the text domain in the style.css file we defined.
Back to Top button
This button is a tiny button in the corner of the page that if the user clicks it, will go to the top of the page without scrolling.
<button class='to-top' onclick='window.scrollTo({top: 0, behavior: "smooth"});'>
<span class='dashicons dashicons-arrow-up-alt'></span>
</button>
The onclick()
function contains JavaScript code to scroll with a smooth move.
In this code, we use “Dashicons” of WordPress. If you logged in user you can see the icons in the front end, but other users can’t see them. You have to enqueue it in the functions.php file.
Header content
The header section contains the logo of the website if it has been set, if not, display the website title and description.
In this section, we used the_custom_logo()
function and the menu. The logo and menu will be defined in the “functions.php” file.
We are going to develop a responsive WordPress sample theme, then we have to make everything responsive, especially the menus. Then we added the below elements to make it happen.
<a class='mobile-btn' tabindex='0'>
<span class='dashicons dashicons-menu-alt3'></span>
</a>
and
<div class='close' tabindex='0'><span class='dashicons dashicons-no-alt'></span></div>
Both will be displayed in mobile mode. The first one will open the menu and the second one will close it.
searchform.php
As we told you, in WordPress theme development you have to avoid naming your files with pre-reserved names. The “searchform.php“ also is one of them.
In the header section, we used the get_search_form() function to display the search box. This function displays WordPress’s inner search box by default but if you wanna create a custom search box in WordPress, you have to define it in the “searchform.php” file.
This file contains search box codes to modify the WordPress default search box.
Go to the root folder of your theme and create a “searchform.php” file. Open the file and add the following codes.
<?php
if (!defined('ABSPATH')) {
exit;
}
?>
<div class="search-box-form">
<form role="search" method="get" class="search-form" action="<?php echo esc_url(home_url("/")); ?>">
<input type="search" placeholder="<?php esc_attr_e('Search', 'sample') ?>" class="search-field" value="<?php echo esc_attr(get_search_query()); ?>" name="s" />
<button type="submit" tabindex="0" class="search-submit"><span class="dashicons dashicons-search"></span></button>
</form>
</div>
With the below code, you can ensure that the user can’t access directly to this file.
if (!defined('ABSPATH')) {
exit;
}
The home_url() returns the home page URL.
esc_attr_e()
andesc_attr()
: Attribute sanitization. With esc_attr_e() you can add translatable text and you don’t need an echo.esc_url()
: URL sanitization.
Read more about data validation and sanitization here.
Style of the header
In WordPress theme development like other web pages development, HTML creates the structure and the CSS creates the look. We just created header HTML, now let’s design the look.
This is not WordPress theme development, this is WordPress theme designing.
Before going to add some CSS to our code, we have to enqueue our style to WordPress in the functions.php file.
After enqueueing the style, open the style.css file and add the following codes.
functions.php
This filename is pre-reserved too. We can say, this file is the heart of the functionality of the theme. We will define WordPress theme functionality in this file such as custom logo, link style, custom google font and etc.
Custom Logo
if (!function_exists('sample_setup_logo')) {
function sample_setup_logo()
{
add_theme_support(
'custom-logo',
array(
'height' => 300,
'width' => 250,
'flex-width' => true,
'flex-height' => true,
'unlink-homepage-logo' => true,
)
);
}
add_action('after_setup_theme', 'sample_setup_logo');
}
Website title
if (!function_exists('sample_setup_title')) {
function sample_setup_title()
{
add_theme_support('title-tag');
}
add_action('after_setup_theme', 'sample_setup_title');
}
Menu
if (!function_exists('sample_setup_menu')) {
function sample_setup_menu()
{
register_nav_menus(
array(
'main-menu' => esc_html__('Main Menu', 'sample'),
'bottom-social-menu' => esc_html__('Bottom Social Menu', 'sample'),
)
);
}
add_action('after_setup_theme', 'sample_setup_menu');
}
Dashicons
if (!function_exists('sample_enqueue_dashicons')) {
function sample_enqueue_dashicons()
{
wp_enqueue_style('dashicons');
}
add_action('wp_enqueue_scripts', 'sample_enqueue_dashicons');
}
Enqueue Style
if (!function_exists('sample_enqueue_style')) {
function sample_enqueue_style()
{
wp_enqueue_style('sample-style', get_stylesheet_uri());
}
add_action('wp_enqueue_scripts', 'sample_enqueue_style');
}
Enqueue Script
if (!function_exists('sample_enqueue_script')) {
function sample_enqueue_script()
{
wp_enqueue_script('sample-script', get_template_directory_uri() . '/assets/js/custom.js', array('jquery'), '1.0.0', true);
}
add_action('wp_enqueue_scripts', 'sample_enqueue_script');
}
WordPress Theme Development
- Remove Extra Attributes From WordPress Theme Code
- Data Sanitization and Validation in WordPress
- Conditional Tags in WordPress
- How to Include Properly CSS and JS Files in WordPress
- WordPress theme update from custom host
- Delete role=”navigation” from the WordPress theme
- Move WordPress Comment Field To Bottom of The Form
- How to Customize the Excerpt Length in WordPress
- Add Google Font To WordPress Theme
- How to Add a Custom Widget Area to WordPress Themes
- How to Add Skip Link to WordPress Theme
- How to Create Custom Search Form in WordPress
- Get Attachment URL By ID in WordPress
- Add And Enqueue Google Fonts To Your Theme In WordPress
- How to Detect Internet Explorer Browser In WordPress
- Custom Comment List In WordPress
- Use One Click Demo Import Plugin In Your Theme
- Masonry Posts In WordPress
- Post Thumbnail Custom Size In WordPress
- Post Avatar Custom Size In WordPress
- How To Display Related Posts In WordPress With Example
- How to Redirect to Admin Page After Theme Activation In WordPress
- Create Bootstrap WordPress theme with v4 & 5
- Add custom background color to WordPress theme
- Add custom logo to WordPress them
- Detect client browser support JavaScript in WordPress theme
- Edit WordPress password form in theme
- How to Add Custom Meta Boxes in WordPress Posts
WordPress Development
- How To Create A Custom WordPress Plugin Step by Step With Example
- How to Create Custom WordPress Widget Step by Step With Example
- How To Create WordPress Custom Admin Page Without Plugin: A Quick and Easy Guide
- How to Create Shortcode in WordPress with Example
- Drag and Drop List in WordPress
- Ajax in WordPress with Example: Full Guide
- Customizer Select List Control in WordPress : Dropdown
- Check If Plugin Is Active In WordPress
- How to Enable Debugging in WordPress
- How to Remove Product Tabs in WooCommerce