wordpress theme development tutorial step by step updated 2022

    By: Thad Mertz
    2 years ago

    Hi devs lets build a wordpress theme from scratch. Here we have the html template that we will convert to completely working wordpress theme. Theme will be reusable. So we are going to use few functions for example registering navbar menu. adding featured image to wordpress theme. Here some sample code from the files.

    functions.php

    <?php
    require('functionIncludes/Includes.php');
    require('functionIncludes/enablingFeatures.php');
    require('functionIncludes/navigationMenu.php');
    require('functionIncludes/pagination.php');
    require('functionIncludes/postTypes.php');
    

    Here we divided code into several files and then calling in functions.php to making theme more organised.

    Includes have code for including css and js

    <?php
    
    
    // Loading css and javascript.
    
    
    function loadingFiles() {
        // Include Javascript files.
        wp_enqueue_script('jquery_script_Js', get_theme_file_uri('assets/js/jquery-3.5.1.min.js'), null, null, true);
        wp_enqueue_script('bootstrap_Js', get_theme_file_uri('assets/js/bootstrap.bundle.min.js'), null, null, true);
        
        if (is_front_page())
        {
            wp_enqueue_style('animate_Css', get_theme_file_uri('assets/vendor/animate/animate.css'));
            wp_enqueue_style('bootstrap_Css', get_theme_file_uri('assets/css/bootstrap.css'));
            wp_enqueue_style('owlCarousel_Css', get_theme_file_uri('assets/vendor/owl-carousel/css/owl.carousel.css'));
        
    
    
            wp_enqueue_script('wow_Js', get_theme_file_uri('assets/vendor/wow/wow.min.js'), null, null, true);
            wp_enqueue_script('owl_Js', get_theme_file_uri('assets/vendor/owl-carousel/js/owl.carousel.min.js'), null, null, true);
            wp_enqueue_script('waypoint_Js', get_theme_file_uri('assets/vendor/waypoints/jquery.waypoints.min.js'), null, null, true);
            wp_enqueue_script('animate_number_Js', get_theme_file_uri('assets/vendor/animateNumber/jquery.animateNumber.min.js'), null, null, true);
        }
    
    
        wp_enqueue_script('google_maps', get_theme_file_uri('assets/js/google-maps.js'), null, null, true);
        wp_enqueue_script('theme_Js', get_theme_file_uri('assets/js/theme.js'), null, null, true);
    
    
    
        // Theme Styles.
        wp_enqueue_style('bootstrap_style_css', get_theme_file_uri('assets/css/bootstrap.css'));
        wp_enqueue_style('main_icons_style_css', get_theme_file_uri('assets/css/maicons.css'));
        wp_enqueue_style('custom_theme_style_css', get_theme_file_uri('assets/css/theme.css'));
    
    
        // This will load your default style.css
        wp_enqueue_style('main_style_css', get_stylesheet_uri());
    }
    
    
    add_action('wp_enqueue_scripts', 'loadingFiles');
    

    then we have a file for "enabling features".

    <?php
    
    
    //Navigation Menu
    
    
    register_nav_menus(array(
       'primary' => __('Primary Menu'),
       'secondary' => __('Footer Menu')
    ));
    
    
    
    // Add Featured image Support.
    
    
    
     function addFeaturedImageSupport(){
        add_theme_support('post-thumbnails');
        add_image_size('single-page-main-image', 600,250, true);
        add_image_size('blog-list-page', 220,120, false);
        add_image_size('image_for_slider', 300,280, false);
    }
    
    
    add_action('after_setup_theme','addFeaturedImageSupport');
    

    We also going to have code for customising menu for making style similar to theme

    <?php
    
    
    
    // Adding classes to navigation li. Also Selecting nav link for current page.
    
    
    function add_additional_class_on_li($classes, $item, $args) {
        
        if (in_array('current-menu-item', $classes) ){
            $classes[] = 'active ';
        }
    
    
        if(isset($args->add_li_class)) 
        {
            $classes[] = $args->add_li_class;
        }
        return $classes;
    }
    add_filter('nav_menu_css_class', 'add_additional_class_on_li', 1, 3);
    
    
    // Adding classes to navigation anchor tag.
    function add_link_atts($atts) {
        $atts['class'] = "nav-link";
        return $atts;
      }
    add_filter( 'nav_menu_link_attributes', 'add_link_atts');
    

    Now let's see how we have our pagination setup (Custom pagination) for making similar style as theme.

    <?php
    
    
    function custom_pagination() {
        global $wp_query;
        $big = 999999999; // need an unlikely integer
        $pages = paginate_links( array(
            'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
            'format' => '?paged=%#%',
            'current' => max( 1, get_query_var('paged') ),
            'total' => $wp_query->max_num_pages,
            'prev_next' => false,
            'type'  => 'array',
            'prev_next'   => true,
            'prev_text'    => __( 'Previous', 'text-domain' ),
            'next_text'    => __( 'Next', 'text-domain'),
        ) );
        $output = '';
    
    
        if ( is_array( $pages ) ) {
            $paged = ( get_query_var('paged') == 0 ) ? 1 : get_query_var( 'paged' );
    
    
            $output .=  '<ul class="pagination justify-content-center">';
            foreach ( $pages as $page ) {
                $output .= "<li class='page-item'>$page</li>";
            }
            $output .= '</ul>';
    
    
            // Create an instance of DOMDocument 
            $dom = new \DOMDocument();
    
    
            // Populate $dom with $output, making sure to handle UTF-8, otherwise
            // problems will occur with UTF-8 characters.
            $dom->loadHTML( mb_convert_encoding( $output, 'HTML-ENTITIES', 'UTF-8' ) );
    
    
            // Create an instance of DOMXpath and all elements with the class 'page-numbers' 
            $xpath = new \DOMXpath( $dom );
    
    
            // http://stackoverflow.com/a/26126336/3059883
            $page_numbers = $xpath->query( "//*[contains(concat(' ', normalize-space(@class), ' '), ' page-numbers ')]" );
    
    
            // Iterate over the $page_numbers node...
            foreach ( $page_numbers as $page_numbers_item ) {
    
    
                // Add class="mynewclass" to the <li> when its child contains the current item.
                $page_numbers_item_classes = explode( ' ', $page_numbers_item->attributes->item(0)->value );
                
                if ( in_array( 'current', $page_numbers_item_classes ) ) {          
                    $list_item_attr_class = $dom->createAttribute( 'class' );
                    $list_item_attr_class->value = 'page-item active';
                    $page_numbers_item->parentNode->appendChild( $list_item_attr_class );
                }
    
    
                // Replace the class 'current' with 'active'
               
                $page_numbers_item->attributes->item(0)->value = str_replace( 
                                'current',
                                'active',
                                $page_numbers_item->attributes->item(0)->value );
    
    
                // Replace the class 'page-numbers' with 'page-link'
                
                $page_numbers_item->attributes->item(0)->value = str_replace( 
                                'page-numbers',
                                'page-link',
                                $page_numbers_item->attributes->item(0)->value );
            }
    
    
            // Save the updated HTML and output it.
            $output = $dom->saveHTML();
        }
    
    
        return $output;
    }
    

    There are few references to other websites for your understanding.

    We also have our website Slider dynamic powered from custom post type.

    <?php
    
    
    function slider_custom_post_type() {
    
    
        $args = array(
            'labels'              => array(
                'name'          => 'Slider', // Plural name
                'singular_name' => 'Slider'   // Singular name
            ),
            'description'         => 'Post type post slider', // Description
            'supports'            => array(
                'title',        // Post title
                'editor',       // Post content
                //'excerpt',      // Allows short description
                //'author',       // Allows showing and choosing author
                'thumbnail',    // Allows feature images
                //'comments',     // Enables comments
                //'custom-fields' // Supports by custom fields
            ),
            //'taxonomies'          => array( 'category', 'post_tag' ), // Allowed taxonomies, categories
            'public'              => true,  // Makes the post type public
            'menu_position'       => 5,     // The position number in the left menu
            'menu_icon'           => true,  // The URL for the icon used for this post type
        );
    
    
        register_post_type('slider', $args); //Create a post type with the slug is ‘product’ and arguments in $args.
    }
    
    
    add_action('init', 'slider_custom_post_type');
    

    Ok without making this post too long. If you want download the theme code from download button.

    Watch Video guide for detailed explanations. Cheers.