Twitter’s Bootstrap is an extremelly powerful and popular responsive grid CSS framework that saves developers lots of time when creating a website.

It’s highly customizable, build with the LESS css preprocessor, has extensive documentation and is equipped with JavaScript libraries for some of the most common tasks.

What I’m going to teach you in this first tutorial of this series:

  1. How to create a simple WordPress theme
  2. How to integrate Bootstrap 3 in your WordPress theme
  3. How to customize your WordPress theme with Bootstrap 3 components


What You Will Need to Complete This Tutorial

To complete this tutorial you will need:

  • WordPress installation
  • Access to your site’s themes folder to create your theme
  • text editor to create your theme

1. Creating your theme

For a WordPress theme, all it needs in order to work is 2 files: index.php and style.css with its comments, so let’s start with this.

Inside the folder /wp-content/themes/, create a new folder called wpbootstrap.
Inside this folder create a file called index.php and paste the next code in this file:

     * The main template file.
     * This is the most generic template file in a WordPress theme and one of the
     * two required files for a theme (the other being style.css).
     * It is used to display a page when nothing more specific matches a query.
     * For example, it puts together the home page when no home.php file exists.
     * Learn more:
     * @package WordPress
     * @subpackage Wp_Bootstrap
     * @since Wp Bootstrap 1.0

Inside the same folder create style.css and paste the following code. The stylesheet must provide details about the Theme in the form of comments.

    Theme Name: Wp Bootstrap
    Theme URI:
    Author: Gabriel Vasile
    Author URI:
    Description: WordPress Bootstrap 3.0.0 Custom Theme
    Version: 1.0
    License: GNU General Public License v2 or later
    License URI:
    Tags: bootstrap
    Text Domain: wpbootstrap

    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.

Add a bit of customization by adding in your theme’s folder a screenshot for your theme and a favicon. The recommended image size for the screenshot is 600×450 and it should be named screenshot.png. You can either add it now, or after you create your theme by taking a print screen of it.

The favicon should be 16×16 and it could be named favicon.ico or favicon.png. The website can help you create one from an image or you can create one by using an image editing software like Photoshop or Gimp.

Et voila! You’ve just created your first WordPress theme. You will immediately see your screenshot and theme details when you go and switch your theme from Appeararance → Themes in your admin panel. We will add later the favicon in your theme as well.


2. Integrating Bootstrap 3 in your theme

In order to integrate JavaScript and CSS files in the theme, we will use a function.php file. The safe and recommended method of adding JavaScript to a WordPress generated page and WordPress Theme or Plugin is by using wp_enqueue_script(). This function includes the script if it hasn’t already been included, and safely handles dependencies.

