A minimal WordPress Theme

Home / A minimal WordPress Theme

A minimal WordPress Theme

July 20, 2019 | Coding | No Comments

WordPress Logo

The company I work for is growing, and part of that growth has me learning WordPress. Id honestly rather not touch it, I do not enjoy working in PHP. But there it is anyway.

I was quickly surprised at how simple, and how little you need to make a theme. You only need two files: index.php and style.css. So I decided to make one that was that simple to demonstrate here.

Shortly into it I decided to add a menu and a sidebar, so two more files: functions.php and sidebar.php. How functional is a theme really, if you don’t have a customizable menu or widget area?

All the code is below, comments inline and github repo is available.


Theme Name: Minimal WordPress
Theme URI: https://wordpress.org/themes/twentyseventeen/
Author: the WordPress team
Author URI: https://wordpress.org/
Description: Minimal WordPress brings your site to life with immersive featured images and subtle animations. With a focus on business sites, it features multiple sections on the front page as well as widgets, navigation and social menus, a logo, and more. Personalize its asymmetrical grid with a custom color scheme and showcase your multimedia content with post formats. Our default theme for 2017 works great in many languages, for any abilities, and on any device.
Version: 1.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: minimaltheme
Tags: one-column, two-columns, right-sidebar, flexible-header, accessibility-ready, custom-colors, custom-header, custom-menu, custom-logo, editor-style, featured-images, footer-widgets, post-formats, rtl-language-support, sticky-post, theme-options, threaded-comments, translation-ready
This theme, like WordPress, is licensed under the GPL.
Use it to make something cool, have fun, and share what you've learned with others.


Everything is going to be displayed on this one page,
we don't want to put potentially thousands of posts on 
our one page... so we redefine the query to paginate.
But only if we are not on a single item page.

if (!is_singular()) {
    $paged = (get_query_var('paged')) ? get_query_var('paged') : '1';
    $args = array(
        'nopaging'               => false,
        'paged'                  => $paged,
        'posts_per_page'         => '2',
        'post_type'              => 'post',
    $query = new WP_Query($args);
} else {
    $query = $wp_query;


<!DOCTYPE html>
<html lang="en">

    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>My Theme</title>
    <!-- wp_head will inject all of wordpress's specific header info
    and anything else we define, like custome css.  We could just write that
    in here ourselves, but we could end up with mulitple headers and this
    helps keep us DRY
    <?php wp_head() ?>

        <div class="nav-wrapper  container">
            <a href="/" class="brand-logo"><?php echo get_bloginfo('name'); ?></a>
                'theme_location' => 'main-menu',
                'container_class' => 'right'
    <main class="container">
        <div class="row">
            <div class="col s12 m8">
                <?php if ($query->have_posts()) : while ($query->have_posts()) : $query->the_post(); ?>
                        <article class="card-panel">
                                <a href="<?php the_permalink(); ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>"><?php the_title(); ?></a>

                            <small><?php the_time('F jS, Y'); ?> by <?php the_author(); ?></small>

                            <div class="entry">
                                <!-- we only want to show the full post if we aren't on a list -->
                                <?php if (is_singular()) {
                                    // If comments are open or we have at least one comment, 
                                    // load up the comment template.
                                    if (comments_open() || get_comments_number()) {
                                } else {
                                } ?>
                            <p class="postmetadata"><?php _e('Posted in'); ?> <?php the_category(', '); ?></p>


                    <?php endwhile;
                    // show pagination links
                    echo paginate_links(array(
                        'total' => $query->max_num_pages,
                        'mid_size' => 2

                else : ?>
                    <p><?php esc_html_e('Sorry, no posts matched your criteria.'); ?></p>
                <?php endif; ?>
            <div class="col s12 m4">
                <?php get_sidebar() ?>

        <!-- like wp_head wp_footer injects necessary script stuff
            such as the code that gives us the WordPress Admin bar
        <?php wp_footer(); ?>



You can register your stylesheets and scripts in the same function
but I prefer to keep them seperate, it just feels cleaner to me
function minimaltheme_enqueue_styles()
    wp_enqueue_style('materialize-css', "https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css");
add_action('wp_enqueue_scripts', 'minimaltheme_enqueue_styles');

function minimaltheme_enqueue_scripts()
    wp_enqueue_script('materialize-js', "https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js");
add_action('wp_enqueue_scripts', 'minimaltheme_enqueue_scripts');
wp_enqueue_style('style', get_stylesheet_uri());

  We need one menu for our nav bar, but you can register
  as many as you like and put them anywhere
function register_menus()
    register_nav_menu('main-menu', __('Main Menu'));
add_action('init', 'register_menus');

// register a sidebar to user throughout the site
add_action('widgets_init', 'minimaltheme_register_sidebars');
function minimaltheme_register_sidebars()
        'name' => __('Main Sidebar', 'minimaltheme'),
        'id' => 'sidebar',
        'description' => __('Widgets in this area will be shown on all posts and pages.', 'minimaltheme'),
        'before_widget' => '<div class="card"><div class="card-content">',
        'after_widget'  => '</div></div>',
        'before_title'  => '<div class="card-title">',
        'after_title'   => '</div>',


if (!is_active_sidebar('sidebar')) {


Available at https://github.com/wsimmerson/minimaltheme


About Author

about author


Jack of all trades. I.T. edition. Programmer, Systems Administrator, DevOps and whatever else comes up.