How to Develop a WordPress Theme Using Bootstrap (Part 2)

This is part 2 of a series of tutorials aimed at describing how to create a WordPress theme from scratch using the Bootstrap CSS framework. This tutorial series is ideal for PHP developers looking to move into WordPress theme development or beginner WordPress theme developers wanting to expand their knowledge and creating a responsive Bootstrap WordPress theme.

In part 1 of this tutorial, we discussed the basics of setting up the theme files, enqueue stylesheets and scripts, and display the blog feed using The Loop. Just to recap, we are using one of the starter example templates from the Bootstrap website for this tutorial: the blog template which is a simple two-column blog layout with custom navigation, header, and type.

In the next installment of this tutorial, we look into developing a carousel for the theme by utilizing the Bootstrap carousel component.

In this part, we discuss creating the header area, navigation, sidebar, and footer areas. If you’d like the download the source right away, here it is: Download Source

Developing a WordPress Theme from Scratch Using the Bootstrap CSS Framework

In the previous installment of this tutorial, we had set up the header.php file, but the navigation and site name and description are still static. Lets edit header.php and take care of these elements.


The starter template has one navigation that sits at the top of the page. In order to incorporate menu support into our theme, we need to tell WordPress that our theme supports one menu by writing a few lines of code to register it. Menu registration requires a location name (slug or identifier) and a descriptive short name. Edit function.php and add the following lines of code:

function bootstrapstarter_register_menu() {
    register_nav_menu('header-menu', __( 'Header Menu' ));
add_action( 'init', 'bootstrapstarter_register_menu' );

This menu would appear in the “Theme Locations” box as “Header Menu”. The admin can create a new menu, add items (pages, custom links, categories, etc.) to it and then assign the menu to the “Header Menu” location.

Now in order to display the menu, we need to refer to the menu slug or identifier at the point in the presentation file (header.php file in our case) where the menu list is going to be displayed. The function to use here is wp_nav_menu(), which you will need once for each menu location.

The starter template has this block of code that shows the navigation bar:

<nav class="blog-nav">
    <a class="blog-nav-item active" href="#">Home</a>
    <a class="blog-nav-item" href="#">New features</a>
    <a class="blog-nav-item" href="#">Press</a>
    <a class="blog-nav-item" href="#">New hires</a>
    <a class="blog-nav-item" href="#">About</a>

Note: We won’t be using (generating) this HTML code as it is – wp_nav_menu() uses lists (ul, li) in its output. So lets remove this block of code and replace it with the following line:

<?php wp_nav_menu( array( 
'theme_location' => 'header-menu', 
'menu_class' => 'blog-nav list-inline' 
) ); ?>

This tells WordPress to display the menu assigned to the “header-menu” location and use the CSS classes “blog-nav” and “list-inline” for the ul element. For the purpose of this template, we do need some extra CSS for the top navigation since we’ve changed the format from simple links to list elements. I’ve added the required CSS in the stylesheet; you can download it with the final code.

Now lets move on to the next static block of code in header.php, which is the blog header or the blog name and description text.

<div class="blog-header">
    <h1 class="blog-title">The Bootstrap Blog</h1>
    <p class="lead blog-description">The official example template of creating a blog with Bootstrap.</p>

Lets use the blog name (“Site Title” set in Settings > General) and the blog tagline (“Tagline” set in Settings > General) to populate these lines. Replace the above lines with the following – we’re using the bloginfo() and get_bloginfo() functions:

<div class="blog-header">
    <h1 class="blog-title"><?php bloginfo( 'name' ); ?></h1>
    <?php $description = get_bloginfo( 'description', 'display' ); ?>
    <?php if($description) { ?><p class="lead blog-description"><?php echo $description ?></p><?php } ?>

That’s it for the header.php file – we will now have a dynamic menu and the top of the blog will show the name of the blog along with the tagline.

Footer (Copyright Text)

Lets open footer.php now. This is the static block of HTML that needs to be replaced:

<p>Blog template built for <a href="">Bootstrap</a> by <a href="">@mdo</a>.</p>
<p><a href="#">Back to top</a></p>

There are many ways to hook this area into WordPress, here are a a couple of options:

  • Use a widget here. It could be a Text Widget, and the user would have the freedom to enter anything he wanted here.
  • Use a theme setting. Retrieve a modification setting for the current theme and display it here. This gives the theme more control on what can be entered here and how it will be displayed.

For the purpose of this starter template, lets use a widget for this footer area. So here we begin widgetizing our theme! Widgetizing is a pseudo word that describes the process of implementing Widgets and Widget Areas into a WordPress theme.

In order to add widgets, we need to register them first. Somewhat similar to the menus. Widget registration tells the theme about the widgets that are available and what their names (slugs) are, so that we can use those identifiers to call and display them. We use register_sidebar() to do this – read up more on this function to see all the possible arguments and options. Now add the following lines to functions.php in order to register a widget area called “Footer – Copyright Text”:

function bootstrapstarter_widgets_init() {

    register_sidebar( array(
        'name'          => 'Footer - Copyright Text',
        'id'            => 'footer_copyright_text',
        'before_widget' => '<div class="footer_copyright_text">',
        'after_widget'  => '</div>',
        'before_title'  => '<h4>',
        'after_title'   => '</h4>',
    ) );

add_action( 'widgets_init', 'bootstrapstarter_widgets_init' );

The above code tells WordPress to register a new sidebar widget called “Footer – Copyright Text” with the ID “footer_copyright_text”. And also that any widget assigned to this location should be wrapped with a div with the CSS class “footer_copyright_text” and if a title is entered, the title should be wrapped in h4 tags. Now that we’ve told WordPress about the presence of a footer widget, we use the widget ID to display it in the appropriate spot. So our final footer.php file becomes:

</div><!-- /.row -->

</div><!-- /.container -->

<footer class="blog-footer">
    <?php if ( is_active_sidebar( 'footer-copyright-text' ) ) { dynamic_sidebar( 'footer-copyright-text' ); } ?>
<?php wp_footer(); ?>

We first check if the sidebar called “footer-copyright-text” is active or in use by using the function is_active_sidebar(). Any sidebar that contains widgets will return true, whereas any sidebar that does not contain any widgets will return false. If the sidebar is in use, we use the function dynamic_sidebar() to display the widgets assigned to the sidebar area “footer-copyright-text”.

Now that the footer is widgetized, a Text Widget containing the HTML we removed can be assigned to the “Footer – Copyright Text” sidebar.


The sidebar should be straightforward now that we know how to create widgets. Lets create two widget areas here – if you look at the starter template we’re following, you’ll see that the top widget (“About”) has a grey background. We’d like to treat that one separately – so we register up two sidebar areas: one with the background color and one without.

Add the following two lines to the already existing bootstrapstarter_widgets_init() function we created in the previous step:

    register_sidebar( array(
        'name'          => 'Sidebar - Inset',
        'id'            => 'sidebar-1',
        'before_widget' => '<div class="sidebar-module sidebar-module-inset">',
        'after_widget'  => '</div>',
        'before_title'  => '<h4>',
        'after_title'   => '</h4>',
    ) );
    register_sidebar( array(
        'name'          => 'Sidebar - Default',
        'id'            => 'sidebar-2',
        'before_widget' => '<div class="sidebar-module">',
        'after_widget'  => '</div>',
        'before_title'  => '<h4>',
        'after_title'   => '</h4>',
    ) );

As you can tell, this registers the two sidebars: one wrapped with a div with the CSS classes “sidebar-module sidebar-module-inset” and the other with “sidebar-module” only. Now that these are registered, we need to call the display function in sidebar.php:

<div class="col-sm-3 col-sm-offset-1 blog-sidebar">
    <?php if ( is_active_sidebar( 'sidebar-1' ) ) { dynamic_sidebar( 'sidebar-1' ); } ?>
    <?php if ( is_active_sidebar( 'sidebar-2' ) ) { dynamic_sidebar( 'sidebar-2' ); } ?>
</div><!-- /.blog-sidebar -->

Lastly – we need to include the sidebar into the main template file index.php – previously, we had created all the parts but only the header and footer are being called in the index.php file. So lets open index.php and use the get_sidebar() function right after the blog area – the final index.php is:

<?php get_header(); ?>
<div class="col-sm-8 blog-main">
    if ( have_posts() ) { 
        while ( have_posts() ) : the_post();
    <div class="blog-post">
        <h2 class="blog-post-title"><?php the_title(); ?></h2>
        <p class="blog-post-meta"><?php the_date(); ?> by <?php the_author(); ?></p>
        <?php the_content(); ?>
    </div><!-- /.blog-post -->

        <ul class="pager">
            <li><?php next_posts_link('Previous'); ?></li>
            <li><?php previous_posts_link('Next'); ?></li>

</div><!-- /.blog-main -->

<?php get_sidebar(); ?>

<?php get_footer(); ?>


After doing all the above, lets go to the administration area and go to Appearance > Menus. Create a new menu, add a few items to it and assign it to the “Header Menu” location.

Now for the widgets. Lets go to Appearance > Widgets – you will see something like this:

Grab a Text widget and drag it to the “Footer – Copyright Text” area. Enter this into the Content field:

<p>Blog template built for <a href="">Bootstrap</a> by <a href="">@mdo</a>.</p><p><a href="#">Back to top</a></p>

Grab another Text widget, drag it to the “Sidebar – Inset” area and enter “About” into the Title and the following into the Content field:

<p>Etiam porta <em>sem malesuada magna</em> mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.</p>

Drag the Categories and Archives widgets into the “Sidebar – Default” area. You will end up with something like this:

That should do it! Look at the front end and you will have a fully integrated blog template complete with a sidebar. Pat yourself on the back and take a break.

Download the final source here: Download Source

Note: it contains the CSS fixes and tweaks for the top navigation bar and sidebar lists.

Disclosure: This page may contain external affiliate links that may result in receiving a commission if you make a purchase using the links. The opinions and reviews on this page are completely our own.


  1. Hi there. I just wanted to say thank you for the tutorial. I am a beginner to WordPress, and I am trying to learn wherever I can. I am running into a bit of an issue with the CSS file. I see where you assisgned the class “blog-nav” and “list-inline” in the header to the menu, but when you run the source code it appears to not respond to the CSS. It still has bullets and will not respond to any change. When you inspect the item it tells you that it is listed under “ul” and “li”. When you give “list-style-type: none;” to ul, and “display: inline;” to li it fixes it. But I was wondering if there was a way to target the primary menu only. Thanks again.

    1. Hello George,

      Sorry for the delayed response. Are you saying that the CSS is not loading or the menu list does not have the correct classes ‘blog-nav list-inline’ assigned? The code works fine for me, please be sure to read the first part of the tutorial which shows you how to enqueue the CSS file. If you like, give me a link to your source and I can help you debug it πŸ™‚

      Best of luck!

    2. I had a similar problem and instead of using ‘theme_location’ => ‘header-menu’, I had to use ‘theme_location’ => ‘top’, when setting up the menu in header.php.

  2. Hi!
    First of all, thank you for giving us this tutorial! It was a great help to a beginner like me. I have a problem, though: for some reason, the footer sidebar isn’t showing. I checked the code and it’s identical, I even tried to substitute mine with yours in case I made some mistake but nothing works… The other sidebars are fine. Do you have any suggestion on what might be wrong?
    Thanks again,

    1. Hi! You’re most welcome πŸ™‚ Do you mean the footer copyright text is not showing up for you?

    2. Exactly! I substituted it with a static text but I was curious anyway on why it wouldn’t work…

    3. In footer.php I found a little mistake πŸ˜‰ So, replace id ‘footer-copyright-text’ with ‘footer_copyright_text’

      It should be like this:

  3. How could I change the colors of the elements I.E the blue menu on the top? I tried editing style.css but doesn’t work.

  4. I dropped your theme into my folder just to test things out since I’ve been having issues with this tutorial. The wp_nav_menu generated displays as bulleted items still an that’s directly from your source code completely unaltered.

    1. Also worth noting I ran into issues when setting up the footer’s widget. You’ve got the is_active_sidebar & dynamic_sidebar both calling for footer-copyright-text when it should be footer_copyright_text. Otherwise when you use the widget, nothing appears in the footer.

  5. love the tutorials, but for the life of me can not get the top menu working properly. It keeps displaying as a standard list. I’ve got to have made a stupid mistake somewhere….(I’ve found one…after about an hour of looking!)

  6. I’m also having problems with the navigation menu. Only standard bulleted items and this is with your unaltered scripts (and after making a header-menu in admin, of course).
    Please help, I can’t find where the problem is.

  7. Hi Abby,
    Great job!
    This tut rocks!
    One little thing! For some reason my sidebar want go to to a side
    [ even on very wide monitors πŸ™‚ ] It stays right under the main module all the time.
    Is there a very simple css trick to give it more responsive behaviour?
    Any help will be greatly appreciated!

  8. Hi Abby,
    thank you for that wonderful tut. I am rather experienced with wordpress codeing, but I usually always use the _s-master theme for creating new websites. Maybe bootstrap will be faster because all the grid-stuff and the responstifity is already included.

    I will give it a try and see if I can work faster with bootstrap. Therefore I would like to know if I understood it completetly right: If I download all of your example-files and upload them into a wordpress installation, then I can start immediately with coding on a boostrap basis. Is that right or did I overlook something?


  9. For those who have problems with navs a simple fix is add to header.php <link href="/style.css” rel=”stylesheet”> this will fix the problem

  10. Thank you very much for the tutorial. It was very easy to follow your explanations and helped me a lot. Thanks again.

  11. I have my drop down menu in bullets
    Without clicking the main menu. The sub menu appears in bullets

    For some reason my footer widgets/content will not show on the published site.

    In the backend, I can add widgets, but the content will not show.

    I changed the id to footer:copyright_tect in footer.php

    to this:

    I hope someone can help me with getting it to show. The two other widget areas show.

    1. it should say:

      At the end of the if statement in footer php file

  13. This is a fantastic tutorial. Many thanks πŸ™‚
    I have had one issue with the footer as have a few people. I have been able to fix the issue but am wondering why it works if I use –
    …as opposed to –
    For each variation I changed all the necessary code to match the associated string but the footer only appeared when I used the string with the underscores.
    Thanks again

    1. it’s because in the function that he created it is listed with underscores instead of dashes and that identifier has to match the function when it is called.

  14. This is a really good tutorial for anyone taking their first steps in theming for WordPress as it can be a very daunting experience. Even I was about to give up until finding this.

    Again Footer Problem: The downloaded functions.php still shows the ‘id’ as footer-copyright-text.

    I’d also like to point out that the widgets added should be Custom HTML rather than Text

    1. Thanks Phil! I’ll be posting an update and fixes for this article soon 🀞

  15. not show menu in theme appearance. I had download your source and install in my theme. but not work properly. please help me.

    1. Resolve my problem.
      But I have need further tutorials to learn WordPress. please make new tutorial to add advance functionality in the theme.

  16. Thanx for the tutorial. I read some more documentation and came up with a way to add de navs as bootstrap blog template 4.0 ( similar to this.
    The code to add the menu items without or just the anchor element:
    ‘container’ => false,
    ‘echo’ => false,
    ‘items_wrap’ => ‘%3$s’,
    ‘depth’ => 0,

    echo strip_tags(wp_nav_menu( $menuParameters ), ‘<a>’ );

    And the code to add classes to the anchor elements:

    function add_class_to_all_menu_anchors( $atts ) {
    $atts[‘class’] = ‘p-2 text-muted’;
    return $atts;
    add_filter( ‘nav_menu_link_attributes’, ‘add_class_to_all_menu_anchors’, 10 );

Leave a Reply