We can either use Bootstrap’s CDN to get the files or you can download them directly and put them in your theme. I’ll show you both. First, create your functions.php file inside your theme’s folder and paste the next code, which will get the Bootstrap files directly from their CDN.

   * Enqueues scripts and styles for front end.
   * @since Wp Bootstrap 1.0
   * @return void
  function cwd_wp_bootstrap_scripts_styles() {
    // Loads Bootstrap minified JavaScript file.
    wp_enqueue_script('bootstrapjs', '//', array('jquery'),'3.0.0', true );
    // Loads Bootstrap minified CSS file.
    wp_enqueue_style('bootstrapwp', '//', false ,'3.0.0');
    // Loads our main stylesheet.
    wp_enqueue_style('style', get_stylesheet_directory_uri() . '/style.css', array('bootstrapwp') ,'1.0');
  add_action('wp_enqueue_scripts', 'cwd_wp_bootstrap_scripts_styles');

Watch closely the highlighted lines. The wp_enqueue_script() function links a script file to the generated page at the right time according to the script dependencies, if the script has not been already included and if all the dependencies have been registered. The function has the next arguments:

  • $handle - (string) (required) Name used as a handle for the script.
  • $src - (string) (optional) URL to the script.
  • $deps - (array) (optional) Array of the handles of all the registered scripts that this script depends on.
  • $ver - (string) (optional) String specifying the script version number.
  • $in_footer - (boolean) (optional) If this parameter is true, the script is placed before the end tag instead of in of the HTML document.

,so we have specified at line 11 that we want to enqueue a script named bootstrapjs from this link // , that it depends on jQuery to work, is at version 3.0.0 and should be included in the footer, not in the header.

A safe way to add/enqueue a CSS style file to the WordPress generated page is using wp_enqueue_style() function. This function accepts the next arguments:

  • $handle - (string) (required) Name used as a handle for the stylesheet.
  • $src - (string) (optional) URL to the stylesheet.
  • $deps - (array) (optional) Array of the handles of all the registered stylesheets that this stylesheet depends on.
  • $ver - (string) (optional) String specifying the stylesheet version number.
  • $media - (string) (optional) String specifying the media for which this stylesheet has been defined. Examples: ‘all’, ‘screen’, ‘handheld’, ‘print’. Default: ‘all’

,so we have specified at line 13 that we want to enqueue a style named bootstrapwp from this link // , that has no dependencies, and is at version 3.0.0. And we specified at line 15 that we want to enqueue a style named style (which is our main stylesheet that we created earlier), that it can be found in the current theme’s folder, is named style.css, depends on bootstrapwp stylesheet and is at version 1.0

Then at line 17, we’re using the wp_enqueue_scripts action. This is the proper hook to use when enqueuing items that are meant to appear on the front end. Despite the name, it is used for enqueuing both scripts and styles.

If you want to have the CSS and JavaScript Bootstrap files in your theme, you can download them, create a css folder and put the css in it (find it under dist/css/bootstrap.min.css), create a js folder and put the JavaScript file in it (find it under dist/css/bootstrap.min.js) and include them by changing previous 11 and 13 lines into this:

  wp_enqueue_script('bootstrapjs', get_template_directory_uri() . '/js/bootstrap.min.js', array('jquery'),'3.0.0', true );
  wp_enqueue_style('bootstrapwp', get_template_directory_uri() . '/css/bootstrap.min.css', false ,'3.0.0');

You might’ve realized that I’ve used get_stylesheet_directory_uri() for including style.css and a different function get_template_directory_uri() for including the Bootstrap’s files. The reason I did that, is because get_template_directory_uri() should be used for resources that are not intended to be included in/over-ridden by a child theme whereas get_stylesheet_directory_uri() should be used to include resources that are intended to be included in/over-ridden by the Child Theme.

In order to use DRY (Don’t Repeat Yourself) principles, we will be creating a header.php file and a footer.php file in our theme’s directory. Paste the next code in your header.php file that you have just created.

   * Default Header
   * @package WordPress
   * @subpackage Wp_Bootstrap
   * @since Wp Bootstrap 1.0
   */?><!DOCTYPE html>
  <html <?php language_attributes(); ?>>
    <meta charset="<?php bloginfo( 'charset' ); ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?php wp_title( '|', true, 'right' ); bloginfo('name'); ?></title>
    <link rel="profile" href="">
    <link rel="pingback" href="<?php bloginfo( 'pingback_url' ); ?>">
    <link rel="shortcut icon" href="<?php echo get_stylesheet_directory_uri(); ?>/favicon.ico" />

    // Fires the 'wp_head' action and gets all the scripts included by wordpress, wordpress plugins or functions.php 
    // using wp_enqueue_script if it has $in_footer set to false (which is the default)
    wp_head(); ?>
  <body <?php body_class(); ?>>

At line 17 we include our favicon and at line 22 we use the wp_head() function to fire the ‘wp_head’ action. Without doing this, our JavaScript and CSS will not be added to our header. Always have wp_head() before the closing  tag of your theme – not after – or you will break many plugins, which generally use this hook to add styles, scripts, and meta tags.

The body_class() function gives the body element different classes which will help theme authors to style themes more effectively with CSS.

Paste the next code in your footer.php file that you have just created.

   * Default Footer
   * @package WordPress
   * @subpackage Wp_Bootstrap
   * @since Wp Bootstrap 1.0

  // Gets all the scripts included by wordpress, wordpress plugins or functions.php 
  // using wp_enqueue_script if it has $in_footer set to true
  wp_footer(); ?>

At line 13 we use the wp_footer() function to fire the ‘wp_footer’ action. Without this function, the JavaScript added in our functions.php file with the wp_enqueue_script() funtion that has the last argument $in_footer set to true will not work.

Include header.php file and footer.php file in your index.php by adding the next code right before the closing php tag ?>

  // Gets header.php

  // Gets footer.php

Enable IE8 support of HTML5 elements and media queries by adding  in your header.php after the last meta html element and the next code in your header.php file after the wp_head() function. You need, of course, to add the html5shiv.js and respond.min.js files in your theme’s /js/ folder. You’ll find them in your Bootstrap folder (that you have downloaded earlier) under the /assets/js/ folder. This scripts MUST be added AFTER bootstrap’s css is included, hence positioning them after the wp_head() tag.

  <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
  <!--[if lt IE 9]>
    <script src="<?php echo get_template_directory_uri(); ?>/js/html5shiv.js"></script>
    <script src="<?php echo get_template_directory_uri(); ?>/js/respond.min.js"></script>

We’re now ready to use Bootstrap 3 in our WordPress theme.

3. Including Bootstrap 3 Elements

Install the WP Example Content plugin and “Add A Bundle Of Example Posts” to have some pages to work with. Also, you should probably disable the wordpress admin bar if you want sticky navigation. You can do this from Users → Your profile → Toolbar. Uncheck the “Show Toolbar when viewing site” and click Update profile.

Let’s center our page by placing all our content in a container. To do so, add <div class="container"> in header.php after the body tag and </div> <!-- // .container --> in footer before the wp_footer() function.

Display your website’s title and tagline by adding the next code to your header.php file. (You can change the defaults from your admin panel under the Settings → General section

  <h2><a href="<?php echo home_url(); ?>"><?php echo get_bloginfo('title'); ?></a></h2>
  <p><?php echo get_bloginfo('description'); ?></p>

The get_bloginfo() function returns information about your site which can then be used elsewhere in your PHP code. It has a bunch of keywords that can be used naming the information you want. Now, in order to create a Bootstrap navbar with WordPress, let’s first create a WordPress menu. To do so, before you can go to your Admin panel at the Appearance → Menus section and create one, you need to register a menu. To do this, add the next piece of code at the end of your functions.php file

  if ( ! function_exists( 'cwd_wp_bootstrapwp_theme_setup' ) ):
    function cwd_wp_bootstrapwp_theme_setup() {
      // Adds the main menu
      register_nav_menus( array(
        'main-menu' => __( 'Main Menu', 'cwd_wp_bootstrapwp' ),
      ) );
  add_action( 'after_setup_theme', 'cwd_wp_bootstrapwp_theme_setup' );

The function_exists() check is used to make functions “pluggable.” If a plugin or a theme has already defined a pluggable function, then the WP code knows not to try to redefine it.

The register_nav_menus() function registers multiple custom navigation menus in the new custom menu editor of WordPress 3.0. This allows for the creation of custom menus in the dashboard for use in your theme. It accepts as an argument an associative array of menu location slugs (key) and descriptions (according value). We also used the __() function in order to be able to internationalize our theme later on.

The after_setup_theme hook is called during each page load, after the theme is initialiazed. It is generally used to perform basic setup, registration, and init actions for a theme.

You can now create a menu in your Admin panel under the Appearance → Menu section. Once you’ve done that, paste the next code in your header.php file after the container div.

  <nav class="navbar navbar-default" role="navigation">
    <!-- Mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>

    <!-- Collect the nav links for toggling -->
    <?php // Loading WordPress Custom Menu
       wp_nav_menu( array(
          'container_class' => 'collapse navbar-collapse navbar-ex1-collapse',
          'menu_class'      => 'nav navbar-nav',
          'menu_id'         => 'main-menu',
          //'walker'          => new Cwd_wp_bootstrapwp_Walker_Nav_Menu()
      ) );

The .navbar-header part is what you’ll see on a mobile device. The .sr-only is a helper class that hides an element to all users except screen readers. This is necessary for following accessibility best practices.

If you want you navigation to be sticky, you have to include the navbar-fixed-top or navbar-fixed-bottom class (depending on what yu want) to the <nav> element at first line.

The wp_nav_menu() function displays a navigation menu created in the Appearance → Menus panel and accepts as argument an array that can have the following optional parameters:

  • $theme_location - (string) The location in the theme to be used–must be registered with register_nav_menu() in order to be selectable by the user.
  • $menu - (string) The menu that is desired; accepts (matching in order) id, slug, name.
  • $container - (array) Whether to wrap the ul, and what to wrap it with. Allowed tags are div and nav. Use false for no container.
  • $container_class - (string) The class that is applied to the container.
  • $container_id - (string) The ID that is applied to the container.
  • $menu_class - (string) The class that is applied to the ul element which encloses the menu items. Multiple classes can be separated with spaces.
  • $menu_id - (string) The ID that is applied to the ul element which encloses the menu items.
  • $echo - (boolean) Whether to echo the menu or return it. For returning menu use ’0′
  • $fallback_cb - (string) If the menu doesn’t exist, the fallback function to use. Set to false for no fallback.
  • $before - (string) Output text before the of the link.
  • $after - (string) Output text after the of the link.
  • $link_before - (string) Output text before the link text.
  • $link_after - (string) Output text after the link text.
  • $items_wrap - (string) Evaluated as the format string argument of a sprintf() expression. The format string incorporates the other parameters by numbered token. %1$s is expanded to the value of the ‘menu_id’ parameter, %2$s is expanded to the value of the ‘menu_class’ parameter, and %3$s is expanded to the value of the list items. If a numbered token is omitted from the format string, the related parameter is omitted from the menu markups.
  • $depth - (integer) How many levels of the hierarchy are to be included where 0 means all. -1 displays links at any depth and arranges them in a single, flat list.
  • $walker - (object) Custom walker object to use.

So what we use is this: ‘collapse navbar-collapse navbar-ex1-collapse’ for the container_class in order to create a div with those classes to wrap our ul, ‘nav navbar-nav’ for menu_class to give our  these classes and ‘main-menu’ for menu_id to give  these id.

We need now to replace some of the class generated by WordPress for our submenus with Bootstrap classes. We’re going to replace .sub-menu with the .dropdown-menu class, .current-menu-item with the .active class and we’re going to add class="dropdown-toggle" data-toggle="dropdown" data-target="#" to our menu links that have submenus. Also, we’re going to add the  into our menu links that have submenus. For that we’re going to a Walker Class.

Uncomment the walker line from the last code you’ve copied (14th line from above), paste this: require_once 'inc/nav.php'; at the end of your functions.php file, create an “inc” folder inside your theme’s folder, create a “nav.php” file inside this “inc” folder and paste the next code in it:

   * class Cwd_wp_bootstrapwp_Walker_Nav_Menu()
   * Extending Walker_Nav_Menu Class
   * @author Gabriel Vasile
    class Cwd_wp_bootstrapwp_Walker_Nav_Menu extends Walker_Nav_Menu {

      function display_element ($element, &$children_elements, $max_depth, $depth = 0, $args, &$output) {
        // check, whether there are children for the given ID and append it to the element with a (new) ID
        $element->hasChildren = isset($children_elements[$element->ID]) && !empty($children_elements[$element->ID]);

        return parent::display_element($element, $children_elements, $max_depth, $depth, $args, $output);

      // CHANGE .sub-menu INTO .dropdown-menu
      function start_lvl(&$output, $depth) {
        $indent = str_repeat("\t", $depth);
        $output .= "\n$indent<ul class=\"dropdown-menu\">\n";

      function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
        $item_html = '';
        parent::start_el($item_html, $item, $depth, $args);

        if (($item->hasChildren) && ($depth === 0)) {
          $item_html = str_replace('<a', '<a class="dropdown-toggle" data-toggle="dropdown" data-target="#"', $item_html);
          $item_html = str_replace('</a>', ' <b class="caret"></b></a>', $item_html);

        $output .= $item_html;


    function cwd_wp_bootstrapwp_nav_menu_css_class($classes, $item) {
      // CHANGE .current-menu-item .current-menu-parent .current-menu-ancestor INTO .active
      $classes = preg_replace('/(current(-menu-|[-_]page[-_])(item|parent|ancestor))/', 'active', $classes);

      // Add the .dropdown class to the list items that have children
      if ($item->hasChildren) {
        $classes[] = 'dropdown';

      return $classes;
    add_filter('nav_menu_css_class', 'cwd_wp_bootstrapwp_nav_menu_css_class', 10, 2);

I know that this piece of code can seem hard to understand, so you can check out this tutorial if you want to understand better the Walker class. What we’re basically doing in the display_element() funtion is we’re adding a boolean called hasChildren in our object so we can have a quick way of testing if a menu has submenus.

Then, we’re rewriting the start_lvl() function in order to change the default .sub-menu class into the Bootstrap’s .dropdown-menu class. Then we’re using the start_el() function to add class="dropdown-toggle" data-toggle="dropdown" data-target="#" and  to the menu items that have submenus.

The last function cwd_wp_bootstrapwp_nav_menu_css_class() is used to change the .current-menu-item .current-menu-parent .current-menu-ancestor classes into Bootstrap’s .active class. The nav_menu_css_class is a filter hook called by the WordPress Walker_Nav_Menu class.

If you still want to understand better the Walker Class, analyze the Walker class and the Walker_Nav_Menu class in the WordPress code.

So, there you go! Now you have a Bootstrap menu in your WordPress theme. Let’s also add a copyright message in the footer.php file within a small Bootstrap well like this:

  <div class="well well-sm">
    <a href="#top" class="pull-right">Back to top</a>
    Copyright © Creative Web Design <?php echo date('Y'); ?>

The date('Y') function will output the current year. Your theme should now look something similar with this:

Create a Responsive WordPress Theme With Bootstrap 3

In this tutorial you’ve learned how to

  • Create a WordPress Theme
  • Integrate Bootstrap 3 in a WordPress Theme
  • Create a WordPress Menu with Bootstrap
  • Customize a WordPress Menu using the Walker class
  • Add a Bootstrap well.

In the next tutorial I’ll show you how to create a slider using Custom Post Types and Bootstrap’s Carousel component.