Header, footer and template parts
The header and the footer are the same on every page, and a post card repeats in the feed, the search and the categories. Instead of copying markup from file to file, it is moved into separate template parts.
The header
<?php
// 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(); ?>
<header class="site-header">
<a href="<?php echo esc_url(home_url('/')); ?>"><?php bloginfo('name'); ?></a>
</header>
<main>The footer
<?php
// footer.php
?>
</main>
<footer class="site-footer">
<p>© <?php echo esc_html(date('Y')); ?> <?php bloginfo('name'); ?></p>
</footer>
<?php wp_footer(); ?>
</body>
</html>Including them
<?php
// page.php
get_header();
while (have_posts()) :
the_post();
the_content();
endwhile;
get_footer();get_header() includes header.php, get_footer() includes footer.php. For a special header call get_header('shop') — header-shop.php is included.
A template part
A post card goes into the template-parts folder:
<?php
// template-parts/card.php
?>
<article class="card">
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
<?php the_excerpt(); ?>
</article><?php
// index.php
get_header();
while (have_posts()) :
the_post();
get_template_part('template-parts/card');
endwhile;
get_footer();Arguments
The third parameter passes data into a template part — it is available in the $args array:
<?php
// index.php
get_template_part('template-parts/card', null, ['show_date' => true]);<?php
// template-parts/card.php
if (!empty($args['show_date'])) {
echo '<time>' . esc_html(get_the_date()) . '</time>';
}Menus
A theme declares places for menus, and an editor arranges the items in the dashboard:
// functions.php
add_action('after_setup_theme', function () {
register_nav_menus([
'primary' => 'Primary menu',
'footer' => 'Footer menu',
]);
});<?php
// header.php
wp_nav_menu([
'theme_location' => 'primary',
'container' => 'nav',
'menu_class' => 'menu',
'fallback_cb' => false,
]);Widget areas
A sidebar is a place where blocks are added in the dashboard: a search, a category list, recent posts.
// functions.php
add_action('widgets_init', function () {
register_sidebar([
'name' => 'Sidebar',
'id' => 'sidebar',
'before_widget' => '<section class="widget">',
'after_widget' => '</section>',
]);
});<?php
// sidebar.php
if (is_active_sidebar('sidebar')) {
dynamic_sidebar('sidebar');
}Common mistake
Template parts are included with get_template_part(), not include or require. Only that function looks for the file in the child theme first and then in the parent — without it a child theme cannot replace a single fragment. For the same reason the path is written without .php and without the full folder address.