With the advent and increase in popularity of the mobile web, developers have had to adapt themselves to handling new challenges, such as different layouts in different resolutions, the new user experience paradigm, and optimization for low-bandwidth connections. While facing this, there were also a lot of old problems related to browser compatibility and lack of patterns in the community.
This was the outline scenario when the Bootstrap framework arrived. Developed by Twitter, the main goal of Bootstrap is to provide a web frontend framework for responsive developing with cross-browser compatibility. It is awesome! Developers fell in love with it and started to adopt it right away.
Therefore, to cover this book's objective of presenting the Bootstrap framework to build responsive, mobile-first websites faster than ever before, we must get started by setting up our work environment in the best recommended way. Thus, the topics that we will cover in this chapter are:
- Getting Bootstrap
- Setting up Bootstrap in a web page
- Building the first Bootstrap example
- The container element tag
- Support sources
- Framework compatibility
There are several versions of the framework, but in this book, we will provide support for the latest Bootstrap 3 version (which is v3.3.5), along with the newest version 4 (which is 4.0.0-alpha). When a feature or component is differently supported by one of these versions, we will point it out properly.
First of all, access the official website at http://getbootstrap.com/ and click on the Download Bootstrap button, as shown in the following screenshot:

Tip
Downloading the example code
You can download the example code files for this book from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
You can download the code files by following these steps:
- Log in or register to our website using your e-mail address and password.
- Hover the mouse pointer on the SUPPORT tab at the top.
- Click on Code Downloads & Errata.
- Enter the name of the book in the Search box.
- Select the book for which you're looking to download the code files.
- Choose from the drop-down menu where you purchased this book from.
- Click on Code Download.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
- WinRAR / 7-Zip for Windows
- Zipeg / iZip / UnRarX for Mac
- 7-Zip / PeaZip for Linux
Then you will be redirected to another page that contains these buttons:
- Download Bootstrap: This is the release with the files already compiled.
- Download source: Use this if you want to get the source for customization. This requires knowledge of the Less language.
- Download Sass: Here, you can get the source code in the Sass language.
Click on the Download Bootstrap button to get the framework, since we will cover the full framework using, not Sass, but just HTML, CSS, and JavaScript. After the download, extract the files and you will see that the framework is organized in folders.
Tip
Other versions and releases
Check out the official repository at https://github.com/twbs/bootstrap/ to pick up other versions and see the new releases under development. You will also be able to see other features and community activity.
If you want to go hands-on straightforward with version 4, go to http://v4-alpha.getbootstrap.com/ and download it, or enter the GitHub repository and select the corresponding branch of version 4.
After you've extracted the files, you will see some folders. The first one, in alphabetical order, is css
. Here, you will find the main CSS file (named bootstrap.css
), other files related to the minified version, and a bootstrap-theme.css
file, which is a simple theme of using the Bootstrap components.
There is also a fonts
folder; it contains the files used for the icon components that we will see in future chapters. Finally, there is a folder named js
, where we can find the bootstrap.js
file, the minified version, and the specification for npm
.
Now that we have downloaded the framework and covered its basic file architecture, we will advance to setting up Bootstrap on a web page.
First, let's explicit the folder structure that we will be using in this book. In a folder that we will call main_folder
, we extract the Bootstrap contents and create a file called hello_world.html
at the same level. Inside the Bootstrap contents will be some folders for fonts, CSS, and JavaScript. The final layout should be like this:

Now, we will add the recommended setup of the Bootstrap framework to the hello_world.html
file. Open it in your preferred code editor and add the outline HTML code, like this:
<!DOCTYPE html> <html> <head> <title>Hello World!</title> </head> <body> Hello World </body> </html>
Next, add the code for loading css
inside the head
tag:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
Hello World
</body>
</html>
And at the end of the body
tag, load the JavaScript file:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
Hello World
<script src="js/bootstrap.js"></script>
</body>
</html>
Open the hello_world.html
file in a browser (we will use Google Chrome in this book) and open the JavaScript console. In Chrome, it can be found at Options button (the hamburger button on right upper corner. Go to More Tools | Developer Tools, just as shown in the following screenshot, and click on Console in the opened window. You will see a message saying Bootstrap's JavaScript requires jQuery:

jQuery is a cross-platform JavaScript library, and it is the only third-party requirement for Bootstrap. To get it, we recommend the download from the official website and the latest version (https://jquery.com/download/). Bootstrap requires version 1.9 or higher.
Copy the jQuery file inside the js
folder, and load it in the HTML code at the end of the body tag but before the bootstrap.js
loads, like this:
<script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script>
Bootstrap has three tags that must be at the beginning of the <head>
tag. These tags are used for text encoding and improved visualization on mobile devices:
<meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1">
The viewport
tag is related to the mobile-first philosophy. By adding it, you ensure proper rendering in mobile devices and touch zooming.
You can also disable the zoom functionality by appending user-scalable=no
in the content key. With this option, users will only be able to scroll on the web page, resulting in a feel of using a native mobile application.
Also, if you want to add support for older versions of the Internet Explorer (IE) browser (older than version 9), you must add some libraries to have fallback compatibility for the HTML5 and CSS3 elements. We will add them via CDN, which is the Bootstrap recommendation. So, add these lines at the end of the <head>
tag:
<!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]-->
At this point, the file should be like this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Hello World!</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> Hello World! <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
This is our base page example! Keep it for the purpose of coding every example of this book and for any other web page that you will develop.
We would like to point out that Bootstrap requires the doctype
HTML5 style before the <html>
tag:
<!DOCTYPE html> <html> ... <!--rest of the HTML code --> </html>
Folder structure
First, let's explicit the folder structure that we will be using in this book. In a folder that we will call main_folder
, we extract the Bootstrap contents and create a file called hello_world.html
at the same level. Inside the Bootstrap contents will be some folders for fonts, CSS, and JavaScript. The final layout should be like this:

Now, we will add the recommended setup of the Bootstrap framework to the hello_world.html
file. Open it in your preferred code editor and add the outline HTML code, like this:
<!DOCTYPE html> <html> <head> <title>Hello World!</title> </head> <body> Hello World </body> </html>
Next, add the code for loading css
inside the head
tag:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
Hello World
</body>
</html>
And at the end of the body
tag, load the JavaScript file:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
Hello World
<script src="js/bootstrap.js"></script>
</body>
</html>
Open the hello_world.html
file in a browser (we will use Google Chrome in this book) and open the JavaScript console. In Chrome, it can be found at Options button (the hamburger button on right upper corner. Go to More Tools | Developer Tools, just as shown in the following screenshot, and click on Console in the opened window. You will see a message saying Bootstrap's JavaScript requires jQuery:

jQuery is a cross-platform JavaScript library, and it is the only third-party requirement for Bootstrap. To get it, we recommend the download from the official website and the latest version (https://jquery.com/download/). Bootstrap requires version 1.9 or higher.
Copy the jQuery file inside the js
folder, and load it in the HTML code at the end of the body tag but before the bootstrap.js
loads, like this:
<script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script>
Bootstrap has three tags that must be at the beginning of the <head>
tag. These tags are used for text encoding and improved visualization on mobile devices:
<meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1">
The viewport
tag is related to the mobile-first philosophy. By adding it, you ensure proper rendering in mobile devices and touch zooming.
You can also disable the zoom functionality by appending user-scalable=no
in the content key. With this option, users will only be able to scroll on the web page, resulting in a feel of using a native mobile application.
Also, if you want to add support for older versions of the Internet Explorer (IE) browser (older than version 9), you must add some libraries to have fallback compatibility for the HTML5 and CSS3 elements. We will add them via CDN, which is the Bootstrap recommendation. So, add these lines at the end of the <head>
tag:
<!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]-->
At this point, the file should be like this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Hello World!</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> Hello World! <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
This is our base page example! Keep it for the purpose of coding every example of this book and for any other web page that you will develop.
We would like to point out that Bootstrap requires the doctype
HTML5 style before the <html>
tag:
<!DOCTYPE html> <html> ... <!--rest of the HTML code --> </html>
Warming up the sample example
Now, we will add the recommended setup of the Bootstrap framework to the hello_world.html
file. Open it in your preferred code editor and add the outline HTML code, like this:
<!DOCTYPE html> <html> <head> <title>Hello World!</title> </head> <body> Hello World </body> </html>
Next, add the code for loading css
inside the head
tag:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
Hello World
</body>
</html>
And at the end of the body
tag, load the JavaScript file:
<!DOCTYPE html>
<html>
<head>
<title>Hello World!</title>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body>
Hello World
<script src="js/bootstrap.js"></script>
</body>
</html>
Open the hello_world.html
file in a browser (we will use Google Chrome in this book) and open the JavaScript console. In Chrome, it can be found at Options button (the hamburger button on right upper corner. Go to More Tools | Developer Tools, just as shown in the following screenshot, and click on Console in the opened window. You will see a message saying Bootstrap's JavaScript requires jQuery:

jQuery is a cross-platform JavaScript library, and it is the only third-party requirement for Bootstrap. To get it, we recommend the download from the official website and the latest version (https://jquery.com/download/). Bootstrap requires version 1.9 or higher.
Copy the jQuery file inside the js
folder, and load it in the HTML code at the end of the body tag but before the bootstrap.js
loads, like this:
<script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script>
Bootstrap has three tags that must be at the beginning of the <head>
tag. These tags are used for text encoding and improved visualization on mobile devices:
<meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1">
The viewport
tag is related to the mobile-first philosophy. By adding it, you ensure proper rendering in mobile devices and touch zooming.
You can also disable the zoom functionality by appending user-scalable=no
in the content key. With this option, users will only be able to scroll on the web page, resulting in a feel of using a native mobile application.
Also, if you want to add support for older versions of the Internet Explorer (IE) browser (older than version 9), you must add some libraries to have fallback compatibility for the HTML5 and CSS3 elements. We will add them via CDN, which is the Bootstrap recommendation. So, add these lines at the end of the <head>
tag:
<!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]-->
At this point, the file should be like this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Hello World!</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> Hello World! <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
This is our base page example! Keep it for the purpose of coding every example of this book and for any other web page that you will develop.
We would like to point out that Bootstrap requires the doctype
HTML5 style before the <html>
tag:
<!DOCTYPE html> <html> ... <!--rest of the HTML code --> </html>
Bootstrap required tags
Bootstrap has three tags that must be at the beginning of the <head>
tag. These tags are used for text encoding and improved visualization on mobile devices:
<meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1">
The viewport
tag is related to the mobile-first philosophy. By adding it, you ensure proper rendering in mobile devices and touch zooming.
You can also disable the zoom functionality by appending user-scalable=no
in the content key. With this option, users will only be able to scroll on the web page, resulting in a feel of using a native mobile application.
Also, if you want to add support for older versions of the Internet Explorer (IE) browser (older than version 9), you must add some libraries to have fallback compatibility for the HTML5 and CSS3 elements. We will add them via CDN, which is the Bootstrap recommendation. So, add these lines at the end of the <head>
tag:
<!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]-->
At this point, the file should be like this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Hello World!</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> Hello World! <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
This is our base page example! Keep it for the purpose of coding every example of this book and for any other web page that you will develop.
We would like to point out that Bootstrap requires the doctype
HTML5 style before the <html>
tag:
<!DOCTYPE html> <html> ... <!--rest of the HTML code --> </html>
Now we are all set for the framework. Replace the Hello World!
line in the body
tag with this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Hello World!</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> <div class="jumbotron"> <h1>Hello, world!</h1> <p>This is our first sample example that will be more awesome in the next chapters!</p> <a class="btn btn-primary btn-lg" href="#" role="button"> Bootstrap by Example, Chapter 1 </a> </div> <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
Open the
hello_world.html
file in the browser, and it must appear like what is shown in the following screenshot:

Congratulations! You have created your first Bootstrap web page. It is simple but very important to understand the details of how to set the framework correctly to keep the recommendation pattern.
Furthermore, we added some components in this example that will be explained in future chapters, but you can start becoming familiar with the CSS classes used and the placement of the elements.
You may notice that in our example, the page content is too close to the left-hand side and without a margin/padding. This is because Bootstrap has a required element called container
that we have not added in the example.
The container
tag must be placed to wrap the site content and nest the grid system (we will present the grid system, called scaffolding, in the next chapter). There are two options for using the container element.
The first one is for creating a web page responsive with a fixed-width container. This one will add responsive margins depending on the device viewport:
<div class="container"> ... </div>
In case you want a full-width container, covering the entire width of the viewport, use container-fluid
:
<div class="container-fluid"> ... </div>
In our example, we will create a fixed-width responsive website. So, our code will be like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hello World!</title>
<link rel="stylesheet" href="css/bootstrap.css">
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js">
</script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js">
</script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Hello, world!</h1>
<p>This is our first sample example that will be more awesome in the next chapters!</p>
<a class="btn btn-primary btn-lg" href="#" role="button">
Bootstrap by Example, Chapter 1
</a>
</div>
</div>
<script src="js/jquery-1.11.3.js"></script>
<script src="js/bootstrap.js"></script>
</body>
</html>
The next screenshot shows what our example looks like with the addition of the container class. I recommend for practicing and complete understanding, that you change the container class to .container-fluid
and see what happens. Change your viewport by resizing your browser window and see how Bootstrap adapts your page visualization:

The preceding image shows the differences between using .container
and .container-fluid
. See the differences of the margins in the sides.
Soon during this book, you will be able to create more complex and beautiful websites, using more advanced Bootstrap components such as the show case shown in the following screenshot, which is an example of a landing page.
Do not worry. We will start at a slow pace to reveal the basics of Bootstrap and how to use it properly on our web page. The following example is our first goal when we develop a landing page example. Just keep in mind that we will always use the same basis presented in this chapter.

The container tag
You may notice that in our example, the page content is too close to the left-hand side and without a margin/padding. This is because Bootstrap has a required element called container
that we have not added in the example.
The container
tag must be placed to wrap the site content and nest the grid system (we will present the grid system, called scaffolding, in the next chapter). There are two options for using the container element.
The first one is for creating a web page responsive with a fixed-width container. This one will add responsive margins depending on the device viewport:
<div class="container"> ... </div>
In case you want a full-width container, covering the entire width of the viewport, use container-fluid
:
<div class="container-fluid"> ... </div>
In our example, we will create a fixed-width responsive website. So, our code will be like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Hello World!</title>
<link rel="stylesheet" href="css/bootstrap.css">
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js">
</script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js">
</script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="jumbotron">
<h1>Hello, world!</h1>
<p>This is our first sample example that will be more awesome in the next chapters!</p>
<a class="btn btn-primary btn-lg" href="#" role="button">
Bootstrap by Example, Chapter 1
</a>
</div>
</div>
<script src="js/jquery-1.11.3.js"></script>
<script src="js/bootstrap.js"></script>
</body>
</html>
The next screenshot shows what our example looks like with the addition of the container class. I recommend for practicing and complete understanding, that you change the container class to .container-fluid
and see what happens. Change your viewport by resizing your browser window and see how Bootstrap adapts your page visualization:

The preceding image shows the differences between using .container
and .container-fluid
. See the differences of the margins in the sides.
Soon during this book, you will be able to create more complex and beautiful websites, using more advanced Bootstrap components such as the show case shown in the following screenshot, which is an example of a landing page.
Do not worry. We will start at a slow pace to reveal the basics of Bootstrap and how to use it properly on our web page. The following example is our first goal when we develop a landing page example. Just keep in mind that we will always use the same basis presented in this chapter.

Bootstrap also offers a setup using CDN to load the framework. It's much easier to set up but comes with some regards. Instead of the <link>
that we created to load the CSS, we must load it from CDN using this:
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
And to load the JavaScript file, replace the JavaScript <script>
tag with the following line:
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
There is some discussion on whether or not to use CDN. We will not touch upon this point, but the main pro is having the content provided faster with high availability. The main con is that you cannot have direct control over what is in the content provided, having unreliable imported code.
The decision of whether or not to use CDN depends on the case. You should consider the different arguments and choose an option that best fits your web page. There is no right or wrong, just different points of view.
The Bootstrap framework is discussed in several places across the Internet. It is important to have an engaged community that keeps evolving the framework and supporting it. You can have support and acquire more knowledge by going to some other resources, such as the following:
- The Bootstrap official GitHub repository. Here (https://github.com/twbs/bootstrap), you can find the road map development and the newest releases, report issues, and solve them by making a pull request.
- The Bootstrap official documentation (http://getbootstrap.com/) provides some additional information of the framework's usage and support.
- Bootstrap Blog (http://blog.getbootstrap.com/) is the best way to follow news about Bootstrap and read the releases notes.
- Bootstrap Expo (http://expo.getbootstrap.com/) is a showcase web page where you can see some beautiful websites that use the framework and resources to be used within such as plugins, themes, and so on.
- Stack Overflow questions related to Bootstrap (http://stackoverflow.com/questions/tagged/twitter-bootstrap). This is one of the best means of communication to get help from for your issues. Search for questions related to yours, and if you can't find something related, I guarantee that you will have an answer very soon.
There are many other resources spread across the Internet. Use them all to your advantage, and appreciate the taste of developing in fast pace with the best frontend framework of our time.
Bootstrap has an official HTML lint called Bootlint (https://github.com/twbs/bootlint). It checks the DOM for mistakes in using Bootstrap elements and components. Add Bootlint to avoid mistakes that delay your development. Check out the repository for installation and usage instructions.
Tools
Bootstrap has an official HTML lint called Bootlint (https://github.com/twbs/bootlint). It checks the DOM for mistakes in using Bootstrap elements and components. Add Bootlint to avoid mistakes that delay your development. Check out the repository for installation and usage instructions.
Bootstrap is one of the best frameworks for building web apps. Since you may use the same layout pattern across the web app, with premade classes and themes provided by the framework, you can speed up your development while maintaining the coherence of the elements used.
After the framework's release, Twitter adopted it like many other web apps as well. The following screenshot shows a great example of a fluid web app that uses Bootstrap with a fluid container:

The Bootstrap framework supports the most recent versions of the most used browsers. However, depending on the browser, the elements' rendering might look a little different from others, such as in the Chrome and Firefox Linux versions.
Internet Explorer's (IE) old versions do not have some properties from CSS3 and HTML5 that are used in the framework, so be aware of this when supporting these browsers. The following table presents the official browser compatibility.
Also, with the new version 4 of the framework, some compatibilities have been dropped. They decided to drop the support that existed for IE8, since it was dragging down the addition of new features, and now Bootstrap is able to take advantage of the use of some new CSS features.
With regard to this, version 4 moved from pixels to rems and ems measures to make responsive and resizing easier, and with that, they dropped support for iOS 6 as well:
Chrome |
Firefox |
Internet Explorer |
Opera |
Safari | |
---|---|---|---|---|---|
Android |
Yes |
Yes |
N/A |
No |
N/A |
iOS |
Yes |
N/A |
N/A |
No |
Yes (iOS 7 + for v4) |
OS X |
Yes |
Yes |
N/A |
Yes |
Yes |
Windows |
Yes |
Yes |
Yes (IE9 + for v4) |
Yes |
No |
Tip
The meaning of em and rem
The units em and rem have moved from trending to reality! They are enforced as present in our context and have now gained the support of Bootstrap. The main difference between em and rem is that they are relative unit metrics, while pixels are not. em is a unit relative to the parent font size and rem is a unit relative to the root element, perfectly fitting this responsivity development context.
In this chapter, you learned some basic concepts about using the Bootstrap framework. These are the key points for creating web sites with high quality. Knowing them in depth gives you a huge advantage and helps with the handling of future problems.
The chapter's goal was to show the recommended setup for the Bootstrap framework, presenting the placement of the tags, libraries import, and creating a very simple web page. Remember that consistency across the website is the main thing about Bootstrap, saving your precious time.
Also keep in mind that when starting a new web page, you have to guarantee a good placement of the main tags and components no matter how you created it (manually, boilerplate, or in other ways). Many problems stem from inadequate groundwork.
We also presented some resources from which you can acquire further knowledge or any kind of help. You now belong to a big "open arms" community that you can always count on.
Now that we have this background, let's attack some real-world problems! In the next chapter, we will start developing a very common real-life example, which is a landing page, while presenting some Bootstrap components, HTML elements, and grid systems.
In this chapter, you will start learning some new Bootstrap elements and components. By doing this, you will first understand the concepts of the Bootstrap grid system and move on to some basic components. Now, we are going to start the development of a responsive sample landing page. First, we will use the base theme of the framework, and in future, we will apply our own style.
The main structure of this chapter is as follows:
- The Bootstrap grid system
- Typography
- Tables
- Buttons
The basis of the Bootstrap framework relies in its grid system. Bootstrap offers components that allow us to structure a website in a responsive grid layout.
To exemplify this, imagine an electronic square sheet table that can be divided into many rows and columns, as shown in the following screenshot. In the table, you can create as many lines as you want while merging cells. But what would happen if you wanted to change the layout of a single row? That could be painful.

The Bootstrap grid system works in a different way. By letting you define a set of rows, each one having a set of independent columns, it allows you to build a solid grid system for your web page. Also, each column can have different sizes to perfectly fit your template.
This not being enough, the Bootstrap grid system adapts for every viewport and resolution, which we call responsiveness.
To start learning about the grid system, we will introduce it using the example of a landing page. As you will see, Bootstrap will allow us to create a complete scaffolding that will automatically adjust the content for any viewport.
For our landing page, we will use the grid presented in the following image. As you can see, it is represented by seven rows, each containing a different number of columns. In this first example, we will use a nonmobile viewport, which we will discuss in the next chapter.

To start that, let's use our default layout presented in Chapter 1, Getting Started. Add inside the div.container
tag another div
with the .row
class:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Landing page</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> <div class="container"> <div class="row"></div> </div> <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
The hierarchy for the grid system always follows the sequence of a container that wraps rows and multiple columns. Keep in mind to always use this sequence to get a proper output.
Now that we have our .container
with the first .row
, let's create our first column. Every row is subdivided into 12 parts, so you can have up to 12 columns in a single row.
To identify a column, we must follow the template of .col-*-*
. The first asterisk means the viewport for the column, and the other one means the size of the column. We will explain more about that, but to create our first column, we create a column identified by .col-md-12
inside our row:
<div class="container"> <div class="row"> <header class="col-md-12"> HEADER </header> </div> </div>
In this column, the md
in.col-md-12
means that for the viewport medium (which means the md
identifier), the column must have a 12-column width. In other words, the column fills the entire width of this row. This column will fill the complete width because it is our header, and as we can see in the previous image, this row is composed of just a single row.
So, to create a column in the Bootstrap grid system, you must follow the recipe of .col-*-*
for every column. While you can set an integer from 1
to 12
for the width, for the viewport, you must set the correct class prefix. In this table, you can see the breakdown of class prefix usage and on which resolution it can be used:
Extra small devices (phones < 544 px / 34 em) |
Small devices (tablets ≥ 544 px / 34 em and < 768 px / 48 em) |
Medium devices (desktops ≥ 768 px /48 em and < 900 px / 62 em) |
Large devices (desktops ≥ 900 px / 62 em and < 1,200 px 75 em) |
Extra large devices (desktops ≥ 1,200 px / 75 em) | |
---|---|---|---|---|---|
Grid behavior |
Horizontal lines at all times |
Collapse at start and fit the column grid | |||
Container's fixed width |
Auto |
|
|
|
|
Class prefix |
|
|
|
|
|
Number of columns |
12 | ||||
Column fixed width |
Auto |
|
|
|
|
Our second row is divided into three equal-sized columns, and the first one is an offset column, or in other words, an empty column that will be filled by a left margin. Therefore, the second row will be like this:
<div class="row"> <div class="col-md-offset-4 col-md-4">1/3</div> <div class="col-md-4">1/3</div> </div>
As you can see, by adding the .col-md-offset-4
class, we create a margin to the left four, sized in just this .row
. By having each row independent of the others, we can properly customize the layout to appear just as it is supposed to be.
Now we will advance to the third row in our scaffolding. If you've got the spirit, you should have no problems with this row. For training, try doing it by yourself and check the solution in the book afterwards! I am sure you can handle it.
So, this row is composed of two columns. The first column must fill 4 out of the 12 parts of the row and the other column will fill the rest. The row in the HTML should look like this:
<div class="row"> <div class="col-md-4"></div> <div class="col-md-8"></div> </div>
About the fourth row—it is composed of a quarter divisor, followed by a half divisor, followed by a last quarter divisor. Using this in base 12, we will have the following grid in the row:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6">1/2</div> <div class="col-md-3">1/4</div> </div>
In the fifth and sixth rows, we will show how you can create a row using two options. In the fifth row, we will create just as we are doing in the other rows, while in the sixth row, we will use the concept of nesting rows.
So, in the fifth row, create it just as you were doing before; create a row with four equally sized rows, which means that each column will have the .col-md-3
class:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div>
For the sixth row, we will use nesting rows. So, let's create the first .row
, having three columns:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"></div> <div class="col-md-3">1/4</div> </div>
As you can see, the first and the last column use the same class of columns in row five—the .col-md-3
class—while the middle column is double the size, with the .col-md-6
class.
Let's nest another .row
inside the middle column. When you create a new nested row, the columns inside of it are refreshed and you have another set of 12-sized columns to put inside it. So, inside this new row, create two columns with the .col-md-6
class to generate two columns representing a fourth of the row:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div>
The concept of nesting rows is pretty complex, since you can infinitely subdivide a row, although it is great to create small grid components inside your page that can be used in other locations.
To create the last row, we need to create the .col-md-2
column, followed by .col-md-7
and .col-md-3
. So, just create a row using the <footer>
tag with those columns. The complete scaffolding will be this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Landing page</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> <div class="container"> <!-- row 1 --> <div class="row"> <header class="col-md-12"> HEADER </header> </div> <!-- row 2 --> <div class="row"> <div class="col-md-offset-4 col-md-4">1/3</div> <div class="col-md-4">1/3</div> </div> <!-- row 3 --> <div class="row"> <div class="col-md-4"></div> <div class="col-md-8"></div> </div> <!-- row 4 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6">1/2</div> <div class="col-md-3">1/4</div> </div> <!-- row 5 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div> <!-- row 6 – nesting rows --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div> <!-- row 7 --> <footer class="row"> <div class="col-md-2">1/2</div> <div class="col-md-7">7/12</div> <div class="col-md-3">1/4</div> </footer> </div> <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
Setting things up
To start that, let's use our default layout presented in Chapter 1, Getting Started. Add inside the div.container
tag another div
with the .row
class:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Landing page</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> <div class="container"> <div class="row"></div> </div> <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
The hierarchy for the grid system always follows the sequence of a container that wraps rows and multiple columns. Keep in mind to always use this sequence to get a proper output.
Now that we have our .container
with the first .row
, let's create our first column. Every row is subdivided into 12 parts, so you can have up to 12 columns in a single row.
To identify a column, we must follow the template of .col-*-*
. The first asterisk means the viewport for the column, and the other one means the size of the column. We will explain more about that, but to create our first column, we create a column identified by .col-md-12
inside our row:
<div class="container"> <div class="row"> <header class="col-md-12"> HEADER </header> </div> </div>
In this column, the md
in.col-md-12
means that for the viewport medium (which means the md
identifier), the column must have a 12-column width. In other words, the column fills the entire width of this row. This column will fill the complete width because it is our header, and as we can see in the previous image, this row is composed of just a single row.
So, to create a column in the Bootstrap grid system, you must follow the recipe of .col-*-*
for every column. While you can set an integer from 1
to 12
for the width, for the viewport, you must set the correct class prefix. In this table, you can see the breakdown of class prefix usage and on which resolution it can be used:
Extra small devices (phones < 544 px / 34 em) |
Small devices (tablets ≥ 544 px / 34 em and < 768 px / 48 em) |
Medium devices (desktops ≥ 768 px /48 em and < 900 px / 62 em) |
Large devices (desktops ≥ 900 px / 62 em and < 1,200 px 75 em) |
Extra large devices (desktops ≥ 1,200 px / 75 em) | |
---|---|---|---|---|---|
Grid behavior |
Horizontal lines at all times |
Collapse at start and fit the column grid | |||
Container's fixed width |
Auto |
|
|
|
|
Class prefix |
|
|
|
|
|
Number of columns |
12 | ||||
Column fixed width |
Auto |
|
|
|
|
Our second row is divided into three equal-sized columns, and the first one is an offset column, or in other words, an empty column that will be filled by a left margin. Therefore, the second row will be like this:
<div class="row"> <div class="col-md-offset-4 col-md-4">1/3</div> <div class="col-md-4">1/3</div> </div>
As you can see, by adding the .col-md-offset-4
class, we create a margin to the left four, sized in just this .row
. By having each row independent of the others, we can properly customize the layout to appear just as it is supposed to be.
Now we will advance to the third row in our scaffolding. If you've got the spirit, you should have no problems with this row. For training, try doing it by yourself and check the solution in the book afterwards! I am sure you can handle it.
So, this row is composed of two columns. The first column must fill 4 out of the 12 parts of the row and the other column will fill the rest. The row in the HTML should look like this:
<div class="row"> <div class="col-md-4"></div> <div class="col-md-8"></div> </div>
About the fourth row—it is composed of a quarter divisor, followed by a half divisor, followed by a last quarter divisor. Using this in base 12, we will have the following grid in the row:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6">1/2</div> <div class="col-md-3">1/4</div> </div>
In the fifth and sixth rows, we will show how you can create a row using two options. In the fifth row, we will create just as we are doing in the other rows, while in the sixth row, we will use the concept of nesting rows.
So, in the fifth row, create it just as you were doing before; create a row with four equally sized rows, which means that each column will have the .col-md-3
class:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div>
For the sixth row, we will use nesting rows. So, let's create the first .row
, having three columns:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"></div> <div class="col-md-3">1/4</div> </div>
As you can see, the first and the last column use the same class of columns in row five—the .col-md-3
class—while the middle column is double the size, with the .col-md-6
class.
Let's nest another .row
inside the middle column. When you create a new nested row, the columns inside of it are refreshed and you have another set of 12-sized columns to put inside it. So, inside this new row, create two columns with the .col-md-6
class to generate two columns representing a fourth of the row:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div>
The concept of nesting rows is pretty complex, since you can infinitely subdivide a row, although it is great to create small grid components inside your page that can be used in other locations.
To create the last row, we need to create the .col-md-2
column, followed by .col-md-7
and .col-md-3
. So, just create a row using the <footer>
tag with those columns. The complete scaffolding will be this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Landing page</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> <div class="container"> <!-- row 1 --> <div class="row"> <header class="col-md-12"> HEADER </header> </div> <!-- row 2 --> <div class="row"> <div class="col-md-offset-4 col-md-4">1/3</div> <div class="col-md-4">1/3</div> </div> <!-- row 3 --> <div class="row"> <div class="col-md-4"></div> <div class="col-md-8"></div> </div> <!-- row 4 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6">1/2</div> <div class="col-md-3">1/4</div> </div> <!-- row 5 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div> <!-- row 6 – nesting rows --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div> <!-- row 7 --> <footer class="row"> <div class="col-md-2">1/2</div> <div class="col-md-7">7/12</div> <div class="col-md-3">1/4</div> </footer> </div> <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
Offset columns
Our second row is divided into three equal-sized columns, and the first one is an offset column, or in other words, an empty column that will be filled by a left margin. Therefore, the second row will be like this:
<div class="row"> <div class="col-md-offset-4 col-md-4">1/3</div> <div class="col-md-4">1/3</div> </div>
As you can see, by adding the .col-md-offset-4
class, we create a margin to the left four, sized in just this .row
. By having each row independent of the others, we can properly customize the layout to appear just as it is supposed to be.
Now we will advance to the third row in our scaffolding. If you've got the spirit, you should have no problems with this row. For training, try doing it by yourself and check the solution in the book afterwards! I am sure you can handle it.
So, this row is composed of two columns. The first column must fill 4 out of the 12 parts of the row and the other column will fill the rest. The row in the HTML should look like this:
<div class="row"> <div class="col-md-4"></div> <div class="col-md-8"></div> </div>
About the fourth row—it is composed of a quarter divisor, followed by a half divisor, followed by a last quarter divisor. Using this in base 12, we will have the following grid in the row:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6">1/2</div> <div class="col-md-3">1/4</div> </div>
In the fifth and sixth rows, we will show how you can create a row using two options. In the fifth row, we will create just as we are doing in the other rows, while in the sixth row, we will use the concept of nesting rows.
So, in the fifth row, create it just as you were doing before; create a row with four equally sized rows, which means that each column will have the .col-md-3
class:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div>
For the sixth row, we will use nesting rows. So, let's create the first .row
, having three columns:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"></div> <div class="col-md-3">1/4</div> </div>
As you can see, the first and the last column use the same class of columns in row five—the .col-md-3
class—while the middle column is double the size, with the .col-md-6
class.
Let's nest another .row
inside the middle column. When you create a new nested row, the columns inside of it are refreshed and you have another set of 12-sized columns to put inside it. So, inside this new row, create two columns with the .col-md-6
class to generate two columns representing a fourth of the row:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div>
The concept of nesting rows is pretty complex, since you can infinitely subdivide a row, although it is great to create small grid components inside your page that can be used in other locations.
To create the last row, we need to create the .col-md-2
column, followed by .col-md-7
and .col-md-3
. So, just create a row using the <footer>
tag with those columns. The complete scaffolding will be this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Landing page</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> <div class="container"> <!-- row 1 --> <div class="row"> <header class="col-md-12"> HEADER </header> </div> <!-- row 2 --> <div class="row"> <div class="col-md-offset-4 col-md-4">1/3</div> <div class="col-md-4">1/3</div> </div> <!-- row 3 --> <div class="row"> <div class="col-md-4"></div> <div class="col-md-8"></div> </div> <!-- row 4 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6">1/2</div> <div class="col-md-3">1/4</div> </div> <!-- row 5 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div> <!-- row 6 – nesting rows --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div> <!-- row 7 --> <footer class="row"> <div class="col-md-2">1/2</div> <div class="col-md-7">7/12</div> <div class="col-md-3">1/4</div> </footer> </div> <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
Completing the grid rows
Now we will advance to the third row in our scaffolding. If you've got the spirit, you should have no problems with this row. For training, try doing it by yourself and check the solution in the book afterwards! I am sure you can handle it.
So, this row is composed of two columns. The first column must fill 4 out of the 12 parts of the row and the other column will fill the rest. The row in the HTML should look like this:
<div class="row"> <div class="col-md-4"></div> <div class="col-md-8"></div> </div>
About the fourth row—it is composed of a quarter divisor, followed by a half divisor, followed by a last quarter divisor. Using this in base 12, we will have the following grid in the row:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6">1/2</div> <div class="col-md-3">1/4</div> </div>
In the fifth and sixth rows, we will show how you can create a row using two options. In the fifth row, we will create just as we are doing in the other rows, while in the sixth row, we will use the concept of nesting rows.
So, in the fifth row, create it just as you were doing before; create a row with four equally sized rows, which means that each column will have the .col-md-3
class:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div>
For the sixth row, we will use nesting rows. So, let's create the first .row
, having three columns:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"></div> <div class="col-md-3">1/4</div> </div>
As you can see, the first and the last column use the same class of columns in row five—the .col-md-3
class—while the middle column is double the size, with the .col-md-6
class.
Let's nest another .row
inside the middle column. When you create a new nested row, the columns inside of it are refreshed and you have another set of 12-sized columns to put inside it. So, inside this new row, create two columns with the .col-md-6
class to generate two columns representing a fourth of the row:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div>
The concept of nesting rows is pretty complex, since you can infinitely subdivide a row, although it is great to create small grid components inside your page that can be used in other locations.
To create the last row, we need to create the .col-md-2
column, followed by .col-md-7
and .col-md-3
. So, just create a row using the <footer>
tag with those columns. The complete scaffolding will be this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Landing page</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> <div class="container"> <!-- row 1 --> <div class="row"> <header class="col-md-12"> HEADER </header> </div> <!-- row 2 --> <div class="row"> <div class="col-md-offset-4 col-md-4">1/3</div> <div class="col-md-4">1/3</div> </div> <!-- row 3 --> <div class="row"> <div class="col-md-4"></div> <div class="col-md-8"></div> </div> <!-- row 4 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6">1/2</div> <div class="col-md-3">1/4</div> </div> <!-- row 5 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div> <!-- row 6 – nesting rows --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div> <!-- row 7 --> <footer class="row"> <div class="col-md-2">1/2</div> <div class="col-md-7">7/12</div> <div class="col-md-3">1/4</div> </footer> </div> <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
Nesting rows
In the fifth and sixth rows, we will show how you can create a row using two options. In the fifth row, we will create just as we are doing in the other rows, while in the sixth row, we will use the concept of nesting rows.
So, in the fifth row, create it just as you were doing before; create a row with four equally sized rows, which means that each column will have the .col-md-3
class:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div>
For the sixth row, we will use nesting rows. So, let's create the first .row
, having three columns:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"></div> <div class="col-md-3">1/4</div> </div>
As you can see, the first and the last column use the same class of columns in row five—the .col-md-3
class—while the middle column is double the size, with the .col-md-6
class.
Let's nest another .row
inside the middle column. When you create a new nested row, the columns inside of it are refreshed and you have another set of 12-sized columns to put inside it. So, inside this new row, create two columns with the .col-md-6
class to generate two columns representing a fourth of the row:
<div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div>
The concept of nesting rows is pretty complex, since you can infinitely subdivide a row, although it is great to create small grid components inside your page that can be used in other locations.
To create the last row, we need to create the .col-md-2
column, followed by .col-md-7
and .col-md-3
. So, just create a row using the <footer>
tag with those columns. The complete scaffolding will be this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Landing page</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> <div class="container"> <!-- row 1 --> <div class="row"> <header class="col-md-12"> HEADER </header> </div> <!-- row 2 --> <div class="row"> <div class="col-md-offset-4 col-md-4">1/3</div> <div class="col-md-4">1/3</div> </div> <!-- row 3 --> <div class="row"> <div class="col-md-4"></div> <div class="col-md-8"></div> </div> <!-- row 4 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6">1/2</div> <div class="col-md-3">1/4</div> </div> <!-- row 5 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div> <!-- row 6 – nesting rows --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div> <!-- row 7 --> <footer class="row"> <div class="col-md-2">1/2</div> <div class="col-md-7">7/12</div> <div class="col-md-3">1/4</div> </footer> </div> <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
Finishing the grid
To create the last row, we need to create the .col-md-2
column, followed by .col-md-7
and .col-md-3
. So, just create a row using the <footer>
tag with those columns. The complete scaffolding will be this:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Landing page</title> <link rel="stylesheet" href="css/bootstrap.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> <div class="container"> <!-- row 1 --> <div class="row"> <header class="col-md-12"> HEADER </header> </div> <!-- row 2 --> <div class="row"> <div class="col-md-offset-4 col-md-4">1/3</div> <div class="col-md-4">1/3</div> </div> <!-- row 3 --> <div class="row"> <div class="col-md-4"></div> <div class="col-md-8"></div> </div> <!-- row 4 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6">1/2</div> <div class="col-md-3">1/4</div> </div> <!-- row 5 --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> <div class="col-md-3">1/4</div> </div> <!-- row 6 – nesting rows --> <div class="row"> <div class="col-md-3">1/4</div> <div class="col-md-6"> <div class="row"> <div class="col-md-6">1/4</div> <div class="col-md-6">1/4</div> </div> </div> <div class="col-md-3">1/4</div> </div> <!-- row 7 --> <footer class="row"> <div class="col-md-2">1/2</div> <div class="col-md-7">7/12</div> <div class="col-md-3">1/4</div> </footer> </div> <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> </body> </html>
You can easily switch the actual example grid with a fluid full-width layout. To do so, replace the farthest .container
with .container-fluid
:
<div class="container-fluid"> … </div>
Now, we will start using some of the CSS provided for Bootstrap to make our components responsive and more elegant. Our main goal is to make our grid page like what is shown in this screenshot:

Let's break down each row and learn about typography and some other components. We will do this without using a single custom line of CSS!
Getting started with the first row, you may see that this row has a gray background, which is not present in the rest of the layout. To create this, we must make a change in our grid by creating a new .container
for this row. So, create another .container
and place it inside the first row:
<div class="container"> <!-- row 1 --> <div class="row"> <header class="col-md-12"> </header> </div> </div> <div class="container"> <!—- the others rows (2 to 7) --> </div>
Now, to make the gray area, we will use a class in Bootstrap called .jumbotron
. The jumbotron
is a flexible Bootstrap component that can extend to the entire viewport to showcase some content, in this case the header. So, wrap the container inside a div.jumbotron
:
<div class="jumbotron"> <div class="container"> <!-- row 1 --> <div class="row"> <header class="col-md-12"> </header> </div> </div> </div>
Inside the header, as we can see in the layout, we must create a title, a subtitle, and a button. For the title, let's use the <h1>
and <h2>
heading elements. For the button, let's create a link with the .btn
, .btn-default
, and .btn-lg
classes. We will mention more about these components in the next subsections:
<div class="jumbotron"> <div class="container"> <!-- row 1 --> <div class="row"> <header class="col-md-12"> <h1>A simple landing page example</h1> <h2>Sub title for support</h2> <a class="btn btn-default btn-lg" href="#" role="button"> Link </a> </header> </div> </div> </div>
Bootstrap provides styled headings from h1
to h6
. You should always use them in order of importance, from <h1>
to <h6>
(the least important).
Tip
Do you know why headings are important?
Heading are very important for Search Engine Optimization (SEO). They suggest for search engines what is important in your page context. You must keep the hierarchy for page coherence, and do not skip any tag (that is, jump from heading 3 to heading 5). Otherwise, the structure will be broken and not relevant for SEO.
The heading has classes for identifying its style. So, if your most important phrase is not the biggest one at times, you can swap the sizes by adding heading classes, just as in the following example:
<h1 class="h3">Heading 1 styled as heading 3</h1> <h2 class="h1">Heading 2 styled as heading 1</h2> <h3 class="h2">Heading 3 styled as heading 2</h3>

The other element of the first row is a button! We can apply button classes for hyperlinks, button elements, and inputs. To make one of these elements a button, just add the .btn
class followed by the kind of button, in this case the kind .btn-default
, which is a blue button. The next table shows every possibility of color classes for a button:
Button class |
Output |
---|---|
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
We have also added the .btn-lg
class in the first row button. This class will increase the size of the button. Bootstrap also provides some other button size classes, such as .btn-sm
for small buttons and .btn-xs
for even smaller ones.
You can also make a button span the full width of the parent element with the .btn-block
class, changing the display of the button to block
.
With regards to the second row, we have a row that contains a heading and complementary small text after that.
To add lighter and secondary text to the heading, we can add a <small>
tag or any other tag with the .small
class inside the heading. The HTML for the first column in the second row should be like the following:
<div class="row"> <div class="col-md-offset-4 col-md-4"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4"> <h3> Add to your favorites <small> <kbd><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
Note that inside the small tag, we have added a <kbd>
tag, which is an HTML element that creates a user-like input keyboard. Refresh the web browser and you will see this row as shown here:

For the third row, we have a code snippet and an image. To create a code snippet, use the <pre>
tag for multiple lines of code. The <pre>
tag is present in HTML for creating preformatted text, such as a code snippet. You have the option of adding the .pre-scrollable
class, which will add a scrollbar if the code snippet reaches the maximum height of 350 px (or 21.8 em).
For this row, in the right column, we have an image. For that, just create an <img>
tag and add the .img-responsive
class, which will make the images automatically responsive-friendly to the viewport. The HTML for the third row is as follows:
<div class="row"> <div class="col-md-3"> <pre><p>I love programming!</p> <p>This paragraph is on my landing page</p> <br/> <br/> <p>Bootstrap by example</p> </pre> </div> <div class="col-md-9"> <img src="imgs/center.png" class="img-responsive"> </div> </div>
Refresh your browser and you will see the result of this row as shown in the following screenshot:

In the fourth row, we have images in both the left and right columns and a testimonial in the middle. Bootstrap provides a typographic theme for doing block quotes, so just create a <blockquote>
tag. Inside it, create a <footer>
tag to identify the source, and wrap the name in a <cite>
tag, like this:
<div class="row"> <div class="col-md-3"> <img src="imgs/bs.png" class="img-responsive"> </div> <div class="col-md-6"> <blockquote> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> <footer>Testimonial from someone at <cite title="Source Title">Source Title</cite></footer> </blockquote> </div> <div class="col-md-3"> <img src="imgs/packt.png" class="img-responsive"> </div> </div>

Moving on, we must advance to the fifth row. This row is here just to show the different ways in which we can apply typography and coding elements tags using Bootstrap. Let's go through each one to describe its usage.
In the first column, we have a piece of inline code. To do that, wrap the snippet in a <code>
tag. From the first to the fourth column of this row, we are presenting the alignment classes. Using these, you can easily realign text content in a paragraph tag. The code for the row is as follows:
<div class="row"> <div class="col-md-3"> <p class="text-left"><code><Left></code></p> </div> <div class="col-md-3"> <p class="text-center">Center</p> </div> <div class="col-md-3"> <p class="text-justify">Justify</p> </div> <div class="col-md-3"> <p class="text-right">Right</p> </div> </div>
Just use the right classes for a proper alignment. The result in the browser should look like this:

The sixth row is composed of four equally divided columns, but in this case, we are using the nesting rows option. On the first three columns, we added Bootstrap text transformation classes to make the text lowercase, uppercase, and capitalized, respectively. The code for this row should be like the following:
<div class="row"> <div class="col-md-3"> <h3>Lowercase</h3> <p class="text-lowercase"> Lorem ipsum dolor ... consequat. </p> </div> <div class="col-md-6"> <div class="row"> <div class="col-md-6"> <h3>Uppercase</h3> <p class="text-uppercase"> Lorem ipsum dolor ... consequat. </p> </div> <div class="col-md-6"> <h3>Capitalize</h3> <p class="text-capitalize"> Lorem ipsum dolor ... consequat. </p> </div> </div> </div> <div class="col-md-3"> <h3>Strong and italic</h3> <p> <strong>Lorem ipsum</strong> dolor ... <em>consequat</em>. </p> </div> </div>
Pay attention to the last column, where we are using the <strong>
tags to make the text bold and the <em>
tag to make the text italic. Refresh your web browser and see the result, like this:

Finally, we are going through the footer, which is the last row. If you take a look at the full layout image (the one presented at the beginning of this section), you will notice that it is composed of three columns. The first column contains a logo image, the middle one contains an inline list, and the last one has the company's contact address.
For the first column, we should just create an <img>
tag with the .img-responsive
class. For the second column, the inline list, we must create a <ul>
tag. By default, every <li>
inside a <ul>
has the bullets on the left-hand side. To remove them, apply the .unstyled
Bootstrap class. Also, a <ul>
will create the <li>
elements as a block. In our case, we want the <li>
to appear side by side, so we use the .list-inline
Bootstrap class to create this effect.
To present contact information in the last column, we will use the <address>
tag. Bootstrap offers a CSS theme for this tag; you just need to keep the formatting along with the <br>
tags, as shown in this code:
<footer class="row jumbotron"> <div class="col-md-2"> <img src="imgs/logo.png" class="img-responsive"> </div> <div class="col-md-7"> <ul class="list-inline list-unstyled"> <li><a href="#">Documentation</a></li> <li><a href="#">Packt publisher</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Bootstrap</a></li> <li><a href="#">Contact</a></li> </ul> </div> <div class="col-md-3"> <address> <strong>Name, Inc.</strong><br> Address line 1<br> Address line 2<br> <abbr title="Phone">P:</abbr> (123) 456-7890 </address> </div> </footer>
Pay attention to the <footer>
tag. We added the .jumbotron
class to make it rounded and give it a gray background. The following screenshot presents to us the result of the footer:

There are headings everywhere
Bootstrap provides styled headings from h1
to h6
. You should always use them in order of importance, from <h1>
to <h6>
(the least important).
Tip
Do you know why headings are important?
Heading are very important for Search Engine Optimization (SEO). They suggest for search engines what is important in your page context. You must keep the hierarchy for page coherence, and do not skip any tag (that is, jump from heading 3 to heading 5). Otherwise, the structure will be broken and not relevant for SEO.
The heading has classes for identifying its style. So, if your most important phrase is not the biggest one at times, you can swap the sizes by adding heading classes, just as in the following example:
<h1 class="h3">Heading 1 styled as heading 3</h1> <h2 class="h1">Heading 2 styled as heading 1</h2> <h3 class="h2">Heading 3 styled as heading 2</h3>

The other element of the first row is a button! We can apply button classes for hyperlinks, button elements, and inputs. To make one of these elements a button, just add the .btn
class followed by the kind of button, in this case the kind .btn-default
, which is a blue button. The next table shows every possibility of color classes for a button:
Button class |
Output |
---|---|
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
We have also added the .btn-lg
class in the first row button. This class will increase the size of the button. Bootstrap also provides some other button size classes, such as .btn-sm
for small buttons and .btn-xs
for even smaller ones.
You can also make a button span the full width of the parent element with the .btn-block
class, changing the display of the button to block
.
With regards to the second row, we have a row that contains a heading and complementary small text after that.
To add lighter and secondary text to the heading, we can add a <small>
tag or any other tag with the .small
class inside the heading. The HTML for the first column in the second row should be like the following:
<div class="row"> <div class="col-md-offset-4 col-md-4"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4"> <h3> Add to your favorites <small> <kbd><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
Note that inside the small tag, we have added a <kbd>
tag, which is an HTML element that creates a user-like input keyboard. Refresh the web browser and you will see this row as shown here:

For the third row, we have a code snippet and an image. To create a code snippet, use the <pre>
tag for multiple lines of code. The <pre>
tag is present in HTML for creating preformatted text, such as a code snippet. You have the option of adding the .pre-scrollable
class, which will add a scrollbar if the code snippet reaches the maximum height of 350 px (or 21.8 em).
For this row, in the right column, we have an image. For that, just create an <img>
tag and add the .img-responsive
class, which will make the images automatically responsive-friendly to the viewport. The HTML for the third row is as follows:
<div class="row"> <div class="col-md-3"> <pre><p>I love programming!</p> <p>This paragraph is on my landing page</p> <br/> <br/> <p>Bootstrap by example</p> </pre> </div> <div class="col-md-9"> <img src="imgs/center.png" class="img-responsive"> </div> </div>
Refresh your browser and you will see the result of this row as shown in the following screenshot:

In the fourth row, we have images in both the left and right columns and a testimonial in the middle. Bootstrap provides a typographic theme for doing block quotes, so just create a <blockquote>
tag. Inside it, create a <footer>
tag to identify the source, and wrap the name in a <cite>
tag, like this:
<div class="row"> <div class="col-md-3"> <img src="imgs/bs.png" class="img-responsive"> </div> <div class="col-md-6"> <blockquote> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> <footer>Testimonial from someone at <cite title="Source Title">Source Title</cite></footer> </blockquote> </div> <div class="col-md-3"> <img src="imgs/packt.png" class="img-responsive"> </div> </div>

Moving on, we must advance to the fifth row. This row is here just to show the different ways in which we can apply typography and coding elements tags using Bootstrap. Let's go through each one to describe its usage.
In the first column, we have a piece of inline code. To do that, wrap the snippet in a <code>
tag. From the first to the fourth column of this row, we are presenting the alignment classes. Using these, you can easily realign text content in a paragraph tag. The code for the row is as follows:
<div class="row"> <div class="col-md-3"> <p class="text-left"><code><Left></code></p> </div> <div class="col-md-3"> <p class="text-center">Center</p> </div> <div class="col-md-3"> <p class="text-justify">Justify</p> </div> <div class="col-md-3"> <p class="text-right">Right</p> </div> </div>
Just use the right classes for a proper alignment. The result in the browser should look like this:

The sixth row is composed of four equally divided columns, but in this case, we are using the nesting rows option. On the first three columns, we added Bootstrap text transformation classes to make the text lowercase, uppercase, and capitalized, respectively. The code for this row should be like the following:
<div class="row"> <div class="col-md-3"> <h3>Lowercase</h3> <p class="text-lowercase"> Lorem ipsum dolor ... consequat. </p> </div> <div class="col-md-6"> <div class="row"> <div class="col-md-6"> <h3>Uppercase</h3> <p class="text-uppercase"> Lorem ipsum dolor ... consequat. </p> </div> <div class="col-md-6"> <h3>Capitalize</h3> <p class="text-capitalize"> Lorem ipsum dolor ... consequat. </p> </div> </div> </div> <div class="col-md-3"> <h3>Strong and italic</h3> <p> <strong>Lorem ipsum</strong> dolor ... <em>consequat</em>. </p> </div> </div>
Pay attention to the last column, where we are using the <strong>
tags to make the text bold and the <em>
tag to make the text italic. Refresh your web browser and see the result, like this:

Finally, we are going through the footer, which is the last row. If you take a look at the full layout image (the one presented at the beginning of this section), you will notice that it is composed of three columns. The first column contains a logo image, the middle one contains an inline list, and the last one has the company's contact address.
For the first column, we should just create an <img>
tag with the .img-responsive
class. For the second column, the inline list, we must create a <ul>
tag. By default, every <li>
inside a <ul>
has the bullets on the left-hand side. To remove them, apply the .unstyled
Bootstrap class. Also, a <ul>
will create the <li>
elements as a block. In our case, we want the <li>
to appear side by side, so we use the .list-inline
Bootstrap class to create this effect.
To present contact information in the last column, we will use the <address>
tag. Bootstrap offers a CSS theme for this tag; you just need to keep the formatting along with the <br>
tags, as shown in this code:
<footer class="row jumbotron"> <div class="col-md-2"> <img src="imgs/logo.png" class="img-responsive"> </div> <div class="col-md-7"> <ul class="list-inline list-unstyled"> <li><a href="#">Documentation</a></li> <li><a href="#">Packt publisher</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Bootstrap</a></li> <li><a href="#">Contact</a></li> </ul> </div> <div class="col-md-3"> <address> <strong>Name, Inc.</strong><br> Address line 1<br> Address line 2<br> <abbr title="Phone">P:</abbr> (123) 456-7890 </address> </div> </footer>
Pay attention to the <footer>
tag. We added the .jumbotron
class to make it rounded and give it a gray background. The following screenshot presents to us the result of the footer:

Playing with buttons
The other element of the first row is a button! We can apply button classes for hyperlinks, button elements, and inputs. To make one of these elements a button, just add the .btn
class followed by the kind of button, in this case the kind .btn-default
, which is a blue button. The next table shows every possibility of color classes for a button:
Button class |
Output |
---|---|
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
We have also added the .btn-lg
class in the first row button. This class will increase the size of the button. Bootstrap also provides some other button size classes, such as .btn-sm
for small buttons and .btn-xs
for even smaller ones.
You can also make a button span the full width of the parent element with the .btn-block
class, changing the display of the button to block
.
With regards to the second row, we have a row that contains a heading and complementary small text after that.
To add lighter and secondary text to the heading, we can add a <small>
tag or any other tag with the .small
class inside the heading. The HTML for the first column in the second row should be like the following:
<div class="row"> <div class="col-md-offset-4 col-md-4"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4"> <h3> Add to your favorites <small> <kbd><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
Note that inside the small tag, we have added a <kbd>
tag, which is an HTML element that creates a user-like input keyboard. Refresh the web browser and you will see this row as shown here:

For the third row, we have a code snippet and an image. To create a code snippet, use the <pre>
tag for multiple lines of code. The <pre>
tag is present in HTML for creating preformatted text, such as a code snippet. You have the option of adding the .pre-scrollable
class, which will add a scrollbar if the code snippet reaches the maximum height of 350 px (or 21.8 em).
For this row, in the right column, we have an image. For that, just create an <img>
tag and add the .img-responsive
class, which will make the images automatically responsive-friendly to the viewport. The HTML for the third row is as follows:
<div class="row"> <div class="col-md-3"> <pre><p>I love programming!</p> <p>This paragraph is on my landing page</p> <br/> <br/> <p>Bootstrap by example</p> </pre> </div> <div class="col-md-9"> <img src="imgs/center.png" class="img-responsive"> </div> </div>
Refresh your browser and you will see the result of this row as shown in the following screenshot:

In the fourth row, we have images in both the left and right columns and a testimonial in the middle. Bootstrap provides a typographic theme for doing block quotes, so just create a <blockquote>
tag. Inside it, create a <footer>
tag to identify the source, and wrap the name in a <cite>
tag, like this:
<div class="row"> <div class="col-md-3"> <img src="imgs/bs.png" class="img-responsive"> </div> <div class="col-md-6"> <blockquote> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> <footer>Testimonial from someone at <cite title="Source Title">Source Title</cite></footer> </blockquote> </div> <div class="col-md-3"> <img src="imgs/packt.png" class="img-responsive"> </div> </div>

Moving on, we must advance to the fifth row. This row is here just to show the different ways in which we can apply typography and coding elements tags using Bootstrap. Let's go through each one to describe its usage.
In the first column, we have a piece of inline code. To do that, wrap the snippet in a <code>
tag. From the first to the fourth column of this row, we are presenting the alignment classes. Using these, you can easily realign text content in a paragraph tag. The code for the row is as follows:
<div class="row"> <div class="col-md-3"> <p class="text-left"><code><Left></code></p> </div> <div class="col-md-3"> <p class="text-center">Center</p> </div> <div class="col-md-3"> <p class="text-justify">Justify</p> </div> <div class="col-md-3"> <p class="text-right">Right</p> </div> </div>
Just use the right classes for a proper alignment. The result in the browser should look like this:

The sixth row is composed of four equally divided columns, but in this case, we are using the nesting rows option. On the first three columns, we added Bootstrap text transformation classes to make the text lowercase, uppercase, and capitalized, respectively. The code for this row should be like the following:
<div class="row"> <div class="col-md-3"> <h3>Lowercase</h3> <p class="text-lowercase"> Lorem ipsum dolor ... consequat. </p> </div> <div class="col-md-6"> <div class="row"> <div class="col-md-6"> <h3>Uppercase</h3> <p class="text-uppercase"> Lorem ipsum dolor ... consequat. </p> </div> <div class="col-md-6"> <h3>Capitalize</h3> <p class="text-capitalize"> Lorem ipsum dolor ... consequat. </p> </div> </div> </div> <div class="col-md-3"> <h3>Strong and italic</h3> <p> <strong>Lorem ipsum</strong> dolor ... <em>consequat</em>. </p> </div> </div>
Pay attention to the last column, where we are using the <strong>
tags to make the text bold and the <em>
tag to make the text italic. Refresh your web browser and see the result, like this:

Finally, we are going through the footer, which is the last row. If you take a look at the full layout image (the one presented at the beginning of this section), you will notice that it is composed of three columns. The first column contains a logo image, the middle one contains an inline list, and the last one has the company's contact address.
For the first column, we should just create an <img>
tag with the .img-responsive
class. For the second column, the inline list, we must create a <ul>
tag. By default, every <li>
inside a <ul>
has the bullets on the left-hand side. To remove them, apply the .unstyled
Bootstrap class. Also, a <ul>
will create the <li>
elements as a block. In our case, we want the <li>
to appear side by side, so we use the .list-inline
Bootstrap class to create this effect.
To present contact information in the last column, we will use the <address>
tag. Bootstrap offers a CSS theme for this tag; you just need to keep the formatting along with the <br>
tags, as shown in this code:
<footer class="row jumbotron"> <div class="col-md-2"> <img src="imgs/logo.png" class="img-responsive"> </div> <div class="col-md-7"> <ul class="list-inline list-unstyled"> <li><a href="#">Documentation</a></li> <li><a href="#">Packt publisher</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Bootstrap</a></li> <li><a href="#">Contact</a></li> </ul> </div> <div class="col-md-3"> <address> <strong>Name, Inc.</strong><br> Address line 1<br> Address line 2<br> <abbr title="Phone">P:</abbr> (123) 456-7890 </address> </div> </footer>
Pay attention to the <footer>
tag. We added the .jumbotron
class to make it rounded and give it a gray background. The following screenshot presents to us the result of the footer:

More typography and code tags
With regards to the second row, we have a row that contains a heading and complementary small text after that.
To add lighter and secondary text to the heading, we can add a <small>
tag or any other tag with the .small
class inside the heading. The HTML for the first column in the second row should be like the following:
<div class="row"> <div class="col-md-offset-4 col-md-4"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4"> <h3> Add to your favorites <small> <kbd><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
Note that inside the small tag, we have added a <kbd>
tag, which is an HTML element that creates a user-like input keyboard. Refresh the web browser and you will see this row as shown here:

For the third row, we have a code snippet and an image. To create a code snippet, use the <pre>
tag for multiple lines of code. The <pre>
tag is present in HTML for creating preformatted text, such as a code snippet. You have the option of adding the .pre-scrollable
class, which will add a scrollbar if the code snippet reaches the maximum height of 350 px (or 21.8 em).
For this row, in the right column, we have an image. For that, just create an <img>
tag and add the .img-responsive
class, which will make the images automatically responsive-friendly to the viewport. The HTML for the third row is as follows:
<div class="row"> <div class="col-md-3"> <pre><p>I love programming!</p> <p>This paragraph is on my landing page</p> <br/> <br/> <p>Bootstrap by example</p> </pre> </div> <div class="col-md-9"> <img src="imgs/center.png" class="img-responsive"> </div> </div>
Refresh your browser and you will see the result of this row as shown in the following screenshot:

In the fourth row, we have images in both the left and right columns and a testimonial in the middle. Bootstrap provides a typographic theme for doing block quotes, so just create a <blockquote>
tag. Inside it, create a <footer>
tag to identify the source, and wrap the name in a <cite>
tag, like this:
<div class="row"> <div class="col-md-3"> <img src="imgs/bs.png" class="img-responsive"> </div> <div class="col-md-6"> <blockquote> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> <footer>Testimonial from someone at <cite title="Source Title">Source Title</cite></footer> </blockquote> </div> <div class="col-md-3"> <img src="imgs/packt.png" class="img-responsive"> </div> </div>

Moving on, we must advance to the fifth row. This row is here just to show the different ways in which we can apply typography and coding elements tags using Bootstrap. Let's go through each one to describe its usage.
In the first column, we have a piece of inline code. To do that, wrap the snippet in a <code>
tag. From the first to the fourth column of this row, we are presenting the alignment classes. Using these, you can easily realign text content in a paragraph tag. The code for the row is as follows:
<div class="row"> <div class="col-md-3"> <p class="text-left"><code><Left></code></p> </div> <div class="col-md-3"> <p class="text-center">Center</p> </div> <div class="col-md-3"> <p class="text-justify">Justify</p> </div> <div class="col-md-3"> <p class="text-right">Right</p> </div> </div>
Just use the right classes for a proper alignment. The result in the browser should look like this:

The sixth row is composed of four equally divided columns, but in this case, we are using the nesting rows option. On the first three columns, we added Bootstrap text transformation classes to make the text lowercase, uppercase, and capitalized, respectively. The code for this row should be like the following:
<div class="row"> <div class="col-md-3"> <h3>Lowercase</h3> <p class="text-lowercase"> Lorem ipsum dolor ... consequat. </p> </div> <div class="col-md-6"> <div class="row"> <div class="col-md-6"> <h3>Uppercase</h3> <p class="text-uppercase"> Lorem ipsum dolor ... consequat. </p> </div> <div class="col-md-6"> <h3>Capitalize</h3> <p class="text-capitalize"> Lorem ipsum dolor ... consequat. </p> </div> </div> </div> <div class="col-md-3"> <h3>Strong and italic</h3> <p> <strong>Lorem ipsum</strong> dolor ... <em>consequat</em>. </p> </div> </div>
Pay attention to the last column, where we are using the <strong>
tags to make the text bold and the <em>
tag to make the text italic. Refresh your web browser and see the result, like this:

Finally, we are going through the footer, which is the last row. If you take a look at the full layout image (the one presented at the beginning of this section), you will notice that it is composed of three columns. The first column contains a logo image, the middle one contains an inline list, and the last one has the company's contact address.
For the first column, we should just create an <img>
tag with the .img-responsive
class. For the second column, the inline list, we must create a <ul>
tag. By default, every <li>
inside a <ul>
has the bullets on the left-hand side. To remove them, apply the .unstyled
Bootstrap class. Also, a <ul>
will create the <li>
elements as a block. In our case, we want the <li>
to appear side by side, so we use the .list-inline
Bootstrap class to create this effect.
To present contact information in the last column, we will use the <address>
tag. Bootstrap offers a CSS theme for this tag; you just need to keep the formatting along with the <br>
tags, as shown in this code:
<footer class="row jumbotron"> <div class="col-md-2"> <img src="imgs/logo.png" class="img-responsive"> </div> <div class="col-md-7"> <ul class="list-inline list-unstyled"> <li><a href="#">Documentation</a></li> <li><a href="#">Packt publisher</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Bootstrap</a></li> <li><a href="#">Contact</a></li> </ul> </div> <div class="col-md-3"> <address> <strong>Name, Inc.</strong><br> Address line 1<br> Address line 2<br> <abbr title="Phone">P:</abbr> (123) 456-7890 </address> </div> </footer>
Pay attention to the <footer>
tag. We added the .jumbotron
class to make it rounded and give it a gray background. The following screenshot presents to us the result of the footer:

The Bootstrap framework offers a wide variety for table customization. To present them, we will create a new row before the <footer>
and a price table for our landing page, like this:

To do this, we must create a regular table with the <table>
, <thead>
, <tbody>
, <tr>
, <th>
, and <td>
tags. The table will have three columns and eight rows. Therefore, the HTML code should be like this:
<div class="row"> <div class="col-md-10 col-md-offset-1"> <table> <thead> <tr> <th> <h4>Free plan</h4> </th> <th> <h4>Standard plan</h4> </th> <th> <h4>Premium plan</h4> </th> </tr> </thead> <tbody> <tr> <td> <h3>$ 0</h3> </td> <td> <h3>$ 99</h3> </td> <td> <h3>$ 999</h3> </td> </tr> <tr> <td>Lorem ipsum</td> <td>Lorem ipsum</td> <td>Lorem ipsum</td> </tr> <tr> <td>Lorem ipsum</td> <td>Lorem ipsum</td> <td>Lorem ipsum</td> </tr> <tr> <td>Dolor sit amet</td> <td>Lorem ipsum</td> <td>Lorem ipsum</td> </tr> <tr> <td>-</td> <td>Dolor sit amet</td> <td>Lorem ipsum</td> </tr> <tr> <td>-</td> <td>-</td> <td>Lorem ipsum</td> </tr> <tr> <td><a href="#">Purchase</a></td> <td><a href="#">Purchase</a></td> <td><a href="#">Purchase</a></td> </tr> </tbody> </table> </div> </div>
Right now, we have no secrets in our table. Let's start using CSS Bootstrap styles! First of all, add the .table
class to the <table>
tag (duh!). This seems redundant, but it's an option of the framework used to make it explicit.
Then, we will apply some specific styles. To make the rows striped, we add the .table-striped
class to <table>
as well. We want this table to have borders, so we add the .table-bordered
class to make it like that. Last but not least, add the .table-hover
class to enable hover state in the <tbody>
rows.
Now we will move on to the <tr>
tag inside <thead>
. To make its background green, we add the .success
class. Similar to buttons, every cell, row, or table in a <table>
tag can receive color classes, officially called Bootstrap contextual classes.
Contextual classes follow the same colors meant for buttons. So, for the second column, we apply the .info
class to get a cyan background color, and we use a .danger
class to get a red background color in the last column.
Inside each <th>
tag, we have an <h4>
typography tag. If you take a look at the image showing how the table should look, you will notice that the heading texts are in the center. You may remember how to do that; just apply the .text-center
class in the headings.
The themed <thead>
tag will be like this:
<thead> <tr> <th class="success"> <h4 class="text-center">Free plan</h4> </th> <th class="info"> <h4 class="text-center">Standard plan</h4> </th> <th class="danger"> <h4 class="text-center">Premium plan</h4> </th> </tr> </thead>
Now we will move on to the first table row in <tbody>
, which is the price row. We just need to center <h4>
in the same way as we did in the <thead>
row—by adding the .text-center
class:
<h3 class="text-center">$ 0</h3>
The next five rows have no specific style, but the last one has buttons and some tricks!
Do you remember how to apply the color theme in the buttons? You just need to follow the <thead>
column color style, prepending .btn-*
in the Bootstrap contextual classes. For instance, the first one will have the .btn-success
class to turn a green button.
Furthermore, the button must fill the full width of the cell. To make the button span the complete parent width, add the .btn-block
class and the magic is completely done! The code for the last row is as follows:
<tr> <td><a href="#" class="btn btn-success btn-block">Purchase</a></td> <td><a href="#" class="btn btn-info btn-block">Purchase</a></td> <td><a href="#" class="btn btn-danger btn-block">Purchase</a></td> </tr>
Styling the buttons
Do you remember how to apply the color theme in the buttons? You just need to follow the <thead>
column color style, prepending .btn-*
in the Bootstrap contextual classes. For instance, the first one will have the .btn-success
class to turn a green button.
Furthermore, the button must fill the full width of the cell. To make the button span the complete parent width, add the .btn-block
class and the magic is completely done! The code for the last row is as follows:
<tr> <td><a href="#" class="btn btn-success btn-block">Purchase</a></td> <td><a href="#" class="btn btn-info btn-block">Purchase</a></td> <td><a href="#" class="btn btn-danger btn-block">Purchase</a></td> </tr>
Right now, we have finished the first version of our landing page! It should look like what is shown in the next screenshot. Note that we did it without a single line of custom CSS!:

This is the power of Bootstrap. Can you feel it? You can do beautiful things very quickly. Bootstrap is a must-have tool for prototyping!
Change the viewport of your page by resizing the window and you will see how nicely Bootstrap adapts to any resolution. You don't have to worry about it if you have done a great job at making the grid and placing the elements.
Before ending this chapter, we must get some things clear. Bootstrap offers some helper classes mixins and some vendor's mixins, which offer cross-browser compatibility support.
Bootstrap 3 started using box-sizing: border-box
for all elements and pseudo-elements. With this enabled, the width and height properties start to include the padding and the border but not the margin.
With that, it is easier to set the right sizing for your elements. This is because any change that you make in the element, such as customizing the padding of a .row
, will reflect the width and height of the whole element. The following figure shows you the differences of box-sizing.

Bootstrap offers quick classes to make an element float. Add the .pull-left
or .pull-right
class to make the elements float left or right, respectively. Keep in mind that both classes apply the !important
modifier to avoid override issues:
<div class="pull-left"></div> <div class="pull-right"></div>
Clearfix is a way of clearing the floating of an element related to its child element. The Bootstrap columns are all floated left, and the parent row has a clearfix. This makes every column appear right next to each other, and the row does not overlap with other rows. This figure exemplifies how clearfix works:

So, if you want to add the clearfix to a new element or pseudo-element, add the .clearfix
class and you can get the hard work quickly done.
In the following table, the font sizes for default text and heading are presented. It describes the heading, font family, and line height. It is important to make it explicit for you to deeply understand the Bootstrap default configuration if you want a different customization.
CSS option |
Default value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Box-sizing
Bootstrap 3 started using box-sizing: border-box
for all elements and pseudo-elements. With this enabled, the width and height properties start to include the padding and the border but not the margin.
With that, it is easier to set the right sizing for your elements. This is because any change that you make in the element, such as customizing the padding of a .row
, will reflect the width and height of the whole element. The following figure shows you the differences of box-sizing.

Bootstrap offers quick classes to make an element float. Add the .pull-left
or .pull-right
class to make the elements float left or right, respectively. Keep in mind that both classes apply the !important
modifier to avoid override issues:
<div class="pull-left"></div> <div class="pull-right"></div>
Clearfix is a way of clearing the floating of an element related to its child element. The Bootstrap columns are all floated left, and the parent row has a clearfix. This makes every column appear right next to each other, and the row does not overlap with other rows. This figure exemplifies how clearfix works:

So, if you want to add the clearfix to a new element or pseudo-element, add the .clearfix
class and you can get the hard work quickly done.
In the following table, the font sizes for default text and heading are presented. It describes the heading, font family, and line height. It is important to make it explicit for you to deeply understand the Bootstrap default configuration if you want a different customization.
CSS option |
Default value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Quick floats
Bootstrap offers quick classes to make an element float. Add the .pull-left
or .pull-right
class to make the elements float left or right, respectively. Keep in mind that both classes apply the !important
modifier to avoid override issues:
<div class="pull-left"></div> <div class="pull-right"></div>
Clearfix is a way of clearing the floating of an element related to its child element. The Bootstrap columns are all floated left, and the parent row has a clearfix. This makes every column appear right next to each other, and the row does not overlap with other rows. This figure exemplifies how clearfix works:

So, if you want to add the clearfix to a new element or pseudo-element, add the .clearfix
class and you can get the hard work quickly done.
In the following table, the font sizes for default text and heading are presented. It describes the heading, font family, and line height. It is important to make it explicit for you to deeply understand the Bootstrap default configuration if you want a different customization.
CSS option |
Default value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Clearfix
Clearfix is a way of clearing the floating of an element related to its child element. The Bootstrap columns are all floated left, and the parent row has a clearfix. This makes every column appear right next to each other, and the row does not overlap with other rows. This figure exemplifies how clearfix works:

So, if you want to add the clearfix to a new element or pseudo-element, add the .clearfix
class and you can get the hard work quickly done.
In the following table, the font sizes for default text and heading are presented. It describes the heading, font family, and line height. It is important to make it explicit for you to deeply understand the Bootstrap default configuration if you want a different customization.
CSS option |
Default value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Font definitions for typography
In the following table, the font sizes for default text and heading are presented. It describes the heading, font family, and line height. It is important to make it explicit for you to deeply understand the Bootstrap default configuration if you want a different customization.
CSS option |
Default value |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In this chapter, we started our example of creating a landing page. By now, we can create a beautiful page without a single line of CSS or JavaScript!
First, we were able to reveal the secrets behind Bootstrap's scaffolding and understand its proper usage. You learned how to set rows inside a container, columns inside rows, and settings classes for a specific viewport. We played some tricks on columns as well, making nested rows, offsetting columns, and using multiple containers.
The basis of scaffolding will be important throughout the book, and it is in fact the basis of the Bootstrap framework. The power to manipulate it is a key factor in understanding the framework. I advise you to try out some new combinations of rows in your landing page and see what happens. Further in this book, we will show you some other grid combinations and custom layouts.
Furthermore, we played with buttons, which is another key factor in Bootstrap. We presented some of the basis of button configurations and customizations. During the rest of this book, some more options will be presented in many different ways, but respecting the basis that you have just learned.
Tables are also a very common element in web pages, and Bootstrap offers a wide variety of customizations for them. We showed an example with all the main table features that you can for sure use in your daily tasks.
Finally, we saw some tricks of the framework. As I already said, you must understand the roots of Bootstrap to understand the magic. In an easy way, Bootstrap offers helpers to make our work as fast as it can get.
In the next chapter, we will dive into mobile-first development and different viewport configurations, making our landing page best fit for any device. We will also show a nice way to debug our page for any virtual devices.
You should be asking yourself, "I thought that we should first do the layout in mobile and then go to the desktop version. Why are we in the opposing way?"
Sorry, you are right! We should always go mobile-first. We went the opposite direction just for learning purposes and now we are going to fix it.
In the current chapter, we will focus on mobile design and site responsiveness with the help of the Bootstrap framework by learning how to change the page layout for different viewports, changing the content, and more. The key points of the chapter are as follows:
- Mobile-first development
- Debugging for any device
- Bootstrap grid system for different resolutions
To figure out what, we will continue with the landing page that we developed in the last chapter.
Maybe you have asked yourself (or even searched for) the reason for the mobile-first paradigm trend. It is simple and makes complete sense for speeding up your development.
The main argument for the mobile-first paradigm is that it is easier to make it than to shrink it. In other words, if you make a desktop version of the web page (known as responsive design or mobile last) first and then adjust the website for mobile, it has a 99 percent probability of breaking the layout at some point and you will have to fix a lot of things.
On the other hand, if you create the mobile version first, naturally the website will use (or show) less content than the desktop version. So, it will be easier to just add the content, place the things in the right places, and create the fully responsiveness stack.
The following figure tries to illustrate this concept. Going mobile last, you will get a degraded, sharped, and crappy layout and you will get a progressively enhanced, future-friendly, awesome web page if you go mobile first. The following figure tries to illustrate the design flow of each paradigm. You can see what happens to the poor elephant… Mobile-first naturally grows the elephant instead of adjusting it:

In the beginning of Bootstrap, there was no concept of mobile-first. It was first used for responsive design web pages. With the Version 3 of the framework, the concept of mobile-first became very solid in the community.
The whole code of the scaffolding system was rewritten to become mobile-first from the start. They decided to reformulate how to set the grid instead of just adding mobile styles. This made a great impact in compatibility between versions older than v3, but was crucial for making the framework even more popular.
As we saw in the first chapter, to ensure the proper rendering of the page, set the correct viewport at the <head>
tag:
<meta name="viewport" content="width=device-width, initial-scale=1">
Let's see how to debug different viewports using the Google Chrome web browser. Even if you already know that you can skip this section, it is important to refresh the steps for doing that.
First of all, open the current landing page project that we will continue working with in this chapter in the Google Chrome browser. In the page, you need to select the Developer tools option. There are many ways to open this menu:
- Right-click at any place on the page and click on the last option Element inspector
- Go to the setting (the sandwich button at the top-right of the address bar), click on More tools, and select Developer tools
- The shortcut to open it is Ctrl + Shift + I (cmd for OS X users)
- F12 in Windows also works (this is an Internet Explorer legacy)
In the Developer tools, click in the mobile phone on the left of a magnifier, as shown in the following screenshot:

It will change the display of the viewport to a certain device and you can also set a specific network usage to limit the data bandwidth. Chrome will show a message telling you that for properly visualization you may need to reload the page to get the correct rendering.

As shown in the next screenshot, we have activated the Device mode for an iPhone 5 device. When we set this viewport, problems started appearing because we did not make the landing page with mobile-first methodology.

The first problem is in the second row of our layout. See how Ctrl + D breaks to a new line. That is not supposed to happen.
Another problem is that we have a horizontal scroll for this device due to some unknown reason. That sucks! We will have more work than with the opposite direction that starts with the mobile page. Keep it as a lesson for not repeating the same mistake.
Now, we can debug our website in different devices with different resolutions. You may see that the mouse cursor has changed to a gray circle. Also, the click actions have changed to tap actions. With that, you can fully test the website without the physical device.
Let's first clean out the messy parts in the layout before playing some tricks with the mobile version.
First, we will stop the line from breaking in the Ctrl + D text in the second row of our design. For fixing this issue, we will create our first line of CSS code. Add the <head>
tag to a custom CSS file. Remember to place it below the bootstrap.css
import line:
<link rel="stylesheet" href="css/base.css">
In the base.css
file, create a helper class rule for .nowrap
:
.nowrap { white-space: nowrap; }
In the HTML file, add the created class to the <kbd>
element (line 43):
<kbd class="nowrap"><kbd>ctrl</kbd> + <kbd>d</kbd></kbd>
Reload the page and you'll see that one problem is solved. Now, let's fix the horizontal scroll. Can you figure out what is making the unintended horizontal scroll? A tip, the problem is in the table!
The problem is caused by the buttons with the display block that make the content of each column larger than intended. To fix this, we will create our first CSS media query:
@media (max-width: 48em) { table .btn { font-size: 0.75rem; font-size: 3.5vw; } }
Breaking down each line, first we see the current media query. The rule is that for max-width
of 48em
(defined in Bootstrap as small devices), apply the following rules. If the view port is greater than 48em
, the rule will not be applied.
For the .btn
elements inside the table
element, we changed the font size (this was causing the horizontal overflow). We used a new way to set the font size based on the viewport with the 3.5vw
value. Each 1vw
corresponds to 1 percent of the total viewport. If we change the viewport, we will change the font size dynamically without breaking the layout.
Since it is a new property, nowadays just Chrome 20-34 and Safari 6 or higher have this rendering feature. For this reason, we added the other line with font-size: 0.75rem
as a fallback case. If the browser can't handle the viewport font size, it will already had decreased the font to 12px
, which is a font that does not break the layout.
Now that we have fixed everything and learned some things about media queries and CSS3 properties, let's play with our layout and change it a bit for different devices. We will be starting with mobile and go further until we reach large desktops.
To do so, we must apply the column class for the specific viewport, as we did for medium displays using the .col-md-*
class. The following table was presented in the previous chapter to show the different classes and the resolutions applicable for specific classes:
Extra small devices (phones < 544px / 34em) |
Small devices (tablets ≥ 544px / 34em and < 768px / 48em) |
Medium devices (desktops ≥ 768px /48em < 900px / 62em) |
Large devices (desktops ≥ 900px / 62em < 1200px 75em) |
Extra-large devices (Desktops ≥ 1200px / 75em) | |
---|---|---|---|---|---|
Grid behavior |
Horizontal lines at all times |
Collapse at start and fit column grid | |||
Container fixed width |
Auto |
|
|
|
|
Class prefix |
|
|
|
|
|
Number of columns |
12 columns | ||||
Column fixed width |
Auto |
|
|
|
|
To adapt our landing page to mobile devices, we will be using the Chrome mobile debug tool with the device iPhone 5 set and no network throttling.
You might have noticed that for small devices, Bootstrap just stacks each column without the referring for different rows. Some of our rows seem fine in this new grid, like the header and the second one. In the third row, it is a bit strange that the portion of code and the image are not in the same line, as shown in the following screenshot:

For doing that, we need to add the class columns prefix for extra small devices, which is .col-xs-*
, where *
is the size of the row from 1 to 12. Add the class .col-xs-5
and .col-xs-7
for the columns of the respective row (near line 49). Refresh the page and you will see now how the columns are side-by-side. The code is as follows:
<div class="row"> <!-- row 3 --> <div class="col-md-3 col-xs-5"> <pre><p>I love programming!</p> <p>This paragraph is on my landing page</p> <br/> <br/> <p>Bootstrap by example</p> </pre> </div> <div class="col-md-9 col-xs-7"> <img src="imgs/center.png" class="img-responsive"> </div> </div>
Although the image of the web browser is too small on the right, it would be better if it was a more vertical stretched image, such a mobile phone (what a coincidence!). To make it, we need to hide the browser image in extra small devices and display an image of a mobile device. Add the new mobile image below the old one, as shown in the code:
<img src="imgs/mobile.png" class="img-responsive">
You will see both images stacked up vertically in the right column. Then, we need to use a new concept of availability classes. We need to hide the browser image and display the mobile image just for this kind of viewport, which is extra small. For that, add the class .hidden-xs
in the browser image and add the class .visible-xs
in the mobile image:
<div class="row"> <!-- row 3 --> <div class="col-md-3 col-xs-5"> <pre><p>I love programming!</p> <p>This paragraph is on my landing page</p> <br/> <br/> <p>Bootstrap by example</p> </pre> </div> <div class="col-md-9 col-xs-7"> <img src="imgs/center.png" class="img-responsive hidden-xs"> <img src="imgs/mobile.png" class="img-responsive visible-xs"> </div> </div>
Now this row seems nice! The browser image was hidden in extra small devices and the mobile image is shown only for this viewport in question. The following screenshot shows the final display of this row:

Moving on to the next row, the fourth one, it is the testimonial row surrounded by two images. It would be nicer if the testimonial appeared first and both of the images were displayed after it, splitting the same row. For this, we will repeat almost the same techniques presented in the previous row. Let's do it again for practice.
The first change is to hide the Bootstrap image with the class .hidden-xs
. After that, create another image tag with the Bootstrap image in the same column of the PACKT image. The final code of the row should be like this:
<div class="row"> <!-- row 4 --> <div class="col-md-3 hidden-xs"> <img src="imgs/bs.png" class="img-responsive"> </div> <div class="col-md-6 col-xs-offset-1 col-xs-11"> <blockquote> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> <footer>Testimonial from someone at <cite title="Source Title">Source Title</cite></footer> </blockquote> </div> <div class="col-md-3 col-xs-7"> <img src="imgs/packt.png" class="img-responsive"> </div> <div class="col-xs-5 visible-xs"> <img src="imgs/bs.png" class="img-responsive"> </div> </div>
We made plenty of things now and they are highlighted in bold. First is the .hidden-xs
in the first column of Bootstrap image, which hid the column for this viewport.
Afterwards, in the testimonial, we changed the grid for mobile, adding a column offset with size 1 and making the testimonial fill the rest of the row with the class .col-xs-11
.
Finally, as we said, we want to split in the same row both images from PACKT and Bootstrap. For that, make the first image column fill seven columns with the class .col-xs-7
.
The other image column is a little more complicated. Since it is just visible for mobile devices, we add the class .col-xs-5
. This will make the element span five columns in extra small devices. Moreover, we hide the column for other viewports with the class .visible-xs
.
As we can see, this row has more than 12 columns (1 offset, 11 testimonial, 7 PACKT image, 5 Bootstrap image). This process is called column wrapping, and it happens when you put more than 12 columns in the same row so the groups of extra columns will wrap to the next lines.
Tip
Availability classes
Just like the .hidden-*
, there are the .visible-*-*
classes for each variation of display and column from 1 to 12. There is also a way to change the display CSS property using the class .visible-*-*
, where the last *
means block, inline, or inline-block. Use this to set the properly visualization for different visualizations.
The following screenshot shows the result of the changes. As you can see, we made the testimonial appears first, with one column of offset and both images appearing below it:

After completing the mobile visualizations, let's go further to tablets and small devices, which are devices from 48em to 62em. Most of this these devices are tablets or old desktop monitors. For this example, we are using the iPad Mini in the portrait position with a resolution of 768 x 1024 pixels.
For this resolution, Bootstrap handles the rows just like extra small devices by just stacking up each one of the columns, making them fill the total width of the page. So if we do not want that to happen, we have to manually set the column fill for each element with the class .col-sm-*
.
If you see how our example is presented now, there are two main problems. The first one is the second row, where the headings are in separated lines when they could be in the same. So, we just need to apply the grid classes for small devices with the class .col-sm-6
for each column, splitting them into equal sizes:
<div class="row"> <div class="col-md-offset-4 col-md-4 col-sm-6"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4 col-sm-6"> <h3> Add to your favorites <small> <kbd class="nowrap"><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
The result should be as shown in the following screenshot:

The second problem in this viewport is again the testimonial row! Because of the classes that we have added for mobile viewport, now the testimonial has an offset column and different column span. We must add the classes for small devices and make this row with the Bootstrap image on the left, the testimonial in the middle, and the PACKT image at the right position:
<div class="row"> <div class="col-md-3 hidden-xs col-sm-3"> <img src="imgs/bs.png" class="img-responsive"> </div> <div class="col-md-6 col-xs-offset-1 col-xs-11 col-sm-6 col-sm-offset-0"> <blockquote> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> <footer>Testimonial from someone at <cite title="Source Title">Source Title</cite></footer> </blockquote> </div> <div class="col-md-3 col-xs-7 col-sm-3"> <img src="imgs/packt.png" class="img-responsive"> </div> <div class="col-xs-5 hidden-sm hidden-md hidden-lg"> <img src="imgs/bs.png" class="img-responsive"> </div> </div>
As you can see, we had to reset the column offset in the testimonial column. It happened because it kept the offset that we added for extra small devices. Moreover, we are just ensuring that the images columns had to fill just three columns. Here's the result:

Everything else seems fine! These viewport was easier to setup. See how Bootstrap helps us a lot? Let's move to the final viewport: desktop or large devices.
Last but not least, we enter the grid layout for desktop and large devices. We skipped medium devices, because we first coded for that viewport.
Deactivate the device mode in Chrome and put your page in a viewport with a width larger or equal to 1200 pixels or 75em.
The grid prefix that we will be using is .col-lg-*
. If you take a look at the landing page, you will see that everything is well placed and we don't need to make changes! However, we would like to make some tweaks to make our layout fancier and learn some stuffs of Bootstrap grid.
We want to touch upon column ordering. It is possible to change the order of column in the same row by applying the classes .col-lg-push-*
and .col-lg-pull-*
(note that we are using the large devices prefix, but any other grid class prefix can be used).
The .col-lg-push-*
means that the column will be pushed to the right by the *
columns, where *
is the number of columns pushed. On the other hand, .col-lg-pull-*
will pull the column in the left direction by *
, where *
is the number of columns as well. Let's test this trick in the second row by changing the order of both columns:
<div class="row"> <div class="col-md-offset-4 col-md-4 col-sm-6 col-lg-push-4"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4 col-sm-6 col-lg-pull-4"> <h3> Add to your favorites <small> <kbd class="nowrap"><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
We just added the class .col-lg-push-4
to the first column and .col-lg-pull-4
to the other one to get this result. By doing this, we changed the order of both columns in second row, as shown in the following screenshot:

Mobile and extra small devices
To adapt our landing page to mobile devices, we will be using the Chrome mobile debug tool with the device iPhone 5 set and no network throttling.
You might have noticed that for small devices, Bootstrap just stacks each column without the referring for different rows. Some of our rows seem fine in this new grid, like the header and the second one. In the third row, it is a bit strange that the portion of code and the image are not in the same line, as shown in the following screenshot:

For doing that, we need to add the class columns prefix for extra small devices, which is .col-xs-*
, where *
is the size of the row from 1 to 12. Add the class .col-xs-5
and .col-xs-7
for the columns of the respective row (near line 49). Refresh the page and you will see now how the columns are side-by-side. The code is as follows:
<div class="row"> <!-- row 3 --> <div class="col-md-3 col-xs-5"> <pre><p>I love programming!</p> <p>This paragraph is on my landing page</p> <br/> <br/> <p>Bootstrap by example</p> </pre> </div> <div class="col-md-9 col-xs-7"> <img src="imgs/center.png" class="img-responsive"> </div> </div>
Although the image of the web browser is too small on the right, it would be better if it was a more vertical stretched image, such a mobile phone (what a coincidence!). To make it, we need to hide the browser image in extra small devices and display an image of a mobile device. Add the new mobile image below the old one, as shown in the code:
<img src="imgs/mobile.png" class="img-responsive">
You will see both images stacked up vertically in the right column. Then, we need to use a new concept of availability classes. We need to hide the browser image and display the mobile image just for this kind of viewport, which is extra small. For that, add the class .hidden-xs
in the browser image and add the class .visible-xs
in the mobile image:
<div class="row"> <!-- row 3 --> <div class="col-md-3 col-xs-5"> <pre><p>I love programming!</p> <p>This paragraph is on my landing page</p> <br/> <br/> <p>Bootstrap by example</p> </pre> </div> <div class="col-md-9 col-xs-7"> <img src="imgs/center.png" class="img-responsive hidden-xs"> <img src="imgs/mobile.png" class="img-responsive visible-xs"> </div> </div>
Now this row seems nice! The browser image was hidden in extra small devices and the mobile image is shown only for this viewport in question. The following screenshot shows the final display of this row:

Moving on to the next row, the fourth one, it is the testimonial row surrounded by two images. It would be nicer if the testimonial appeared first and both of the images were displayed after it, splitting the same row. For this, we will repeat almost the same techniques presented in the previous row. Let's do it again for practice.
The first change is to hide the Bootstrap image with the class .hidden-xs
. After that, create another image tag with the Bootstrap image in the same column of the PACKT image. The final code of the row should be like this:
<div class="row"> <!-- row 4 --> <div class="col-md-3 hidden-xs"> <img src="imgs/bs.png" class="img-responsive"> </div> <div class="col-md-6 col-xs-offset-1 col-xs-11"> <blockquote> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> <footer>Testimonial from someone at <cite title="Source Title">Source Title</cite></footer> </blockquote> </div> <div class="col-md-3 col-xs-7"> <img src="imgs/packt.png" class="img-responsive"> </div> <div class="col-xs-5 visible-xs"> <img src="imgs/bs.png" class="img-responsive"> </div> </div>
We made plenty of things now and they are highlighted in bold. First is the .hidden-xs
in the first column of Bootstrap image, which hid the column for this viewport.
Afterwards, in the testimonial, we changed the grid for mobile, adding a column offset with size 1 and making the testimonial fill the rest of the row with the class .col-xs-11
.
Finally, as we said, we want to split in the same row both images from PACKT and Bootstrap. For that, make the first image column fill seven columns with the class .col-xs-7
.
The other image column is a little more complicated. Since it is just visible for mobile devices, we add the class .col-xs-5
. This will make the element span five columns in extra small devices. Moreover, we hide the column for other viewports with the class .visible-xs
.
As we can see, this row has more than 12 columns (1 offset, 11 testimonial, 7 PACKT image, 5 Bootstrap image). This process is called column wrapping, and it happens when you put more than 12 columns in the same row so the groups of extra columns will wrap to the next lines.
Tip
Availability classes
Just like the .hidden-*
, there are the .visible-*-*
classes for each variation of display and column from 1 to 12. There is also a way to change the display CSS property using the class .visible-*-*
, where the last *
means block, inline, or inline-block. Use this to set the properly visualization for different visualizations.
The following screenshot shows the result of the changes. As you can see, we made the testimonial appears first, with one column of offset and both images appearing below it:

After completing the mobile visualizations, let's go further to tablets and small devices, which are devices from 48em to 62em. Most of this these devices are tablets or old desktop monitors. For this example, we are using the iPad Mini in the portrait position with a resolution of 768 x 1024 pixels.
For this resolution, Bootstrap handles the rows just like extra small devices by just stacking up each one of the columns, making them fill the total width of the page. So if we do not want that to happen, we have to manually set the column fill for each element with the class .col-sm-*
.
If you see how our example is presented now, there are two main problems. The first one is the second row, where the headings are in separated lines when they could be in the same. So, we just need to apply the grid classes for small devices with the class .col-sm-6
for each column, splitting them into equal sizes:
<div class="row"> <div class="col-md-offset-4 col-md-4 col-sm-6"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4 col-sm-6"> <h3> Add to your favorites <small> <kbd class="nowrap"><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
The result should be as shown in the following screenshot:

The second problem in this viewport is again the testimonial row! Because of the classes that we have added for mobile viewport, now the testimonial has an offset column and different column span. We must add the classes for small devices and make this row with the Bootstrap image on the left, the testimonial in the middle, and the PACKT image at the right position:
<div class="row"> <div class="col-md-3 hidden-xs col-sm-3"> <img src="imgs/bs.png" class="img-responsive"> </div> <div class="col-md-6 col-xs-offset-1 col-xs-11 col-sm-6 col-sm-offset-0"> <blockquote> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> <footer>Testimonial from someone at <cite title="Source Title">Source Title</cite></footer> </blockquote> </div> <div class="col-md-3 col-xs-7 col-sm-3"> <img src="imgs/packt.png" class="img-responsive"> </div> <div class="col-xs-5 hidden-sm hidden-md hidden-lg"> <img src="imgs/bs.png" class="img-responsive"> </div> </div>
As you can see, we had to reset the column offset in the testimonial column. It happened because it kept the offset that we added for extra small devices. Moreover, we are just ensuring that the images columns had to fill just three columns. Here's the result:

Everything else seems fine! These viewport was easier to setup. See how Bootstrap helps us a lot? Let's move to the final viewport: desktop or large devices.
Last but not least, we enter the grid layout for desktop and large devices. We skipped medium devices, because we first coded for that viewport.
Deactivate the device mode in Chrome and put your page in a viewport with a width larger or equal to 1200 pixels or 75em.
The grid prefix that we will be using is .col-lg-*
. If you take a look at the landing page, you will see that everything is well placed and we don't need to make changes! However, we would like to make some tweaks to make our layout fancier and learn some stuffs of Bootstrap grid.
We want to touch upon column ordering. It is possible to change the order of column in the same row by applying the classes .col-lg-push-*
and .col-lg-pull-*
(note that we are using the large devices prefix, but any other grid class prefix can be used).
The .col-lg-push-*
means that the column will be pushed to the right by the *
columns, where *
is the number of columns pushed. On the other hand, .col-lg-pull-*
will pull the column in the left direction by *
, where *
is the number of columns as well. Let's test this trick in the second row by changing the order of both columns:
<div class="row"> <div class="col-md-offset-4 col-md-4 col-sm-6 col-lg-push-4"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4 col-sm-6 col-lg-pull-4"> <h3> Add to your favorites <small> <kbd class="nowrap"><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
We just added the class .col-lg-push-4
to the first column and .col-lg-pull-4
to the other one to get this result. By doing this, we changed the order of both columns in second row, as shown in the following screenshot:

Tablets and small devices
After completing the mobile visualizations, let's go further to tablets and small devices, which are devices from 48em to 62em. Most of this these devices are tablets or old desktop monitors. For this example, we are using the iPad Mini in the portrait position with a resolution of 768 x 1024 pixels.
For this resolution, Bootstrap handles the rows just like extra small devices by just stacking up each one of the columns, making them fill the total width of the page. So if we do not want that to happen, we have to manually set the column fill for each element with the class .col-sm-*
.
If you see how our example is presented now, there are two main problems. The first one is the second row, where the headings are in separated lines when they could be in the same. So, we just need to apply the grid classes for small devices with the class .col-sm-6
for each column, splitting them into equal sizes:
<div class="row"> <div class="col-md-offset-4 col-md-4 col-sm-6"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4 col-sm-6"> <h3> Add to your favorites <small> <kbd class="nowrap"><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
The result should be as shown in the following screenshot:

The second problem in this viewport is again the testimonial row! Because of the classes that we have added for mobile viewport, now the testimonial has an offset column and different column span. We must add the classes for small devices and make this row with the Bootstrap image on the left, the testimonial in the middle, and the PACKT image at the right position:
<div class="row"> <div class="col-md-3 hidden-xs col-sm-3"> <img src="imgs/bs.png" class="img-responsive"> </div> <div class="col-md-6 col-xs-offset-1 col-xs-11 col-sm-6 col-sm-offset-0"> <blockquote> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p> <footer>Testimonial from someone at <cite title="Source Title">Source Title</cite></footer> </blockquote> </div> <div class="col-md-3 col-xs-7 col-sm-3"> <img src="imgs/packt.png" class="img-responsive"> </div> <div class="col-xs-5 hidden-sm hidden-md hidden-lg"> <img src="imgs/bs.png" class="img-responsive"> </div> </div>
As you can see, we had to reset the column offset in the testimonial column. It happened because it kept the offset that we added for extra small devices. Moreover, we are just ensuring that the images columns had to fill just three columns. Here's the result:

Everything else seems fine! These viewport was easier to setup. See how Bootstrap helps us a lot? Let's move to the final viewport: desktop or large devices.
Last but not least, we enter the grid layout for desktop and large devices. We skipped medium devices, because we first coded for that viewport.
Deactivate the device mode in Chrome and put your page in a viewport with a width larger or equal to 1200 pixels or 75em.
The grid prefix that we will be using is .col-lg-*
. If you take a look at the landing page, you will see that everything is well placed and we don't need to make changes! However, we would like to make some tweaks to make our layout fancier and learn some stuffs of Bootstrap grid.
We want to touch upon column ordering. It is possible to change the order of column in the same row by applying the classes .col-lg-push-*
and .col-lg-pull-*
(note that we are using the large devices prefix, but any other grid class prefix can be used).
The .col-lg-push-*
means that the column will be pushed to the right by the *
columns, where *
is the number of columns pushed. On the other hand, .col-lg-pull-*
will pull the column in the left direction by *
, where *
is the number of columns as well. Let's test this trick in the second row by changing the order of both columns:
<div class="row"> <div class="col-md-offset-4 col-md-4 col-sm-6 col-lg-push-4"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4 col-sm-6 col-lg-pull-4"> <h3> Add to your favorites <small> <kbd class="nowrap"><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
We just added the class .col-lg-push-4
to the first column and .col-lg-pull-4
to the other one to get this result. By doing this, we changed the order of both columns in second row, as shown in the following screenshot:

Desktop and large devices
Last but not least, we enter the grid layout for desktop and large devices. We skipped medium devices, because we first coded for that viewport.
Deactivate the device mode in Chrome and put your page in a viewport with a width larger or equal to 1200 pixels or 75em.
The grid prefix that we will be using is .col-lg-*
. If you take a look at the landing page, you will see that everything is well placed and we don't need to make changes! However, we would like to make some tweaks to make our layout fancier and learn some stuffs of Bootstrap grid.
We want to touch upon column ordering. It is possible to change the order of column in the same row by applying the classes .col-lg-push-*
and .col-lg-pull-*
(note that we are using the large devices prefix, but any other grid class prefix can be used).
The .col-lg-push-*
means that the column will be pushed to the right by the *
columns, where *
is the number of columns pushed. On the other hand, .col-lg-pull-*
will pull the column in the left direction by *
, where *
is the number of columns as well. Let's test this trick in the second row by changing the order of both columns:
<div class="row"> <div class="col-md-offset-4 col-md-4 col-sm-6 col-lg-push-4"> <h3> Some text with <small>secondary text</small> </h3> </div> <div class="col-md-4 col-sm-6 col-lg-pull-4"> <h3> Add to your favorites <small> <kbd class="nowrap"><kbd>ctrl</kbd> + <kbd>d</kbd></kbd> </small> </h3> </div> </div>
We just added the class .col-lg-push-4
to the first column and .col-lg-pull-4
to the other one to get this result. By doing this, we changed the order of both columns in second row, as shown in the following screenshot:

We have completed another chapter. Here, we discussed why we should always go mobile-first if we want to make a web page for every viewport, from mobile to large desktop. Making things bigger is always easier and causes less issues, so start small with mobile devices and evolve the web page until it reaches large desktop resolutions.
We saw how to debug different devices using our browser and set the right classes for each viewport. We now have our example of a landing page with full stack responsiveness, working well in any device.
We covered the grid options for various devices resolutions using the mobile-first methodology—starting with mobile and going further until the large desktop version.
The main lesson of this chapter was that we always should go mobile-first. We did not follow this approach at first and because of that, we faced some problems that we could have eliminated if we had started mobile-first.
It was not mentioned before, but going mobile-first helps the whole team. The designer will have a bigger picture of what he or she needs to reach and what information is important from the beginning. The backend developer can focus on the main features and optimize them for mobile before moving on to the rest of the page content delivery. Mobile-first is also part of the development strategy.
At this point, we have our landing page fully set at all resolutions. Using Bootstrap, we took a shortcut towards responsivity, doing all the groundwork with a few lines of code in HTML and some more in CSS.
In the next chapter, we will apply some customizable styles to make the page a little less like a Bootstrap page. We will also see how to create landing pages for different uses by customizing the components.
After making our landing page mobile-first and fully responsive for any device, it is time to go further into the Bootstrap framework, adding more and more components along with the style improvement.
This is the main objective of this chapter. We will take a step forward in terms of layout improvement, taking in regards the use of Bootstrap components. The chapter's key points are:
- Layout improvement
- Bootstrap forms
- Using images in Bootstrap
- Bootstrap helpers
By the end of this chapter, our landing page will almost be done, and you will be able to handle every HTML component customized by Bootstrap.
First of all, the grid that we used for the current landing page is just a showcase of Bootstrap's potential and possibilities of customization. In this chapter, our objective is to make the grid fancier and more beautiful. To do this, we will change the grid to be like the one presented in the next figure.
We will go a little faster this time, since you already know how to create the grid using Bootstrap. Also, we will go mobile-first, as we discussed in the last chapter, but the screenshots will be taken from larger viewports just to improve the understandability.

As you can see in the grid image, we split the grid into six parts. This time, each part will be a section that we will present step by step. If you are starting the example from scratch, don't forget to keep the boilerplate that we presented previously.
So, we will start with the header. The code for representing the grid presented should be this one, to be placed right after the <body>
tag:
<header> <div class="container"> <!-- row 1 --> <div class="row"> <a class="brand pull-left" href="#">Company name</a> <ul class="list-inline list-unstyled pull-right"> <li><a href="#about">About</a></li> <li><a href="#features">Features</a></li> <li><a href="#pricing">Pricing</a></li> <li><a href="#contact">Contact</a></li> </ul> </div> </div> </header>
As you can see, the <header>
tag is wrapping all of our .container
, making it similar to a section. Just for the note, to have the brand link placed on the left-hand side and the list on the right-hand side, we added the .pull-left
and .pull-right
classes to it, respectively. These are two Bootstrap helpers.
Now, let's modify our CSS to change the header style. Remember to import the custom CSS file at <header>
:
<link rel="stylesheet" href="css/base.css">
For that part, we will change the background color and the alignment to a better placement of the link and list elements, so let's customize and override some styles from Bootstrap:
header { background-color: #F8F8F8; } header ul { margin: 0; } header a, header li { padding: 1.4rem 0; color: #777; font-weight: bold; }
The header will look like what is shown in the following screenshot:

We have called the introduction header section 2 of our grid. In this section, we have a big name of the company followed by the tagline and some buttons. The code for this row should be as follows:
<section id="intro-header"> <div class="container"> <!-- row 2 --> <div class="row"> <div class="wrap-headline"> <h1 class="text-center">Company name</h1> <h2 class="text-center">Tagline message</h2> <hr> <ul class="list-inline list-unstyled text-center"> <li> <a class="btn btn-default btn-lg" href="#" role="button">Sign in</a> </li> <li> <a class="btn btn-primary btn-lg" href="#" role="button">Sign up</a> </li> </ul> </div> </div> </div> </section>
So, we have wrapped the entire container in a section, just as we said we would. There is no secret here; we used <h1>
for the company name and <h2>
for the tagline. We placed the buttons in a centered list, just like the headlines, using the .text-center
helper class, and the buttons are all set as before.
We will place a big image as the background for the #intro-header
section. To do this, we edit the CSS file as follows:
section#intro-header { background-image: url(../imgs/landscape.jpg); background-size: cover; }
The background set as cover
will do the trick for us to make the image cover full width, although the size of the section is too small right now. For that, we will use our .wrap-headline
element to do the trick and make it bigger:
section#intro-header .wrap-headline { position: relative; padding-top: 20%; padding-bottom: 20%; }
As you may notice, we let a 20%
padding at the top and bottom relative to our current position. With this, the height of the section becomes responsive to any viewport.
Moving on, we add some more CSS rules just for formatting, as follows:
section#intro-header { background-image: url(../imgs/landscape.jpg); background-size: cover; } section#intro-header .wrap-headline { position: relative; padding-top: 20%; padding-bottom: 20%; } section#intro-header h1, section#intro-header h2 { color: #FFF; } section#intro-header h2 { font-size: 1.5rem; } section#intro-header hr { width: 10%; } section#intro-header .btn-default { background-color: rgba(255, 255, 255, 0.5); border: none; }
The final output of those two sections should be like the one shown in the following screenshot. Pretty fancy, isn't it?

So, for the about section, we will place a container that wraps all of the section as well. We will play with two rows equally divided, in which we will display an image and text alternated side by side. The code for this section should be as follows:
<section id="about"> <div class="container"> <!-- row 3 --> <div class="row"> <div class="col-sm-6"> <img src="imgs/mock_ipad.jpg" class="img-responsive"> </div> <div class="col-sm-6"> <h3>Lorem ipsum dolor sit amet</h3> <p> Lorem ipsum dolor... </p> </div> </div> <hr> <!-- row 4 --> <div class="row"> <div class="col-sm-6"> <h3>Lorem ipsum dolor sit amet</h3> <p> Lorem ipsum dolor... </p> </div> <div class="col-sm-6"> <img src="imgs/mock_nexus.jpg" class="img-responsive"> </div> </div> </div> </section>
At this section, we just created two rows with two columns in each one. Since the columns are equally divided, they receive the .col-sm-6
class. We added the .img-responsive
class to the images to keep the ratio over the viewport and placed some text content on the image side of the column.
For the CSS, we add some rules to increase the margin between the content and the top portion of the page:
section#about img { margin-top: 6.5rem; margin-bottom: 5rem; } section#about h3 { margin-top: 10rem; }
The following screenshot shows the resultant output of this section. Check whether the result of your code is similar to the following screenshot, and then let's move on to the features section:

The features section is composed of two lines of three columns, although we will create only one .row
element and use the column wrapper technique. Do you remember it?
The column wrapper technique uses more than 12 parts of columns in a single row. The columns that overflow the .row
will then be placed in the line below, creating the effect similar to having two .row
elements:
<section id="features"> <div class="container"> <!-- row 5 --> <div class="row"> <div class="col-sm-12"> <h3 class="text-center">Features</h3> <p class="text-center">Features headline message</p> </div> </div> <!-- row 6 --> <div class="row"> <div class="col-sm-2 col-md-4"> <div class="feature">Feature</div> </div> <div class="col-sm-2 col-md-4"> <div class="feature">Feature</div> </div> <div class="col-sm-2 col-md-4"> <div class="feature">Feature</div> </div> <div class="col-sm-2 col-md-4"> <div class="feature">Feature</div> </div> <div class="col-sm-2 col-md-4"> <div class="feature">Feature</div> </div> <div class="col-sm-2 col-md-4"> <div class="feature">Feature</div> </div> </div> </div> </div> </section>
In this section, we created two rows. The first one holds the title and headline of the section with the <h3>
and <p>
tags, respectively. The second row is just composed of six equal columns with the .col-sm-2
and .col-md-4
classes. The use of .col-sm-2
will place the .feature
elements in a single line when using a small viewport.
Now, edit the CSS, and let's change the text color and add some padding between the features columns list:
section#features { background-color: #eef2f5; border-top: 0.1rem solid #e9e9e9; border-bottom: 0.1rem solid #e9e9e9; } section#features * { color: #657C8E; } section#features .feature { padding-top: 2rem; padding-bottom: 4rem; text-align: center; }
The following screenshot presents the final output for the features section. Then it is time for us to start modifying the price table. It should be easy since we have already done the groundwork for it.

For the price table section, we will use the same table from the Manipulating tables section in Chapter 2, Creating a Solid Scaffolding, but with a few modifications to make it prettier. We will make some small changes, as presented in the following code:
<section id="pricing"> <div class="container"> <!-- row 7 --> <div class="row"> <div class="col-sm-12"> <h3 class="text-center price-headline">Price table</h3> </div> </div> <!-- row 8 --> <div class="row"> <div class="col-sm-10 col-sm-offset-1"> <table class="table table-striped table-hover"> <thead> <tr> <th class="success"> <h4 class="text-center white-text">Free plan</h4> </th> <th class="info"> <h4 class="text-center white-text">Standard plan</h4> </th> <th class="danger"> <h4 class="text-center white-text">Premium plan</h4> </th> </tr> </thead> <tbody> <tr> <td class="success"> <h3 class="text-center white-text">$ 0</h3> </td> <td class="info"> <h3 class="text-center white-text">$ 99</h3> </td> <td class="danger"> <h3 class="text-center white-text">$ 999</h3> </td> </tr> <tr> <td>Lorem ipsum</td> <td>Lorem ipsum</td> <td>Lorem ipsum</td> </tr> <tr> <td>Lorem ipsum</td> <td>Lorem ipsum</td> <td>Lorem ipsum</td> </tr> <tr> <td>Dolor sit amet</td> <td>Lorem ipsum</td> <td>Lorem ipsum</td> </tr> <tr> <td>-</td> <td>Dolor sit amet</td> <td>Lorem ipsum</td> </tr> <tr> <td>-</td> <td>-</td> <td>Lorem ipsum</td> </tr> <tr> <td><a href="#" class="btn btn-success btn-block">Purchase</a></td> <td><a href="#" class="btn btn-info btn-block">Purchase</a></td> <td><a href="#" class="btn btn-danger btn-block">Purchase</a></td> </tr> </tbody> </table> </div> </div> </div> </section>
The first change is that we added a header, <h3>
, in this section in the first row. Furthermore, we added the .success
, .info
, and .danger
classes to the first <tr>
in <tbody>
(they are highlighted in bold).
Also in <table>
, we removed the .table-bordered
class to take out the border from it. Finally, we changed some colors in the CSS file and created the .white-text
class, which is highlighted in the code as well:
section#pricing h3.price-headline { margin-top: 5rem; margin-bottom: 3rem; } section#pricing .white-text { color: #FFF; } section#pricing thead .success { background-color: #78CFBF; } section#pricing thead .info { background-color: #3EC6E0; } section#pricing thead .danger { background-color: #E3536C; } section#pricing tbody .success { background-color: #82DACA; } section#pricing tbody .info { background-color: #53CFE9; } section#pricing tbody .danger { background-color: #EB6379; }
The following screenshot presents the result of the price table. Finally, to sum it up, we will advance to the footer, which contains the contact information:

For the footer, we will have five columns, the first one being the logo with a .col-sm-2
. This will be followed by three info columns, each one with a .col-sm-2
as well. The last column is the address column, with the .col-sm-4
class. The HTML code is as follows:
<footer> <div class="container"> <div class="col-sm-2"> <img src="imgs/logo.png" class="img-responsive"> </div> <div class="col-sm-2"> <h5>The company</h5> <ul class="list-unstyled"> <li><a href="#">Documentation</a></li> <li><a href="#">Packt publisher</a></li> <li><a href="#">About us</a></li> <li><a href="#">Contact</a></li> </ul> </div> <div class="col-sm-2"> <h5>Social</h5> <ul class="list-unstyled"> <li><a href="#">Facebook</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Blog</a></li> </ul> </div> <div class="col-sm-2"> <h5>Support</h5> <ul class="list-unstyled"> <li><a href="#">Contact</a></li> <li><a href="#">Privacy police</a></li> <li><a href="#">Terms & conditions</a></li> <li><a href="#">Help desk</a></li> </ul> </div> <div class="col-sm-4"> <address> <strong>Name, Inc.</strong> Address line 1<br> Address line 2<br> <abbr title="Phone">P:</abbr> (123) 456-7890 </address> </div> </div> </footer>
Now, let's prettify the footer with some CSS rules:
footer { background-color: #191919; color: #ADADAD; margin-top: 3em; } footer h5, footer img { margin-top: 5em; font-weight: bold; } footer address { margin-top: 5em; margin-bottom: 5em; color: #5A5A5A; } footer ul { margin-bottom: 5em; } footer address strong { color: #ADADAD; display: block; padding-bottom: 0.62em; } footer a { font-weight: 300; color: #5A5A5A; } footer a:hover { text-decoration: none; color: #FFF; }
So, we basically changed the background to a shaded one, added some margins to make the footer larger, and modified the links' colors. And we are done with the new layout! See in the following screenshot how the final layout for the footer looks:

Resize the viewport and you will see how the page correctly adapts to any kind of resolution. So we have made the page again, this time with the mobile-first perspective in mind, adding more content and using Bootstrap as our backup. Nicely done!
The Web would not be the same without forms. They are one of the major methods of interacting with a web page and sending data to consolidate. Since the beginning of the Web, the style and rendering of forms were a source of trouble, because they were displayed differently for each browser and there were placement problems.
This is one of the reasons Bootstrap appeared to make all web pages follow the same rendering pattern for any browser and device. For forms, this is no different. There are styles for almost every kind of element. We will start talking about forms in this section, although we will keep discussing them in later chapters as well, since they are an important element in frontend web development.
To start easy, we will use an inline form in our landing page. Let's add a new row between the price table row and the footer with the following HTML code:
<section id="newsletter" class="text-center"> <h4>Stay connected with us. Join the newsletter to receive fresh info.</h4> <form class="form-inline" method="POST"> <div class="form-group"> <input class="form-control" placeholder="Your name"> </div> <div class="form-group"> <input class="form-control" placeholder="Your email"> </div> <button type="submit" class="btn btn-primary">Join now!</button> </form> </section>
OK, we're starting to break down every part of the code. The first part—we just created a new <section>
and centralized it using the .text-center
class from the Bootstrap helpers.
The first form type that you will learn about is .form-inline
, which simply makes all the controls inside it the inline-block kind. Because of that, we are able to centralize the form using the .text-center
helper. Also, this form will make the controls inline until the small viewport, when it changes the controls to become blocks, each one filling one line.
Inside .form-inline
, we have two div.form-group
. Every element inside a <form>
that contains the .form-group
class will automatically be displayed as a block element. In almost every form element, we will have a .form-group
, since it is an important wrapper for labels and controls for the purpose of optimizing spacing in Bootstrap.
In our case, since we set the form to be the inline kind (because of the .form-inline
class), the .form-group
elements will be inline elements as well.
The two <input>
are not magical; just place it in your code as shown. The same applies to the button, by using the .btn-primary
class to make it blue.
The CSS for this section is quite simple. We have just made some tweaks for better rendering:
section#newsletter { border-top: 1px solid #E0E0E0; padding-top: 3.2em; margin-top: 2em; } section#newsletter h4 { padding: 1em; } section#newsletter form { padding: 1em; margin-top: 2em; margin-bottom: 5.5em; }
Our first form is complete! The following screenshot shows the final output of the form:

This one was the simplest form. Now let's crack some other forms to nail it in Bootstrap.
To make a contact form, we need to create another HTML file. Name it contact.html
and use the same header and footer that you used earlier in the landing page. The final output is shown in the next image. Let's break down each part of the form to achieve the final result:

First of all, we need to create the grid for this form. As you can see, the form is in the center of the page, so to do that, create this HTML code:
<section id="contact" class="container"> <div class="row"> <div class="col-sm-offset-2 col-sm-8"> … </div> </div> </section>
We just created the grid for this container. Inside this column, we need to create a <form>
element with the following code:
<form class="form-horizontal"> <div class="form-group"> <label class="col-sm-2 control-label" for="contact-name">Name</label> <div class="col-sm-10"> <input class="form-control" type="text" id="contact-name" placeholder="Full name"> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label" for="contact-email">Email</label> <div class="col-sm-10"> <input class="form-control" type="text" id="contact-email" placeholder="Contact email"> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label" for="contact-email">Message</label> <div class="col-sm-10"> <textarea class="form-control" rows="3" placeholder="Type your message"></textarea> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <label class="checkbox"> <input type="checkbox" value=""> I want to subscribe to receive updates from the company. </label> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button class="btn btn-success btn-lg" type="submit">Submit</button> </div> </div> </form>
At first sight, it looks like a common form, with two input fields, a text area, a checkbox, and a submit button. The .form-horizontal
class is responsible for aligning the labels and the inputs side by side horizontally. Note that we are using the .col-sm-*
grid classes in both labels and inputs in a grid of 12 parts inside .form-group
, just like the column nesting technique.
In the .form-group
checkbox, we created a <div>
with an offset of 2
to fill the part that is not needed in this case. Note that we are able to use the same grid classes to acquire the same results inside forms. To place the Bootstrap theme in the checkbox, just add the .checkbox
class to the label wrapping the input.
We don't need much CSS in this section; just add some padding to give some space to the form:
section#contact form { padding-top: 9rem; padding-bottom: 3rem; }
It's time to start playing with some JavaScript! Create a file named main.js
inside the js
folder, which also contains the Bootstrap JavaScript file and jQuery library. To do the groundwork in the JavaScript file, we need to load it after document
is ready:
$(document).ready(function() { // document ready, place you code });
Then, we will validate the form before sending it. To do that, attach an event handler to the form submission, like this:
$(document).ready(function() { $('#contact form').on('submit', function(e) { e.preventDefault(); }); });
You may know this, but the e.preventDefault()
code line is a method that prevents the default action from being triggered, the form submission in this case.
Moving on, we create the variables that we will use and the validation code:
$(document).ready(function() { $('#contact form').on('submit', function(e) { e.preventDefault(); var $form = $(e.currentTarget), $email = $form.find('#contact-email'), $button = $form.find('button[type=submit]'); if($email.val().indexOf('@') == -1) { vaca = $email.closest('form-group') $email.closest('.form-group').addClass('has-error'); } else { $form.find('.form-group').addClass('has-success').removeClass('has-error'); $button.attr('disabled', 'disabled'); $button.after('<span>Message sent. We will contact you soon.</span>'); } }); });
So, we first created our variables for the form, the email
field, and the button
element. After that, we performed a naïve validation on the email
field, where if the @
character is present in the field, it is valid. If it is not present, we add the .has-error
class to the parent .form-group
of the field. It will produce the elements inside the form group in red, as presented in the following screenshot:

Load the JavaScript file in the HTML of contact.html
just below where bootstrap.js
loads:
<script src="js/bootstrap.js"></script>
<script src="js/main.js"></script>
If the @
sign is present in the field, we simply pass the validation by fake-sending it. When this happens, we add the .has-success
class to each .form-group
, making them green. We also add the attribute disabled
to the button, changing its behavior and theme as Bootstrap does it.
Finally, we add after the button a simple feedback message for the user, saying that the contact message was sent. The following screenshot shows the case where the contact message is successfully sent:

Now that you have learned some more form styles in the contact file, we will play with another kind of form: the sign-in form.
Go back to the landing page HTML file, and in the sign in .btn
located inside the introduction header, add the #sign-btn
identifier:
<a id="sign-btn" class="btn btn-default btn-lg" href="#" role="button">Sign in</a>
After the <ul>
that wraps the sign buttons, place the sign-in form code:
<form id="signin" class="form-inline text-center hidden-element"> <div class="form-group"> <div class="input-group"> <div class="input-group-addon">@</div> <input type="text" class="form-control" id="signin-email" placeholder="Email"> </div> </div> <div class="form-group"> <div class="input-group"> <div class="input-group-addon">*</div> <input type="password" class="form-control" id="signin-password" placeholder="Password"> </div> </div> <button type="submit" class="btn btn-default">Sign in</button> </form>
The result should be like what is shown in the following screenshot, where the new form appears after the buttons:

Before moving on to fixing the layout, let's explain .input-group
. Bootstrap offers this option to prepend or append things to an input using .input-group-addon
. In this case, we prepend @
and *
to each input. We could also have appended this to the inputs by placing .input-group-addon
after the input instead of before.
For the CSS, we just added the .hidden-element
rule. We could not use the .hidden
Bootstrap helper because it applies the !important
option, and we would not have been able to make it visible again without removing the class:
.hidden-element { display: none; }
Let's animate it a little! Go to the JavaScript file and add the event listener to the click on the sign-in button:
$(document).ready(function() { … // rest of the JavaScript code $('#sign-btn').on('click', function(e) { $(e.currentTarget).closest('ul').hide(); $('form#signin').fadeIn('fast'); }); });
By doing this, we hide the <ul>
element that contains the sign buttons and show the sign in form. That was just the cherry on our pie, and we are done with forms by now! Refresh the web page in the browser, click on the Sign in button, and see the new form appearing. Moving forward, we will use some images and see how Bootstrap can help us with that.
For images, Bootstrap offers some classes to make your day better. We have already discussed the use of the .img-responsive
class, on which the image becomes scalable by setting max-width: 100%
and height: auto
.
The framework also offers three convenient classes to style your image. To make use of that, place the following code after the price table in the landing:
<section id="team"> <div class="container"> <div class="row"> <div class="col-sm-12"> <ul class="list-inline list-unstyled text-center"> <li> <img src="imgs/jon.png" class="img-rounded"> <h5>Jonny Doo</h5> <p>CEO</p> </li> <li> <img src="imgs/jon.png" class="img-circle"> <h5>Jonny Doo</h5> <p>CTO</p> </li> <li> <img src="imgs/jon.png" class="img-thumbnail"> <h5>Jonny Doo</h5> <p>CIO</p> </li> </ul> </div> </div> </section>
As you can notice, we simply created another container and row with a single column, .col-sm-12
. Inside the column, we added an inline list with the elements, each one having one image with a different class. The .img-rounded
class makes the corners rounded, .img-circle
turns the image into a circular shape, and .img-thumbnail
adds a nice rounded border to the image, like this:

The preceding screenshot shows how this section is displayed. We also had to add some CSS code to increase margins and paddings, along with font customization:
section#team ul { margin: 5rem 0; } section#team li { margin: 0 5rem; } section#team h5 { font-size: 1.5rem; font-weight: bold; }
So, it's nice to have a backup of Bootstrap, even with the images, making our work easier and pacing up the development. By the way, Bootstraps offers tons of helpers with the same objective. We have already used some of them; now let's use even more.
Helpers are Bootstrap classes that help us achieve certain customizations. They are planned to offer a single purpose and reduce CSS frequency of repeated rules. The goal is always the same: increase the pace of development.
We have talked previously about the .pull-left
and .pull-right
classes, which make the HTML element float to the left or right. To center the block, you can use the .center-block
class.
To make use of this, go to the column that wraps the pricing table, and replace the.col-sm-10.col-sm-offset-1
classes with .center-block
. In the CSS, add the following rule:
section#pricing .center-block { width: 90% }
Refresh the web page and you will see that the table stays centered, but now using a different approach.
You can apply the same colors that we used in buttons and the price table to every element in the page. To do that, use these classes: .text-primary
, .text-success
, .text-warning
, .text-info
, .text-danger
, and .text-muted
.
In the images section that we have just made, apply the .text-info
class to the <h5>
elements and apply .text-muted
in <p>
:
<section id="team"> <div class="container"> <div class="row"> <ul class="list-inline list-unstyled text-center"> <li> <img src="imgs/jon.png" class="img-rounded"> <h5 class="text-info">Jonny Doo</h5> <p class="text-muted">CEO</p> </li> <li> <img src="imgs/jon.png" class="img-circle"> <h5 class="text-info">Jonny Doo</h5> <p class="text-muted">CTO</p> </li> <li> <img src="imgs/jon.png" class="img-thumbnail"> <h5 class="text-info">Jonny Doo</h5> <p class="text-muted">CIO</p> </li> </ul> </div> </section>
Refresh the web page, and the headline element will be light blue and the paragraph text grey.
To make the opposite operation—changing the background to the context color—apply the .bg-*
class, where you can pass one of the color options (primary, info, warning, or danger).
In Bootstrap 4, they added new helpers for margins and padding spacing. If you are using Sass, you can set a default $spacer
and every margin will work like a charm by using these classes, although the default value for the spacer is 1rem
.
Next, we will present a table with the classes for margin usage. In summary, you will use the .m-*-*
regex, where the first option is the location, such as top, bottom, and so on. The second option is the size of the margin. Refer to this table for a better understanding of the usage:
Remove margin |
Default margin |
Medium margin (1.5 times) |
Large margin (3 times) | |
---|---|---|---|---|
All |
|
|
|
|
Top |
|
|
|
|
Right |
|
|
|
|
Bottom |
|
|
|
|
Left |
|
|
|
|
Horizontal |
|
|
|
|
Vertical |
|
|
|
|
For the padding, the classes are almost the same; just use the .p-*-*
prefix to get the expected result. Remember that the default spacer is 1rem
, so the medium is 1.5rem
and large is 3rem
:
Remove margin |
Default padding |
Medium padding (1.5 times) |
Large padding (3 times) | |
---|---|---|---|---|
All |
|
|
|
|
Top |
|
|
|
|
Right |
|
|
|
|
Bottom |
|
|
|
|
Left |
|
|
|
|
Horizontal |
|
|
|
|
Vertical |
|
|
|
|
The new version of Bootstrap 4 also allows us to make embeds responsive. So, there are classes for the <iframe>
, <embed>
, <video>
, and <object>
elements. To get the expected result, add the .embed-responsive
class to your element:
<div class="embed-responsive embed-responsive-16by9"> <iframe class="embed-responsive-item" src="//www.youtube.com/embed/dQw4w9WgXcQ" allowfullscreen></iframe> </div>
We added the .embed-responsive-16by9
class to make the aspect ratio of the video 16:9. You can also use the aspect ratios 21:9 and 4:3 with the .embed-responsive-21by9
and .embed-responsive-4by3
classes respectively.
In this chapter, we remade our landing page by applying the Bootstrap theme and customizing it, getting a much better result in the end. Right now, we have a clean web page, developed quickly using the mobile-first paradigm.
You also started to learn the use of some forms by going through three examples, one of these being a complementary contact page. Along with forms, we started using JavaScript! We performed form validation and some simple animations on our page, with regard to the template.
Finally, we presented the Bootstrap image options and a bunch of helpers. Remember that there are more helpers than the ones shown in this chapter, but don't worry, because we will see them in the upcoming chapters.
If you think you already have a fancy landing page, we will prove to you that we can improve it even more! We will talk about it again in the next chapter, reaching icons, more forms, buttons, and navigation bars.
Congratulations! You have reached this point of the book. Brace yourself, because the next level is coming. We will take a step forward by using more complex elements and components of Bootstrap.
It is finally time to take our last step through the landing page example. After learning all the basics of Bootstrap, passing from side to side of the grid system, mobile-first development, and using Bootstrap HTML elements, the landing page example has come to an end. Now it is time to go a little deeper and acquire more knowledge of this beautiful framework—Bootstrap.
In this chapter, we will focus on adding components all over the landing page. We will also touch upon the flexbox
option, present in version 4. After all has been said, our landing page will be ready for the production stage. Get ready for the key points that we will cover in this chapter:
- Glyphicon icons
- Navigation bars
- The Drop-down component
- Input grouping
- Flexbox Bootstrap usage
Bootstrap is such a nice thing! It provides for us more than 250 icons ready for use and fully resizable. The icons were created from the Glyphicon Halflings set (http://glyphicons.com/). They are fully rendered as fonts, so you can customize both size and color for each one of them. To make use of that, let's see the features section on the landing page. As you can see, we let this section be a little simpler. By adding some fonts, we will get a nicer result:
<section id="features"> <div class="container"> <!-- row 5 --> <div class="row"> <div class="col-sm-12"> <h3 class="text-center">Features</h3> <p class="text-center">Features headline message</p> </div> </div> <!-- row 6 --> <div class="row"> <div class="col-sm-2 col-md-4"> <div class="feature"> <span class="glyphicon glyphicon-screenshot" aria-hidden="true"></span> <span class="feature-tag">Product focus</span> </div> </div> <div class="col-sm-2 col-md-4"> <div class="feature"> <span class="glyphicon glyphicon-education" aria-hidden="true"></span> <span class="feature-tag">Teaching as a passion</span> </div> </div> <div class="col-sm-2 col-md-4"> <div class="feature"> <span class="glyphicon glyphicon-send" aria-hidden="true"></span> <span class="feature-tag">Spreading knowledge</span> </div> </div> <div class="col-sm-2 col-md-4"> <div class="feature"> <span class="glyphicon glyphicon-hourglass" aria-hidden="true"></span> <span class="feature-tag">Save your day time</span> </div> </div> <div class="col-sm-2 col-md-4"> <div class="feature"> <span class="glyphicon glyphicon-sunglasses" aria-hidden="true"></span> <span class="feature-tag">Make it fancy</span> </div> </div> <div class="col-sm-2 col-md-4"> <div class="feature"> <span class="glyphicon glyphicon-heart" aria-hidden="true"></span> <span class="feature-tag">Made with love</span> </div> </div> </div> </div> </div> </section>
So, from the beginning, here is the code of the modified features section. The bold text corresponds to the icon additions. It is pretty simple to add an icon. Just check out the options at http://getbootstrap.com/components/#glyphicons, copy the class code, and use it in an element. Note that you must add both classes, .glyphicon
and .glyphicon-*
.
Tip
The aria-hidden property
You may have noticed that there is a property called aria-hidden="true"
present in all the icons. The reason for this is that the fonts are represented as Unicode characters, meaning they may represent words. Therefore, to prevent that accessibility, screen readers start reading those characters such as they are words, the aria-hidden
attribute prevents that.
Even more, we made some changes to the CSS file, adding more rules for the current working section. Add the following style to the base.css
file, located in the css
folder:
section#features .feature { padding-top: 2rem; padding-bottom: 4rem; text-align: center; } section#features .glyphicon { font-size: 2rem; } section#features .glyphicon-heart { color: #E04C4C; } section#features .feature-tag { max-width: 10.7em; display: inline-block; text-align: left; margin-left: 1.5em; font-size: 1.7rem; }
With this, we want to show some nice options that you can use with icons. The first one is that you can change the size of the icon by changing its font size. In our case, we set it to font-size: 2rem
. The second one is that icons provide the option to change their color by just adding the CSS color rule. We applied it to the heart icon, because the heart must be red—color: #E04C4C
.

The preceding screenshot shows the final result of the Features section. As you can see, it is pretty simple to use icons in Bootstrap. Also, the possibilities that the framework offers are very suitable for daily adjustments, such changing icons' colors and sizes.
Tip
Using other icons sets
There are plenty of other icon sets out there that can be used just like glyphicons for Bootstrap. Among all of them, it is worth mentioning Font Awesome (https://fortawesome.github.io/Font-Awesome/). It stands out from others, since it was the first icon set to use font encoding, together with a wide variety of icons.
Bootstrap offers a very nice navigation bar to be placed at the top of website, or even in places where you want that behavior. Let's change our header section to make it our navigation bar. It will stick to the top of the web page, working as a navigation menu.
First of all, let's use a <nav>
element and add to it the .navbar
and .navbar-default
classes, which are required for the component, and the .navbar-fixed-top
class to fix the element at the top. Replace the <header>
HTML section with the following code:
<nav class="navbar navbar-default navbar-fixed-top"> <div class="navbar-header"> <a class="navbar-brand" href="landing_page.html">Company name</a> </div> <div class="navbar-right"> <ul class="nav navbar-nav"> <li><a href="#about">About</a></li> <li><a href="#features">Features</a></li> <li><a href="#pricing">Pricing</a></li> <li><a href="contact.html">Contact</a></li> </ul> </div> </nav>
As was mentioned, the .navbar
and .navbar-default
classes are required for the navigation component. For the Company name link, we added a class, .navbar-brand
, which has the purpose of branding the heading with an appropriate font size and padding.
Then, we created a <div>
tag using the .navbar-right
class to provide a set padding CSS rules and place the list to the right to appear the same way as was before. For the CSS, just add the following rule to create a padding to the <body>
of your page:
body { padding-top: 3.6em; } #nav-menu { margin-right: 1rem; }
The result of the navigation bar should be like what is presented in the following screenshot:

Try to resize the web page and you will see that for small viewports, the horizontal list placed in the navigation will stack vertically, as illustrated in the next screenshot. Fortunately, Bootstrap has the option to collapse the lists at the navigation bar. The procedure for doing this is pretty simple and we will do it now.

So, let's make the .nav-header
collapses and create a toggle
button to show or hide the list menu. Change the HTML to this:
<nav class="navbar navbar-default navbar-fixed-top"> <div class="navbar-header"> <a class="navbar-brand" href="landing_page.html">Company name</a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> </div> <div id="nav-menu" class="collapse navbar-collapse navbar-right"> <ul class="nav navbar-nav"> <li><a href="#about">About</a></li> <li><a href="#features">Features</a></li> <li><a href="#pricing">Pricing</a></li> <li><a href="contact.html">Contact</a></li> </ul> </div> </nav>
The new code is in bold. First, we added a <button>
element to create our sandwich button (the one with three dashes). On data-target
, we must add the element that is the collapse target, #nav-menu
in our case.
Then, we must say which is the element to be collapsed in the small viewport, so for .navbar-right
, we added the .collapse.navbar-collapse
classes. The navigation bar should then appear like the one shown in the following screenshot. Hooray! Bootstrap has saved the day again!

For this example, we fixed the navigation bar to the top of our web page, although we can use different attachments. For instance, we can attach the navigation bar to the bottom using the .navbar-fixed-bottom
class.
The bar can also be static. For that, use the .navbar-static-*
class, where the asterisk can mean top
or bottom
. If you are using the static navigation bars, you must place a container (static or fluid) right in the next level of the component:
<nav class="navbar navbar-default navbar-static-top"> <div class="container"> … </div> </nav>
You can also change the color of the navigation bar. Bootstrap version 3 offers an inverted set of colors. To do so, add the .navbar-inverse
class to the <nav>
element, as follows:
<nav class="navbar navbar-inverse"> … </nav>
In version 4, they added other color options. So if the background of your navigation bar has a dark color, add the .navbar-dark
class to make the text and other elements white. If the background has a light color, use the .navbar-light
class to get the opposite result.
For the background color, you can pass a class called .bg-*
, where the asterisk means a set of colors from Bootstrap. These are default
, primary
, info
, success
, warning
, or danger
:
<nav class="navbar navbar-dark bg-danger"> … </nav>
Until the navigation collapse
Try to resize the web page and you will see that for small viewports, the horizontal list placed in the navigation will stack vertically, as illustrated in the next screenshot. Fortunately, Bootstrap has the option to collapse the lists at the navigation bar. The procedure for doing this is pretty simple and we will do it now.

So, let's make the .nav-header
collapses and create a toggle
button to show or hide the list menu. Change the HTML to this:
<nav class="navbar navbar-default navbar-fixed-top"> <div class="navbar-header"> <a class="navbar-brand" href="landing_page.html">Company name</a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> </div> <div id="nav-menu" class="collapse navbar-collapse navbar-right"> <ul class="nav navbar-nav"> <li><a href="#about">About</a></li> <li><a href="#features">Features</a></li> <li><a href="#pricing">Pricing</a></li> <li><a href="contact.html">Contact</a></li> </ul> </div> </nav>
The new code is in bold. First, we added a <button>
element to create our sandwich button (the one with three dashes). On data-target
, we must add the element that is the collapse target, #nav-menu
in our case.
Then, we must say which is the element to be collapsed in the small viewport, so for .navbar-right
, we added the .collapse.navbar-collapse
classes. The navigation bar should then appear like the one shown in the following screenshot. Hooray! Bootstrap has saved the day again!

For this example, we fixed the navigation bar to the top of our web page, although we can use different attachments. For instance, we can attach the navigation bar to the bottom using the .navbar-fixed-bottom
class.
The bar can also be static. For that, use the .navbar-static-*
class, where the asterisk can mean top
or bottom
. If you are using the static navigation bars, you must place a container (static or fluid) right in the next level of the component:
<nav class="navbar navbar-default navbar-static-top"> <div class="container"> … </div> </nav>
You can also change the color of the navigation bar. Bootstrap version 3 offers an inverted set of colors. To do so, add the .navbar-inverse
class to the <nav>
element, as follows:
<nav class="navbar navbar-inverse"> … </nav>
In version 4, they added other color options. So if the background of your navigation bar has a dark color, add the .navbar-dark
class to make the text and other elements white. If the background has a light color, use the .navbar-light
class to get the opposite result.
For the background color, you can pass a class called .bg-*
, where the asterisk means a set of colors from Bootstrap. These are default
, primary
, info
, success
, warning
, or danger
:
<nav class="navbar navbar-dark bg-danger"> … </nav>
Using different attachments
For this example, we fixed the navigation bar to the top of our web page, although we can use different attachments. For instance, we can attach the navigation bar to the bottom using the .navbar-fixed-bottom
class.
The bar can also be static. For that, use the .navbar-static-*
class, where the asterisk can mean top
or bottom
. If you are using the static navigation bars, you must place a container (static or fluid) right in the next level of the component:
<nav class="navbar navbar-default navbar-static-top"> <div class="container"> … </div> </nav>
You can also change the color of the navigation bar. Bootstrap version 3 offers an inverted set of colors. To do so, add the .navbar-inverse
class to the <nav>
element, as follows:
<nav class="navbar navbar-inverse"> … </nav>
In version 4, they added other color options. So if the background of your navigation bar has a dark color, add the .navbar-dark
class to make the text and other elements white. If the background has a light color, use the .navbar-light
class to get the opposite result.
For the background color, you can pass a class called .bg-*
, where the asterisk means a set of colors from Bootstrap. These are default
, primary
, info
, success
, warning
, or danger
:
<nav class="navbar navbar-dark bg-danger"> … </nav>
Coloring the bar
You can also change the color of the navigation bar. Bootstrap version 3 offers an inverted set of colors. To do so, add the .navbar-inverse
class to the <nav>
element, as follows:
<nav class="navbar navbar-inverse"> … </nav>
In version 4, they added other color options. So if the background of your navigation bar has a dark color, add the .navbar-dark
class to make the text and other elements white. If the background has a light color, use the .navbar-light
class to get the opposite result.
For the background color, you can pass a class called .bg-*
, where the asterisk means a set of colors from Bootstrap. These are default
, primary
, info
, success
, warning
, or danger
:
<nav class="navbar navbar-dark bg-danger"> … </nav>
It is time to go back to the buttons once more. Now we will use the buttons dropdown. Button dropdowns are great for grouping a set of options in a single button. It can be used in several situations.
To make use of these, you just need to make some small markups and class usages. We will also go a little further and add a button dropdown to our new navigation bar. The complete HTML code of the <nav>
tag is this one:
<nav class="navbar navbar-default navbar-fixed-top"> <div class="navbar-header"> <a class="navbar-brand" href="landing_page.html">Company name</a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <!-- <a class="btn btn-primary navbar-btn pull-right" href="#" role="button">Sign up</a> --> </div> <div class="btn-group pull-right"> <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Customer area <span class="caret"></span> </button> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul> </div> <div id="nav-menu" class="collapse navbar-collapse navbar-right"> <ul class="nav navbar-nav"> <li><a href="#about">About</a></li> <li><a href="#features">Features</a></li> <li><a href="#pricing">Pricing</a></li> <li><a href="contact.html">Contact</a></li> </ul> </div> </nav>
The highlighted code is the new one for the drop-down button. We have to create a <button>
, followed by a list <ul>
, all of that wrapped by a div.btn-group
. It is a pretty strict piece of code that should be used for these components.
Regarding the CSS, we must add some spacing between the button and the list. So, the CSS for the button drop-down is as follows:
nav .btn-group { margin: 0.8rem 2rem 0 0; }
The result for the button is presented in the following screenshot:

Oops! If you see the example for large devices, the new button looks pretty good, although it looks badly placed for small devices. Let's fix this with a media
query!
@media(max-width: 48em){ nav .btn-group { position: absolute; top: 0; right: 4em; } }
After the fix, the output that you get should be as shown in this screenshot:

The Bootstrap buttons dropdown offers some custom options. The first one that we will discuss is the split option. To do this, you need to change your HTML a bit:
<div class="btn-group pull-right">
<button type="button" class="btn btn-primary">Customer area</button>
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>
The main difference is the bold text, where we create another button, which will be responsible for the split effect, as shown in the following screenshot:

Moving on, you can make the drop-down a "drop-up". To do that, simply add the class to div.btn-group
:
<div class="btn-group dropup"> ... </div>
Customizing buttons dropdown
The Bootstrap buttons dropdown offers some custom options. The first one that we will discuss is the split option. To do this, you need to change your HTML a bit:
<div class="btn-group pull-right">
<button type="button" class="btn btn-primary">Customer area</button>
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>
The main difference is the bold text, where we create another button, which will be responsible for the split effect, as shown in the following screenshot:

Moving on, you can make the drop-down a "drop-up". To do that, simply add the class to div.btn-group
:
<div class="btn-group dropup"> ... </div>
As we discussed in the last chapter, it is possible to group components together with inputs, as we did to the sign form in the home page. However, it is possible to add even more things to inputs. We will talk about some group options that can be useful.
First of all, let's exemplify the usage of grouping inputs and buttons. The main idea is almost the same—creating a div.input-group
, and creating an input and a button inside this element, as shown in this HTML code:
<div class="input-group"> <input type="text" class="form-control" placeholder="Type the page title..."> <span class="input-group-btn"> <button class="btn btn-success" type="button">Search</button> </span> </div>
The output of the preceding code is shown in the following screenshot:

The only trick here is to add a <span>
element wrapping the button. If you invert the input order with the button, you will prepend the button to the input:
<div class="input-group"> <span class="input-group-btn"> <button class="btn btn-success" type="button">Search</button> </span> <input type="text" class="form-control" placeholder="Type the page title..."> </div>
The output of the preceding code is shown in this screenshot:

Bootstrap also gives us the possibility to add any other kind of button. To exemplify this, let's now add a button dropdown grouped with an input. Replace <button>
with the button dropdown that we just used in the previous example:
<div class="input-group"> <span class="input-group-btn"> <div class="btn-group pull-right"> <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Customer area <span class="caret"></span> </button> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li role="separator" class="divider"></li> <li><a href="#">Separated link</a></li> </ul> </div> </span> <input type="text" class="form-control" placeholder="Type the page title..."> </div>
It is pretty simple; you can add almost any kind of button, prepended or appended in an input. The following screenshot shows the result of the previous HTML code:

In version 4 of Bootstrap, flexbox support has finally arrived! However, it is an opt-in that can be used. The first step is to understand a little bit of flexbox, just in case you don't know, and then start using it.
We will not add any other element to our landing page example, since support for flexbox just begun with Bootstrap 4. We will cover it only to clarify this new option.
The definition of flexbox came out with the CSS3 specifications. Its main purpose is to better organize elements in a web page in a predictable manner. It can be seen as an option similar to float
but one that offers a lot more choices, such as reordering elements and avoiding known issues of float, for example, the clearfix
workaround.
For a hierarchical organization, first of all, you need to wrap the element of all the flex items (such as the columns inside a .row
). It is also possible to play with the direction and axis from the wrapping element.
To exemplify the usage, let's create an HTML example. Create another file, named flexbox.html
, use your base template and place the HTML code inside the <body>
tag:
<body> <div class="wrapping-flex"> <div class="item1">Item 1</div> <div class="item2">Item 2</div> <div class="item3">Item 3</div> </div> </body>
So, in this case, we must make the div.wrapping-flex
the flex wrapping element. Apply the following CSS and you will get the child elements placed inline:
.wrapping-flex { display: -webkit-flex; display: flex; background-color: #CCC; } .wrapping-flex > div { background-color: #ECA45A; margin: 1rem; padding: 1.5rem; }
Create this is a sample HTML page and you will get the following output:

There are a plenty of options for flexbox. I do recommend the guide at https://css-tricks.com/snippets/css/a-guide-to-flexbox/ for you to learn more about flexbox, since it is not our focus.
However, let's show a very powerful use case of flexbox. Have you ever faced a problem with aligning one div
inside another vertically? I hope not, because it can be a pain in the neck, even more if you made it for older browsers.
With flexbox, we just have to apply the following CSS:
.wrapping-flex { display: -webkit-flex; display: flex; background-color: #CCC; height: 12rem; width: 50%; margin-left: 20%; } .wrapping-flex > div { background-color: #ECA45A; margin: 1rem; padding: 1.5rem; } .wrapping-flex .item2 { align-self: center; height: 5rem; }
We added a height: 12rem
to the wrapping element and set align-self: center
and height: 5rem
to the .item2
element. With that, we align the second flex child <div>
in the center, while the other two children continue to occupy the full height, as shown in the following screenshot:

Version 4 of Bootstrap provides two ways to use flexbox. The first one is with Sass, where you need to set the $enable-flex
variable to the true
state.
The other option is to download the compiled CSS version using the flex opt-in. The compiled version can be found in the Bootstrap repository (https://github.com/twbs/bootstrap/releases).
With regard to using flexbox, you will have limited browser support, since not all browsers are ready for this property. Consider using it if you will have access only from new browsers, such as Internet Explorer versions newer than v10.
Check out the currently available support for the flexbox property here:
Understanding flexbox
The definition of flexbox came out with the CSS3 specifications. Its main purpose is to better organize elements in a web page in a predictable manner. It can be seen as an option similar to float
but one that offers a lot more choices, such as reordering elements and avoiding known issues of float, for example, the clearfix
workaround.
For a hierarchical organization, first of all, you need to wrap the element of all the flex items (such as the columns inside a .row
). It is also possible to play with the direction and axis from the wrapping element.
To exemplify the usage, let's create an HTML example. Create another file, named flexbox.html
, use your base template and place the HTML code inside the <body>
tag:
<body> <div class="wrapping-flex"> <div class="item1">Item 1</div> <div class="item2">Item 2</div> <div class="item3">Item 3</div> </div> </body>
So, in this case, we must make the div.wrapping-flex
the flex wrapping element. Apply the following CSS and you will get the child elements placed inline:
.wrapping-flex { display: -webkit-flex; display: flex; background-color: #CCC; } .wrapping-flex > div { background-color: #ECA45A; margin: 1rem; padding: 1.5rem; }
Create this is a sample HTML page and you will get the following output:

There are a plenty of options for flexbox. I do recommend the guide at https://css-tricks.com/snippets/css/a-guide-to-flexbox/ for you to learn more about flexbox, since it is not our focus.
However, let's show a very powerful use case of flexbox. Have you ever faced a problem with aligning one div
inside another vertically? I hope not, because it can be a pain in the neck, even more if you made it for older browsers.
With flexbox, we just have to apply the following CSS:
.wrapping-flex { display: -webkit-flex; display: flex; background-color: #CCC; height: 12rem; width: 50%; margin-left: 20%; } .wrapping-flex > div { background-color: #ECA45A; margin: 1rem; padding: 1.5rem; } .wrapping-flex .item2 { align-self: center; height: 5rem; }
We added a height: 12rem
to the wrapping element and set align-self: center
and height: 5rem
to the .item2
element. With that, we align the second flex child <div>
in the center, while the other two children continue to occupy the full height, as shown in the following screenshot:

Version 4 of Bootstrap provides two ways to use flexbox. The first one is with Sass, where you need to set the $enable-flex
variable to the true
state.
The other option is to download the compiled CSS version using the flex opt-in. The compiled version can be found in the Bootstrap repository (https://github.com/twbs/bootstrap/releases).
With regard to using flexbox, you will have limited browser support, since not all browsers are ready for this property. Consider using it if you will have access only from new browsers, such as Internet Explorer versions newer than v10.
Check out the currently available support for the flexbox property here:
Playing with Bootstrap and flexbox
Version 4 of Bootstrap provides two ways to use flexbox. The first one is with Sass, where you need to set the $enable-flex
variable to the true
state.
The other option is to download the compiled CSS version using the flex opt-in. The compiled version can be found in the Bootstrap repository (https://github.com/twbs/bootstrap/releases).
With regard to using flexbox, you will have limited browser support, since not all browsers are ready for this property. Consider using it if you will have access only from new browsers, such as Internet Explorer versions newer than v10.
Check out the currently available support for the flexbox property here:
In this chapter, we took a big step towards more complex elements and theory. You deserve congratulations for nailing the first example of this book!
First, we presented icons in Bootstrap! It is a very handy tool to place the perfect icon in a perfect way on your page, by customizing the icon size and color. In version 4 of Bootstrap, they dropped native support for Glyphicons, even though you can still use it as a third-party library.
Then we touched the navigations bar of Bootstrap and presented a bunch of options to customize it for our case. We played with some tricks to collapse the menu in the navigation bar, and added more components to it, such as the button dropdown.
Moreover, we again talked about input grouping by showing some more examples of its usage, such as a group of an input and a button.
Finally, we added some theory to the soup, by introducing flexbox and showing that you can use it in conjunction with Bootstrap in the new version 4.
In the next chapters, we will dive into another example. We will start creating a web app! For that, expect the use of even more Bootstrap elements and components. By the end of the explanation, you will be qualified to create any web application!
Among all kinds of web pages, the web application is the one with the fastest growth in usage. So, we will take a deep dive into this area by developing a really nice web application. Actually, Bootstrap was mainly designed for this type of application, since it was developed at first for the Twitter web application.
Therefore, in this chapter and in the next ones, we will take the reverse path. Instead of developing Bootstrap for Twitter, we will develop an app like Twitter with Bootstrap. With that, we will touch upon even more components and elements of Bootstrap, as follows:
- Web application definitions
- A fully customized navigation bar
- Cards
- Thumbnails
- Pagination
- Breadcrumbs
This chapter will be a bit more difficult, but I believe you are ready for this. So, can you build a web app?
Web applications came from the mix of an application and a browser, of course! Basically, a web application is a client application that runs on a web browser. Thus most of the processes are done on the client machine and the server is just responsible for the data processing.
This is interesting, since you can always deliver to the client the most updated version of the application, while the client does not need to upgrade the software. This leads to fast-paced and continuous development of the app.
Just as we always say when starting a new example, let's use the HTML boilerplate that we always use, keeping the same folder structure and so on:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Web App</title> <link rel="stylesheet" href="css/bootstrap.css"> <link rel="stylesheet" href="css/base.css"> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"> </script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"> </script> <![endif]--> </head> <body> <script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> <script src="js/main.js"></script> </body> </html>
First of all, we will add the navigation bar to our web application. Before the start of the <body>
tag, add the navigation bar, just as we did in the last chapter:
<nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <!-- <a class="btn btn-primary navbar-btn pull-left" href="#" role="button">Sign up</a> --> </div> <div id="nav-menu" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> </ul> </div> </div> </nav>
First, we created a simple navigation bar with the collapse option, just as we did in the last chapter. The major difference this time is the addition of the image <img src="imgs/logo.png" class="img-responsive">
logo. The CSS for adjusting the logo is as follows:
.navbar-brand img { height: 100% }
So, we need to create the items inside the list ul.nav.navbar-nav
tag. Append the following code inside the list:
<ul class="nav navbar-nav"> <li> <a href="#"> Home </a> </li> <li> <a href="#"> Notifications </a> </li> <li> <a href="#"> Messages </a> </li> </ul>
Therefore, we should add some icons to each menu. Do you remember how to do this? We need to use the Bootstrap Glyphicons. Add the icons, as highlighted in this HTML code:
<ul class="nav navbar-nav"> <li> <a href="#"> <span class="glyphicon glyphicon-home" aria-hidden="true"></span> Home </a> </li> <li> <a href="#"> <span class="glyphicon glyphicon-bell" aria-hidden="true"></span> Notifications </a> </li> <li> <a href="#"> <span class="glyphicon glyphicon-envelope" aria-hidden="true"></span> Messages </a> </li> </ul>
The result right now should look like what is shown in the following screenshot:

In our navigation bar, we will add a search input. There are two tricks for this. The first is the input must be like an input group to have a magnifier icon on the right-hand-side part. The second is that the input must be aligned to the right and not to the left in the <nav>
. In the HTML, let's create a form after ul.nav.navbar-nav
:
<div id="nav-menu" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> … </ul> <form id="search" role="search"> <div class="input-group"> <input type="text" class="form-control" placeholder="Search..."> <span class="glyphicon glyphicon-search" aria-hidden="true"></span> </div> </form> </div>
In the CSS, move the form to the right and add some padding:
nav form#search { float: right; padding: 0.5em; } nav form#search .glyphicon-search { z-index: 99; position: absolute; right: 0.7em; top: 50%; margin-top: -0.44em; } nav form#search .input-group .form-control { border-radius: 0.25em; }
Refresh the web page and check out the input. It should appear as shown in this screenshot:

Our navigation bar is starting to appear like the navigation bar of a web application, but not close enough! Now, it's the turn of the menu options.
We will now do some crazy stuff: add a thumbnail together with a Bootstrap button dropdown. Just before form#search
, add the button HTML:
<div id="nav-options" class="btn-group pull-right"> <button type="button" class="btn btn-default dropdown-toggle thumbnail" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <img src="imgs/jon.png"> </button> <ul class="dropdown-menu"> <li><a href="#">Profile</a></li> <li><a href="#">Setting</a></li> <li role="separator" class="divider"></li> <li><a href="#">Logout</a></li> </ul> </div>
Basically, we used the template for a button dropdown (which you learned about in the previous chapter) and just removed the .caret
component present on it. Instead of adding some text, we added an image, that is, the profile image. In .btn-group
, we applied the helper class from Bootstrap, .pull-right
. Since it was placed before the form, the button will appear after the form.
Then, it's time for the CSS. We need to resize the image and properly set the margins and paddings:
#nav-options { margin: 0.5em; } #nav-options button.thumbnail { margin: 0; padding: 0; } #nav-options img { max-height: 2.3em; border-radius: 0.3em; }
The result of the addition of the button should be like what is shown in the following screenshot:

The last element present in the navigation bar is the Tweet button. To add it, we set following the HTML right before the button group option that we just added:
<button id="tweet" class="btn btn-default pull-right"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button>
For the CSS, we just need to add some margin:
#tweet { margin: 0.5em; }
Finally, we have all the elements and components in our navigation bar, and it should look like this:

Now that we have our navigation bar done, it's time to customize the Bootstrap theme, add some tweaks, and fix viewport issues.
To be a little different, we will use a blue background color for our navigation bar. First, we need to add some simple CSS rules:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; }
Afterwards, let's add the active option to the list on the navigation. Add the .active
class to the first element of the nav
list (the Home one), presented in bold in the following code:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
… <!--others li and the rest of the code -->
</ul>
Then, go to the CSS and set the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 10px; border-bottom: 5px solid #FFF; }
The result of this should be like the one presented in the following screenshot. You can see that Home is in the active state. To mark that, we've added a border below it for denotation:

If you hover over any element in the navigation list, you will see that it has the wrong color. We will use some style to fix that—by using CSS3 transitions! The complete CSS for the customization should be like the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:hover { color: #FFF; -webkit-transition: all 150ms ease-in-out; -moz-transition: all 150ms ease-in-out; -ms-transition: all 150ms ease-in-out; -o-transition: all 150ms ease-in-out; transition: all 150ms ease-in-out; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 0.62em; border-bottom: 0.45em solid #FFF;} .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > li > a:hover { background-color: transparent; color: #F3F3F3; padding-bottom: 0.62em; border-bottom: 0.45em solid #F3F3F3; }
Here, we had to change the default colors from the default Bootstrap navigation list. Also, by adding the transitions, we got a nice effect; when the user hovers over the menu, a border appears at the bottom of the item list.
To finish the navigation bar, it would be nice to add some badges to the notifications item in the up list to show the number of new notifications, just as Twitter has on its website. For that, you will learn to use Bootstrap badges.
So, in the notifications item in the list, add the following highlighted HTML line:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
</ul>
For the CSS, set some positions, paddings, and borders:
.navbar-nav .badge { color: #2F92CA; background-color: #FFF; font-size: 0.7em; padding: 0.27rem 0.55rem 0.2rem 0.4rem; position: absolute; left: 0.37rem; top: 0.7rem; z-index: 99; border: 0.2rem solid #2F92CA; }
Nicely done! Refresh the browser and you will see this pretty, beautiful badge:

We now have three issues with the navigation bar. Can you guess them?
They are the Tweet button at the small viewport, the collapsed navigation menu collapse, and the color of the collapse hamburger button.
Well, first we will handle the easiest one—fix the Tweet button! For that, we will create another element to be placed at the left-hand side of the collapse button and just display it when they are in extra small resolution. First, add the .hidden-xs
class to the current Tweet
button:
<button id="tweet" class="btn btn-default pull-right hidden-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
Secondly, at .navbar-header
, after button.navbar-toggle
, add the following highlighted button:
<div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button id="tweet" class="btn btn-default pull-right visible-xs-block"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button> </div>
So, what we did is hide the Tweet button for extra small devices and show a new one in a different element. Set a mobile viewport and you can see the button's position fixed, as follows:

Next, let's fix the color of the collapse hamburger button. Just apply the next CSS to change its color:
.navbar-header .navbar-toggle, .navbar-default .navbar-toggle:focus { background-color: #57A5D2; } .navbar-default .navbar-toggle:hover { background-color: #3986B3; } .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; }
Finally, let's customize the collapsed navigation bar using Bootstrap helpers. We add the .hidden-xs
class to .nav-options
and the .hidden-sm
class to the form#search
element, making them invisible for extra small and small devices respectively, just as we did to the Tweet button:
<div id="nav-options" class="btn-group pull-right hidden-xs"> … </div> <form id="search" role="search" class="hidden-sm"> … </form>
Then, in the ul.nav.navbar-nav
navigation list, create two items that will replace the ones hidden at the current viewport:
<ul class="nav navbar-nav"> ... <!-- others elements list were hidden --> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profile </a> </li> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout </a> </li> </ul>
Thus we are making them visible for extra small resolution with the .visible.xs-inline
class, as long they are from an inline list.
To wrap it up, let's remove the border in the active list item, since it does not seem nice at the bottom in the layout. Let's change it to a right border instead of bottom with the following CSS using a media query:
@media(max-width:34em){ .navbar-default .navbar-nav > .active > a { border-bottom: none; border-left: 0.45em solid #FFF; padding-left: 0.5em; } }
And we are done! Refresh the web page and see the final result of the navigation bar. It is awesome!

Adding the search input
In our navigation bar, we will add a search input. There are two tricks for this. The first is the input must be like an input group to have a magnifier icon on the right-hand-side part. The second is that the input must be aligned to the right and not to the left in the <nav>
. In the HTML, let's create a form after ul.nav.navbar-nav
:
<div id="nav-menu" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> … </ul> <form id="search" role="search"> <div class="input-group"> <input type="text" class="form-control" placeholder="Search..."> <span class="glyphicon glyphicon-search" aria-hidden="true"></span> </div> </form> </div>
In the CSS, move the form to the right and add some padding:
nav form#search { float: right; padding: 0.5em; } nav form#search .glyphicon-search { z-index: 99; position: absolute; right: 0.7em; top: 50%; margin-top: -0.44em; } nav form#search .input-group .form-control { border-radius: 0.25em; }
Refresh the web page and check out the input. It should appear as shown in this screenshot:

Our navigation bar is starting to appear like the navigation bar of a web application, but not close enough! Now, it's the turn of the menu options.
We will now do some crazy stuff: add a thumbnail together with a Bootstrap button dropdown. Just before form#search
, add the button HTML:
<div id="nav-options" class="btn-group pull-right"> <button type="button" class="btn btn-default dropdown-toggle thumbnail" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <img src="imgs/jon.png"> </button> <ul class="dropdown-menu"> <li><a href="#">Profile</a></li> <li><a href="#">Setting</a></li> <li role="separator" class="divider"></li> <li><a href="#">Logout</a></li> </ul> </div>
Basically, we used the template for a button dropdown (which you learned about in the previous chapter) and just removed the .caret
component present on it. Instead of adding some text, we added an image, that is, the profile image. In .btn-group
, we applied the helper class from Bootstrap, .pull-right
. Since it was placed before the form, the button will appear after the form.
Then, it's time for the CSS. We need to resize the image and properly set the margins and paddings:
#nav-options { margin: 0.5em; } #nav-options button.thumbnail { margin: 0; padding: 0; } #nav-options img { max-height: 2.3em; border-radius: 0.3em; }
The result of the addition of the button should be like what is shown in the following screenshot:

The last element present in the navigation bar is the Tweet button. To add it, we set following the HTML right before the button group option that we just added:
<button id="tweet" class="btn btn-default pull-right"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button>
For the CSS, we just need to add some margin:
#tweet { margin: 0.5em; }
Finally, we have all the elements and components in our navigation bar, and it should look like this:

Now that we have our navigation bar done, it's time to customize the Bootstrap theme, add some tweaks, and fix viewport issues.
To be a little different, we will use a blue background color for our navigation bar. First, we need to add some simple CSS rules:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; }
Afterwards, let's add the active option to the list on the navigation. Add the .active
class to the first element of the nav
list (the Home one), presented in bold in the following code:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
… <!--others li and the rest of the code -->
</ul>
Then, go to the CSS and set the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 10px; border-bottom: 5px solid #FFF; }
The result of this should be like the one presented in the following screenshot. You can see that Home is in the active state. To mark that, we've added a border below it for denotation:

If you hover over any element in the navigation list, you will see that it has the wrong color. We will use some style to fix that—by using CSS3 transitions! The complete CSS for the customization should be like the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:hover { color: #FFF; -webkit-transition: all 150ms ease-in-out; -moz-transition: all 150ms ease-in-out; -ms-transition: all 150ms ease-in-out; -o-transition: all 150ms ease-in-out; transition: all 150ms ease-in-out; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 0.62em; border-bottom: 0.45em solid #FFF;} .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > li > a:hover { background-color: transparent; color: #F3F3F3; padding-bottom: 0.62em; border-bottom: 0.45em solid #F3F3F3; }
Here, we had to change the default colors from the default Bootstrap navigation list. Also, by adding the transitions, we got a nice effect; when the user hovers over the menu, a border appears at the bottom of the item list.
To finish the navigation bar, it would be nice to add some badges to the notifications item in the up list to show the number of new notifications, just as Twitter has on its website. For that, you will learn to use Bootstrap badges.
So, in the notifications item in the list, add the following highlighted HTML line:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
</ul>
For the CSS, set some positions, paddings, and borders:
.navbar-nav .badge { color: #2F92CA; background-color: #FFF; font-size: 0.7em; padding: 0.27rem 0.55rem 0.2rem 0.4rem; position: absolute; left: 0.37rem; top: 0.7rem; z-index: 99; border: 0.2rem solid #2F92CA; }
Nicely done! Refresh the browser and you will see this pretty, beautiful badge:

We now have three issues with the navigation bar. Can you guess them?
They are the Tweet button at the small viewport, the collapsed navigation menu collapse, and the color of the collapse hamburger button.
Well, first we will handle the easiest one—fix the Tweet button! For that, we will create another element to be placed at the left-hand side of the collapse button and just display it when they are in extra small resolution. First, add the .hidden-xs
class to the current Tweet
button:
<button id="tweet" class="btn btn-default pull-right hidden-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
Secondly, at .navbar-header
, after button.navbar-toggle
, add the following highlighted button:
<div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button id="tweet" class="btn btn-default pull-right visible-xs-block"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button> </div>
So, what we did is hide the Tweet button for extra small devices and show a new one in a different element. Set a mobile viewport and you can see the button's position fixed, as follows:

Next, let's fix the color of the collapse hamburger button. Just apply the next CSS to change its color:
.navbar-header .navbar-toggle, .navbar-default .navbar-toggle:focus { background-color: #57A5D2; } .navbar-default .navbar-toggle:hover { background-color: #3986B3; } .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; }
Finally, let's customize the collapsed navigation bar using Bootstrap helpers. We add the .hidden-xs
class to .nav-options
and the .hidden-sm
class to the form#search
element, making them invisible for extra small and small devices respectively, just as we did to the Tweet button:
<div id="nav-options" class="btn-group pull-right hidden-xs"> … </div> <form id="search" role="search" class="hidden-sm"> … </form>
Then, in the ul.nav.navbar-nav
navigation list, create two items that will replace the ones hidden at the current viewport:
<ul class="nav navbar-nav"> ... <!-- others elements list were hidden --> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profile </a> </li> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout </a> </li> </ul>
Thus we are making them visible for extra small resolution with the .visible.xs-inline
class, as long they are from an inline list.
To wrap it up, let's remove the border in the active list item, since it does not seem nice at the bottom in the layout. Let's change it to a right border instead of bottom with the following CSS using a media query:
@media(max-width:34em){ .navbar-default .navbar-nav > .active > a { border-bottom: none; border-left: 0.45em solid #FFF; padding-left: 0.5em; } }
And we are done! Refresh the web page and see the final result of the navigation bar. It is awesome!

Time for the menu options!
Our navigation bar is starting to appear like the navigation bar of a web application, but not close enough! Now, it's the turn of the menu options.
We will now do some crazy stuff: add a thumbnail together with a Bootstrap button dropdown. Just before form#search
, add the button HTML:
<div id="nav-options" class="btn-group pull-right"> <button type="button" class="btn btn-default dropdown-toggle thumbnail" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <img src="imgs/jon.png"> </button> <ul class="dropdown-menu"> <li><a href="#">Profile</a></li> <li><a href="#">Setting</a></li> <li role="separator" class="divider"></li> <li><a href="#">Logout</a></li> </ul> </div>
Basically, we used the template for a button dropdown (which you learned about in the previous chapter) and just removed the .caret
component present on it. Instead of adding some text, we added an image, that is, the profile image. In .btn-group
, we applied the helper class from Bootstrap, .pull-right
. Since it was placed before the form, the button will appear after the form.
Then, it's time for the CSS. We need to resize the image and properly set the margins and paddings:
#nav-options { margin: 0.5em; } #nav-options button.thumbnail { margin: 0; padding: 0; } #nav-options img { max-height: 2.3em; border-radius: 0.3em; }
The result of the addition of the button should be like what is shown in the following screenshot:

The last element present in the navigation bar is the Tweet button. To add it, we set following the HTML right before the button group option that we just added:
<button id="tweet" class="btn btn-default pull-right"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button>
For the CSS, we just need to add some margin:
#tweet { margin: 0.5em; }
Finally, we have all the elements and components in our navigation bar, and it should look like this:

Now that we have our navigation bar done, it's time to customize the Bootstrap theme, add some tweaks, and fix viewport issues.
To be a little different, we will use a blue background color for our navigation bar. First, we need to add some simple CSS rules:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; }
Afterwards, let's add the active option to the list on the navigation. Add the .active
class to the first element of the nav
list (the Home one), presented in bold in the following code:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
… <!--others li and the rest of the code -->
</ul>
Then, go to the CSS and set the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 10px; border-bottom: 5px solid #FFF; }
The result of this should be like the one presented in the following screenshot. You can see that Home is in the active state. To mark that, we've added a border below it for denotation:

If you hover over any element in the navigation list, you will see that it has the wrong color. We will use some style to fix that—by using CSS3 transitions! The complete CSS for the customization should be like the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:hover { color: #FFF; -webkit-transition: all 150ms ease-in-out; -moz-transition: all 150ms ease-in-out; -ms-transition: all 150ms ease-in-out; -o-transition: all 150ms ease-in-out; transition: all 150ms ease-in-out; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 0.62em; border-bottom: 0.45em solid #FFF;} .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > li > a:hover { background-color: transparent; color: #F3F3F3; padding-bottom: 0.62em; border-bottom: 0.45em solid #F3F3F3; }
Here, we had to change the default colors from the default Bootstrap navigation list. Also, by adding the transitions, we got a nice effect; when the user hovers over the menu, a border appears at the bottom of the item list.
To finish the navigation bar, it would be nice to add some badges to the notifications item in the up list to show the number of new notifications, just as Twitter has on its website. For that, you will learn to use Bootstrap badges.
So, in the notifications item in the list, add the following highlighted HTML line:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
</ul>
For the CSS, set some positions, paddings, and borders:
.navbar-nav .badge { color: #2F92CA; background-color: #FFF; font-size: 0.7em; padding: 0.27rem 0.55rem 0.2rem 0.4rem; position: absolute; left: 0.37rem; top: 0.7rem; z-index: 99; border: 0.2rem solid #2F92CA; }
Nicely done! Refresh the browser and you will see this pretty, beautiful badge:

We now have three issues with the navigation bar. Can you guess them?
They are the Tweet button at the small viewport, the collapsed navigation menu collapse, and the color of the collapse hamburger button.
Well, first we will handle the easiest one—fix the Tweet button! For that, we will create another element to be placed at the left-hand side of the collapse button and just display it when they are in extra small resolution. First, add the .hidden-xs
class to the current Tweet
button:
<button id="tweet" class="btn btn-default pull-right hidden-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
Secondly, at .navbar-header
, after button.navbar-toggle
, add the following highlighted button:
<div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button id="tweet" class="btn btn-default pull-right visible-xs-block"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button> </div>
So, what we did is hide the Tweet button for extra small devices and show a new one in a different element. Set a mobile viewport and you can see the button's position fixed, as follows:

Next, let's fix the color of the collapse hamburger button. Just apply the next CSS to change its color:
.navbar-header .navbar-toggle, .navbar-default .navbar-toggle:focus { background-color: #57A5D2; } .navbar-default .navbar-toggle:hover { background-color: #3986B3; } .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; }
Finally, let's customize the collapsed navigation bar using Bootstrap helpers. We add the .hidden-xs
class to .nav-options
and the .hidden-sm
class to the form#search
element, making them invisible for extra small and small devices respectively, just as we did to the Tweet button:
<div id="nav-options" class="btn-group pull-right hidden-xs"> … </div> <form id="search" role="search" class="hidden-sm"> … </form>
Then, in the ul.nav.navbar-nav
navigation list, create two items that will replace the ones hidden at the current viewport:
<ul class="nav navbar-nav"> ... <!-- others elements list were hidden --> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profile </a> </li> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout </a> </li> </ul>
Thus we are making them visible for extra small resolution with the .visible.xs-inline
class, as long they are from an inline list.
To wrap it up, let's remove the border in the active list item, since it does not seem nice at the bottom in the layout. Let's change it to a right border instead of bottom with the following CSS using a media query:
@media(max-width:34em){ .navbar-default .navbar-nav > .active > a { border-bottom: none; border-left: 0.45em solid #FFF; padding-left: 0.5em; } }
And we are done! Refresh the web page and see the final result of the navigation bar. It is awesome!

The option at the thumbnail
We will now do some crazy stuff: add a thumbnail together with a Bootstrap button dropdown. Just before form#search
, add the button HTML:
<div id="nav-options" class="btn-group pull-right"> <button type="button" class="btn btn-default dropdown-toggle thumbnail" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <img src="imgs/jon.png"> </button> <ul class="dropdown-menu"> <li><a href="#">Profile</a></li> <li><a href="#">Setting</a></li> <li role="separator" class="divider"></li> <li><a href="#">Logout</a></li> </ul> </div>
Basically, we used the template for a button dropdown (which you learned about in the previous chapter) and just removed the .caret
component present on it. Instead of adding some text, we added an image, that is, the profile image. In .btn-group
, we applied the helper class from Bootstrap, .pull-right
. Since it was placed before the form, the button will appear after the form.
Then, it's time for the CSS. We need to resize the image and properly set the margins and paddings:
#nav-options { margin: 0.5em; } #nav-options button.thumbnail { margin: 0; padding: 0; } #nav-options img { max-height: 2.3em; border-radius: 0.3em; }
The result of the addition of the button should be like what is shown in the following screenshot:

The last element present in the navigation bar is the Tweet button. To add it, we set following the HTML right before the button group option that we just added:
<button id="tweet" class="btn btn-default pull-right"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button>
For the CSS, we just need to add some margin:
#tweet { margin: 0.5em; }
Finally, we have all the elements and components in our navigation bar, and it should look like this:

Now that we have our navigation bar done, it's time to customize the Bootstrap theme, add some tweaks, and fix viewport issues.
To be a little different, we will use a blue background color for our navigation bar. First, we need to add some simple CSS rules:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; }
Afterwards, let's add the active option to the list on the navigation. Add the .active
class to the first element of the nav
list (the Home one), presented in bold in the following code:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
… <!--others li and the rest of the code -->
</ul>
Then, go to the CSS and set the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 10px; border-bottom: 5px solid #FFF; }
The result of this should be like the one presented in the following screenshot. You can see that Home is in the active state. To mark that, we've added a border below it for denotation:

If you hover over any element in the navigation list, you will see that it has the wrong color. We will use some style to fix that—by using CSS3 transitions! The complete CSS for the customization should be like the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:hover { color: #FFF; -webkit-transition: all 150ms ease-in-out; -moz-transition: all 150ms ease-in-out; -ms-transition: all 150ms ease-in-out; -o-transition: all 150ms ease-in-out; transition: all 150ms ease-in-out; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 0.62em; border-bottom: 0.45em solid #FFF;} .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > li > a:hover { background-color: transparent; color: #F3F3F3; padding-bottom: 0.62em; border-bottom: 0.45em solid #F3F3F3; }
Here, we had to change the default colors from the default Bootstrap navigation list. Also, by adding the transitions, we got a nice effect; when the user hovers over the menu, a border appears at the bottom of the item list.
To finish the navigation bar, it would be nice to add some badges to the notifications item in the up list to show the number of new notifications, just as Twitter has on its website. For that, you will learn to use Bootstrap badges.
So, in the notifications item in the list, add the following highlighted HTML line:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
</ul>
For the CSS, set some positions, paddings, and borders:
.navbar-nav .badge { color: #2F92CA; background-color: #FFF; font-size: 0.7em; padding: 0.27rem 0.55rem 0.2rem 0.4rem; position: absolute; left: 0.37rem; top: 0.7rem; z-index: 99; border: 0.2rem solid #2F92CA; }
Nicely done! Refresh the browser and you will see this pretty, beautiful badge:

We now have three issues with the navigation bar. Can you guess them?
They are the Tweet button at the small viewport, the collapsed navigation menu collapse, and the color of the collapse hamburger button.
Well, first we will handle the easiest one—fix the Tweet button! For that, we will create another element to be placed at the left-hand side of the collapse button and just display it when they are in extra small resolution. First, add the .hidden-xs
class to the current Tweet
button:
<button id="tweet" class="btn btn-default pull-right hidden-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
Secondly, at .navbar-header
, after button.navbar-toggle
, add the following highlighted button:
<div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button id="tweet" class="btn btn-default pull-right visible-xs-block"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button> </div>
So, what we did is hide the Tweet button for extra small devices and show a new one in a different element. Set a mobile viewport and you can see the button's position fixed, as follows:

Next, let's fix the color of the collapse hamburger button. Just apply the next CSS to change its color:
.navbar-header .navbar-toggle, .navbar-default .navbar-toggle:focus { background-color: #57A5D2; } .navbar-default .navbar-toggle:hover { background-color: #3986B3; } .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; }
Finally, let's customize the collapsed navigation bar using Bootstrap helpers. We add the .hidden-xs
class to .nav-options
and the .hidden-sm
class to the form#search
element, making them invisible for extra small and small devices respectively, just as we did to the Tweet button:
<div id="nav-options" class="btn-group pull-right hidden-xs"> … </div> <form id="search" role="search" class="hidden-sm"> … </form>
Then, in the ul.nav.navbar-nav
navigation list, create two items that will replace the ones hidden at the current viewport:
<ul class="nav navbar-nav"> ... <!-- others elements list were hidden --> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profile </a> </li> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout </a> </li> </ul>
Thus we are making them visible for extra small resolution with the .visible.xs-inline
class, as long they are from an inline list.
To wrap it up, let's remove the border in the active list item, since it does not seem nice at the bottom in the layout. Let's change it to a right border instead of bottom with the following CSS using a media query:
@media(max-width:34em){ .navbar-default .navbar-nav > .active > a { border-bottom: none; border-left: 0.45em solid #FFF; padding-left: 0.5em; } }
And we are done! Refresh the web page and see the final result of the navigation bar. It is awesome!

Adding the Tweet button
The last element present in the navigation bar is the Tweet button. To add it, we set following the HTML right before the button group option that we just added:
<button id="tweet" class="btn btn-default pull-right"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button>
For the CSS, we just need to add some margin:
#tweet { margin: 0.5em; }
Finally, we have all the elements and components in our navigation bar, and it should look like this:

Now that we have our navigation bar done, it's time to customize the Bootstrap theme, add some tweaks, and fix viewport issues.
To be a little different, we will use a blue background color for our navigation bar. First, we need to add some simple CSS rules:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; }
Afterwards, let's add the active option to the list on the navigation. Add the .active
class to the first element of the nav
list (the Home one), presented in bold in the following code:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
… <!--others li and the rest of the code -->
</ul>
Then, go to the CSS and set the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 10px; border-bottom: 5px solid #FFF; }
The result of this should be like the one presented in the following screenshot. You can see that Home is in the active state. To mark that, we've added a border below it for denotation:

If you hover over any element in the navigation list, you will see that it has the wrong color. We will use some style to fix that—by using CSS3 transitions! The complete CSS for the customization should be like the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:hover { color: #FFF; -webkit-transition: all 150ms ease-in-out; -moz-transition: all 150ms ease-in-out; -ms-transition: all 150ms ease-in-out; -o-transition: all 150ms ease-in-out; transition: all 150ms ease-in-out; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 0.62em; border-bottom: 0.45em solid #FFF;} .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > li > a:hover { background-color: transparent; color: #F3F3F3; padding-bottom: 0.62em; border-bottom: 0.45em solid #F3F3F3; }
Here, we had to change the default colors from the default Bootstrap navigation list. Also, by adding the transitions, we got a nice effect; when the user hovers over the menu, a border appears at the bottom of the item list.
To finish the navigation bar, it would be nice to add some badges to the notifications item in the up list to show the number of new notifications, just as Twitter has on its website. For that, you will learn to use Bootstrap badges.
So, in the notifications item in the list, add the following highlighted HTML line:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
</ul>
For the CSS, set some positions, paddings, and borders:
.navbar-nav .badge { color: #2F92CA; background-color: #FFF; font-size: 0.7em; padding: 0.27rem 0.55rem 0.2rem 0.4rem; position: absolute; left: 0.37rem; top: 0.7rem; z-index: 99; border: 0.2rem solid #2F92CA; }
Nicely done! Refresh the browser and you will see this pretty, beautiful badge:

We now have three issues with the navigation bar. Can you guess them?
They are the Tweet button at the small viewport, the collapsed navigation menu collapse, and the color of the collapse hamburger button.
Well, first we will handle the easiest one—fix the Tweet button! For that, we will create another element to be placed at the left-hand side of the collapse button and just display it when they are in extra small resolution. First, add the .hidden-xs
class to the current Tweet
button:
<button id="tweet" class="btn btn-default pull-right hidden-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
Secondly, at .navbar-header
, after button.navbar-toggle
, add the following highlighted button:
<div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button id="tweet" class="btn btn-default pull-right visible-xs-block"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button> </div>
So, what we did is hide the Tweet button for extra small devices and show a new one in a different element. Set a mobile viewport and you can see the button's position fixed, as follows:

Next, let's fix the color of the collapse hamburger button. Just apply the next CSS to change its color:
.navbar-header .navbar-toggle, .navbar-default .navbar-toggle:focus { background-color: #57A5D2; } .navbar-default .navbar-toggle:hover { background-color: #3986B3; } .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; }
Finally, let's customize the collapsed navigation bar using Bootstrap helpers. We add the .hidden-xs
class to .nav-options
and the .hidden-sm
class to the form#search
element, making them invisible for extra small and small devices respectively, just as we did to the Tweet button:
<div id="nav-options" class="btn-group pull-right hidden-xs"> … </div> <form id="search" role="search" class="hidden-sm"> … </form>
Then, in the ul.nav.navbar-nav
navigation list, create two items that will replace the ones hidden at the current viewport:
<ul class="nav navbar-nav"> ... <!-- others elements list were hidden --> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profile </a> </li> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout </a> </li> </ul>
Thus we are making them visible for extra small resolution with the .visible.xs-inline
class, as long they are from an inline list.
To wrap it up, let's remove the border in the active list item, since it does not seem nice at the bottom in the layout. Let's change it to a right border instead of bottom with the following CSS using a media query:
@media(max-width:34em){ .navbar-default .navbar-nav > .active > a { border-bottom: none; border-left: 0.45em solid #FFF; padding-left: 0.5em; } }
And we are done! Refresh the web page and see the final result of the navigation bar. It is awesome!

Customizing the navigation bar
Now that we have our navigation bar done, it's time to customize the Bootstrap theme, add some tweaks, and fix viewport issues.
To be a little different, we will use a blue background color for our navigation bar. First, we need to add some simple CSS rules:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; }
Afterwards, let's add the active option to the list on the navigation. Add the .active
class to the first element of the nav
list (the Home one), presented in bold in the following code:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
… <!--others li and the rest of the code -->
</ul>
Then, go to the CSS and set the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 10px; border-bottom: 5px solid #FFF; }
The result of this should be like the one presented in the following screenshot. You can see that Home is in the active state. To mark that, we've added a border below it for denotation:

If you hover over any element in the navigation list, you will see that it has the wrong color. We will use some style to fix that—by using CSS3 transitions! The complete CSS for the customization should be like the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:hover { color: #FFF; -webkit-transition: all 150ms ease-in-out; -moz-transition: all 150ms ease-in-out; -ms-transition: all 150ms ease-in-out; -o-transition: all 150ms ease-in-out; transition: all 150ms ease-in-out; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 0.62em; border-bottom: 0.45em solid #FFF;} .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > li > a:hover { background-color: transparent; color: #F3F3F3; padding-bottom: 0.62em; border-bottom: 0.45em solid #F3F3F3; }
Here, we had to change the default colors from the default Bootstrap navigation list. Also, by adding the transitions, we got a nice effect; when the user hovers over the menu, a border appears at the bottom of the item list.
To finish the navigation bar, it would be nice to add some badges to the notifications item in the up list to show the number of new notifications, just as Twitter has on its website. For that, you will learn to use Bootstrap badges.
So, in the notifications item in the list, add the following highlighted HTML line:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
</ul>
For the CSS, set some positions, paddings, and borders:
.navbar-nav .badge { color: #2F92CA; background-color: #FFF; font-size: 0.7em; padding: 0.27rem 0.55rem 0.2rem 0.4rem; position: absolute; left: 0.37rem; top: 0.7rem; z-index: 99; border: 0.2rem solid #2F92CA; }
Nicely done! Refresh the browser and you will see this pretty, beautiful badge:

We now have three issues with the navigation bar. Can you guess them?
They are the Tweet button at the small viewport, the collapsed navigation menu collapse, and the color of the collapse hamburger button.
Well, first we will handle the easiest one—fix the Tweet button! For that, we will create another element to be placed at the left-hand side of the collapse button and just display it when they are in extra small resolution. First, add the .hidden-xs
class to the current Tweet
button:
<button id="tweet" class="btn btn-default pull-right hidden-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
Secondly, at .navbar-header
, after button.navbar-toggle
, add the following highlighted button:
<div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button id="tweet" class="btn btn-default pull-right visible-xs-block"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button> </div>
So, what we did is hide the Tweet button for extra small devices and show a new one in a different element. Set a mobile viewport and you can see the button's position fixed, as follows:

Next, let's fix the color of the collapse hamburger button. Just apply the next CSS to change its color:
.navbar-header .navbar-toggle, .navbar-default .navbar-toggle:focus { background-color: #57A5D2; } .navbar-default .navbar-toggle:hover { background-color: #3986B3; } .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; }
Finally, let's customize the collapsed navigation bar using Bootstrap helpers. We add the .hidden-xs
class to .nav-options
and the .hidden-sm
class to the form#search
element, making them invisible for extra small and small devices respectively, just as we did to the Tweet button:
<div id="nav-options" class="btn-group pull-right hidden-xs"> … </div> <form id="search" role="search" class="hidden-sm"> … </form>
Then, in the ul.nav.navbar-nav
navigation list, create two items that will replace the ones hidden at the current viewport:
<ul class="nav navbar-nav"> ... <!-- others elements list were hidden --> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profile </a> </li> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout </a> </li> </ul>
Thus we are making them visible for extra small resolution with the .visible.xs-inline
class, as long they are from an inline list.
To wrap it up, let's remove the border in the active list item, since it does not seem nice at the bottom in the layout. Let's change it to a right border instead of bottom with the following CSS using a media query:
@media(max-width:34em){ .navbar-default .navbar-nav > .active > a { border-bottom: none; border-left: 0.45em solid #FFF; padding-left: 0.5em; } }
And we are done! Refresh the web page and see the final result of the navigation bar. It is awesome!

Setting up the custom theme
To be a little different, we will use a blue background color for our navigation bar. First, we need to add some simple CSS rules:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; }
Afterwards, let's add the active option to the list on the navigation. Add the .active
class to the first element of the nav
list (the Home one), presented in bold in the following code:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
… <!--others li and the rest of the code -->
</ul>
Then, go to the CSS and set the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a { color: #FFF; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 10px; border-bottom: 5px solid #FFF; }
The result of this should be like the one presented in the following screenshot. You can see that Home is in the active state. To mark that, we've added a border below it for denotation:

If you hover over any element in the navigation list, you will see that it has the wrong color. We will use some style to fix that—by using CSS3 transitions! The complete CSS for the customization should be like the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:hover { color: #FFF; -webkit-transition: all 150ms ease-in-out; -moz-transition: all 150ms ease-in-out; -ms-transition: all 150ms ease-in-out; -o-transition: all 150ms ease-in-out; transition: all 150ms ease-in-out; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 0.62em; border-bottom: 0.45em solid #FFF;} .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > li > a:hover { background-color: transparent; color: #F3F3F3; padding-bottom: 0.62em; border-bottom: 0.45em solid #F3F3F3; }
Here, we had to change the default colors from the default Bootstrap navigation list. Also, by adding the transitions, we got a nice effect; when the user hovers over the menu, a border appears at the bottom of the item list.
To finish the navigation bar, it would be nice to add some badges to the notifications item in the up list to show the number of new notifications, just as Twitter has on its website. For that, you will learn to use Bootstrap badges.
So, in the notifications item in the list, add the following highlighted HTML line:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
</ul>
For the CSS, set some positions, paddings, and borders:
.navbar-nav .badge { color: #2F92CA; background-color: #FFF; font-size: 0.7em; padding: 0.27rem 0.55rem 0.2rem 0.4rem; position: absolute; left: 0.37rem; top: 0.7rem; z-index: 99; border: 0.2rem solid #2F92CA; }
Nicely done! Refresh the browser and you will see this pretty, beautiful badge:

We now have three issues with the navigation bar. Can you guess them?
They are the Tweet button at the small viewport, the collapsed navigation menu collapse, and the color of the collapse hamburger button.
Well, first we will handle the easiest one—fix the Tweet button! For that, we will create another element to be placed at the left-hand side of the collapse button and just display it when they are in extra small resolution. First, add the .hidden-xs
class to the current Tweet
button:
<button id="tweet" class="btn btn-default pull-right hidden-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
Secondly, at .navbar-header
, after button.navbar-toggle
, add the following highlighted button:
<div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button id="tweet" class="btn btn-default pull-right visible-xs-block"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button> </div>
So, what we did is hide the Tweet button for extra small devices and show a new one in a different element. Set a mobile viewport and you can see the button's position fixed, as follows:

Next, let's fix the color of the collapse hamburger button. Just apply the next CSS to change its color:
.navbar-header .navbar-toggle, .navbar-default .navbar-toggle:focus { background-color: #57A5D2; } .navbar-default .navbar-toggle:hover { background-color: #3986B3; } .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; }
Finally, let's customize the collapsed navigation bar using Bootstrap helpers. We add the .hidden-xs
class to .nav-options
and the .hidden-sm
class to the form#search
element, making them invisible for extra small and small devices respectively, just as we did to the Tweet button:
<div id="nav-options" class="btn-group pull-right hidden-xs"> … </div> <form id="search" role="search" class="hidden-sm"> … </form>
Then, in the ul.nav.navbar-nav
navigation list, create two items that will replace the ones hidden at the current viewport:
<ul class="nav navbar-nav"> ... <!-- others elements list were hidden --> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profile </a> </li> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout </a> </li> </ul>
Thus we are making them visible for extra small resolution with the .visible.xs-inline
class, as long they are from an inline list.
To wrap it up, let's remove the border in the active list item, since it does not seem nice at the bottom in the layout. Let's change it to a right border instead of bottom with the following CSS using a media query:
@media(max-width:34em){ .navbar-default .navbar-nav > .active > a { border-bottom: none; border-left: 0.45em solid #FFF; padding-left: 0.5em; } }
And we are done! Refresh the web page and see the final result of the navigation bar. It is awesome!

Fixing the list navigation bar pseudo-classes
If you hover over any element in the navigation list, you will see that it has the wrong color. We will use some style to fix that—by using CSS3 transitions! The complete CSS for the customization should be like the following:
.navbar-default { background-color: #2F92CA; } .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:hover { color: #FFF; -webkit-transition: all 150ms ease-in-out; -moz-transition: all 150ms ease-in-out; -ms-transition: all 150ms ease-in-out; -o-transition: all 150ms ease-in-out; transition: all 150ms ease-in-out; } .navbar-default .navbar-nav > .active > a { background-color: transparent; color: #FFF; padding-bottom: 0.62em; border-bottom: 0.45em solid #FFF;} .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > li > a:hover { background-color: transparent; color: #F3F3F3; padding-bottom: 0.62em; border-bottom: 0.45em solid #F3F3F3; }
Here, we had to change the default colors from the default Bootstrap navigation list. Also, by adding the transitions, we got a nice effect; when the user hovers over the menu, a border appears at the bottom of the item list.
To finish the navigation bar, it would be nice to add some badges to the notifications item in the up list to show the number of new notifications, just as Twitter has on its website. For that, you will learn to use Bootstrap badges.
So, in the notifications item in the list, add the following highlighted HTML line:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
</ul>
For the CSS, set some positions, paddings, and borders:
.navbar-nav .badge { color: #2F92CA; background-color: #FFF; font-size: 0.7em; padding: 0.27rem 0.55rem 0.2rem 0.4rem; position: absolute; left: 0.37rem; top: 0.7rem; z-index: 99; border: 0.2rem solid #2F92CA; }
Nicely done! Refresh the browser and you will see this pretty, beautiful badge:

We now have three issues with the navigation bar. Can you guess them?
They are the Tweet button at the small viewport, the collapsed navigation menu collapse, and the color of the collapse hamburger button.
Well, first we will handle the easiest one—fix the Tweet button! For that, we will create another element to be placed at the left-hand side of the collapse button and just display it when they are in extra small resolution. First, add the .hidden-xs
class to the current Tweet
button:
<button id="tweet" class="btn btn-default pull-right hidden-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
Secondly, at .navbar-header
, after button.navbar-toggle
, add the following highlighted button:
<div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button id="tweet" class="btn btn-default pull-right visible-xs-block"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button> </div>
So, what we did is hide the Tweet button for extra small devices and show a new one in a different element. Set a mobile viewport and you can see the button's position fixed, as follows:

Next, let's fix the color of the collapse hamburger button. Just apply the next CSS to change its color:
.navbar-header .navbar-toggle, .navbar-default .navbar-toggle:focus { background-color: #57A5D2; } .navbar-default .navbar-toggle:hover { background-color: #3986B3; } .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; }
Finally, let's customize the collapsed navigation bar using Bootstrap helpers. We add the .hidden-xs
class to .nav-options
and the .hidden-sm
class to the form#search
element, making them invisible for extra small and small devices respectively, just as we did to the Tweet button:
<div id="nav-options" class="btn-group pull-right hidden-xs"> … </div> <form id="search" role="search" class="hidden-sm"> … </form>
Then, in the ul.nav.navbar-nav
navigation list, create two items that will replace the ones hidden at the current viewport:
<ul class="nav navbar-nav"> ... <!-- others elements list were hidden --> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profile </a> </li> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout </a> </li> </ul>
Thus we are making them visible for extra small resolution with the .visible.xs-inline
class, as long they are from an inline list.
To wrap it up, let's remove the border in the active list item, since it does not seem nice at the bottom in the layout. Let's change it to a right border instead of bottom with the following CSS using a media query:
@media(max-width:34em){ .navbar-default .navbar-nav > .active > a { border-bottom: none; border-left: 0.45em solid #FFF; padding-left: 0.5em; } }
And we are done! Refresh the web page and see the final result of the navigation bar. It is awesome!

You deserve a badge!
To finish the navigation bar, it would be nice to add some badges to the notifications item in the up list to show the number of new notifications, just as Twitter has on its website. For that, you will learn to use Bootstrap badges.
So, in the notifications item in the list, add the following highlighted HTML line:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
</ul>
For the CSS, set some positions, paddings, and borders:
.navbar-nav .badge { color: #2F92CA; background-color: #FFF; font-size: 0.7em; padding: 0.27rem 0.55rem 0.2rem 0.4rem; position: absolute; left: 0.37rem; top: 0.7rem; z-index: 99; border: 0.2rem solid #2F92CA; }
Nicely done! Refresh the browser and you will see this pretty, beautiful badge:

We now have three issues with the navigation bar. Can you guess them?
They are the Tweet button at the small viewport, the collapsed navigation menu collapse, and the color of the collapse hamburger button.
Well, first we will handle the easiest one—fix the Tweet button! For that, we will create another element to be placed at the left-hand side of the collapse button and just display it when they are in extra small resolution. First, add the .hidden-xs
class to the current Tweet
button:
<button id="tweet" class="btn btn-default pull-right hidden-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
Secondly, at .navbar-header
, after button.navbar-toggle
, add the following highlighted button:
<div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button id="tweet" class="btn btn-default pull-right visible-xs-block"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button> </div>
So, what we did is hide the Tweet button for extra small devices and show a new one in a different element. Set a mobile viewport and you can see the button's position fixed, as follows:

Next, let's fix the color of the collapse hamburger button. Just apply the next CSS to change its color:
.navbar-header .navbar-toggle, .navbar-default .navbar-toggle:focus { background-color: #57A5D2; } .navbar-default .navbar-toggle:hover { background-color: #3986B3; } .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; }
Finally, let's customize the collapsed navigation bar using Bootstrap helpers. We add the .hidden-xs
class to .nav-options
and the .hidden-sm
class to the form#search
element, making them invisible for extra small and small devices respectively, just as we did to the Tweet button:
<div id="nav-options" class="btn-group pull-right hidden-xs"> … </div> <form id="search" role="search" class="hidden-sm"> … </form>
Then, in the ul.nav.navbar-nav
navigation list, create two items that will replace the ones hidden at the current viewport:
<ul class="nav navbar-nav"> ... <!-- others elements list were hidden --> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profile </a> </li> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout </a> </li> </ul>
Thus we are making them visible for extra small resolution with the .visible.xs-inline
class, as long they are from an inline list.
To wrap it up, let's remove the border in the active list item, since it does not seem nice at the bottom in the layout. Let's change it to a right border instead of bottom with the following CSS using a media query:
@media(max-width:34em){ .navbar-default .navbar-nav > .active > a { border-bottom: none; border-left: 0.45em solid #FFF; padding-left: 0.5em; } }
And we are done! Refresh the web page and see the final result of the navigation bar. It is awesome!

Fixing some issues with the navigation bar
We now have three issues with the navigation bar. Can you guess them?
They are the Tweet button at the small viewport, the collapsed navigation menu collapse, and the color of the collapse hamburger button.
Well, first we will handle the easiest one—fix the Tweet button! For that, we will create another element to be placed at the left-hand side of the collapse button and just display it when they are in extra small resolution. First, add the .hidden-xs
class to the current Tweet
button:
<button id="tweet" class="btn btn-default pull-right hidden-xs">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
Secondly, at .navbar-header
, after button.navbar-toggle
, add the following highlighted button:
<div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <img src="imgs/logo.png" class="img-responsive"> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <button id="tweet" class="btn btn-default pull-right visible-xs-block"> <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span> Tweet </button> </div>
So, what we did is hide the Tweet button for extra small devices and show a new one in a different element. Set a mobile viewport and you can see the button's position fixed, as follows:

Next, let's fix the color of the collapse hamburger button. Just apply the next CSS to change its color:
.navbar-header .navbar-toggle, .navbar-default .navbar-toggle:focus { background-color: #57A5D2; } .navbar-default .navbar-toggle:hover { background-color: #3986B3; } .navbar-default .navbar-toggle .icon-bar { background-color: #FFF; }
Finally, let's customize the collapsed navigation bar using Bootstrap helpers. We add the .hidden-xs
class to .nav-options
and the .hidden-sm
class to the form#search
element, making them invisible for extra small and small devices respectively, just as we did to the Tweet button:
<div id="nav-options" class="btn-group pull-right hidden-xs"> … </div> <form id="search" role="search" class="hidden-sm"> … </form>
Then, in the ul.nav.navbar-nav
navigation list, create two items that will replace the ones hidden at the current viewport:
<ul class="nav navbar-nav"> ... <!-- others elements list were hidden --> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Profile </a> </li> <li class="visible-xs-inline"> <a href="#"> <span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout </a> </li> </ul>
Thus we are making them visible for extra small resolution with the .visible.xs-inline
class, as long they are from an inline list.
To wrap it up, let's remove the border in the active list item, since it does not seem nice at the bottom in the layout. Let's change it to a right border instead of bottom with the following CSS using a media query:
@media(max-width:34em){ .navbar-default .navbar-nav > .active > a { border-bottom: none; border-left: 0.45em solid #FFF; padding-left: 0.5em; } }
And we are done! Refresh the web page and see the final result of the navigation bar. It is awesome!

We have finally finished the navigation bar. Now it's time to the page main content. For that, we must create a page grid. Following how Twitter uses a three-column-based layout, we will do the same. The HTML code for the scaffolding is the one that should be placed after the <nav>
element:
<div class="container"> <div class="row"> <div id="profile" class="col-md-3 hidden-sm hidden-xs"></div> <div id="main" class="col-sm-12 col-md-6"> </div> <div id="right-content" class="col-md-3 hidden-sm hidden-xs"> </div> </div> </div>
To understand it, we just created a .container
with a single .row
. The .row
contains three columns, the first and the last being visible only for medium and larger devices. This is because of the .hidden-sm
and .hidden-xs
classes. When both columns are hidden, the middle column fills the row completely. This is because of the .col-sm-12
class.
To finish that, add a padding-top
to <body>
in order to correct the page's position with respect to the navigation bar:
body { padding-top: 4em; background-color: #F5F8FA; }
Moving on, in our web application, we will create a new component containing the about information, named Card. We will take a break from page development to discuss this section in depth.
Cards are flexible container extensions that include internal options, such as header, footer, and other display options. In Bootstrap 4, there is a component called Card, but since we are supporting versions 3 and 4 in this book, we will teach both ways.
As was mentioned before, Bootstrap 4 provides Cards components. To make use of them, create a div.card
element and start adding elements such as .card-block
and .card-img-top
:
<div class="card"> <img class="card-img-top img-responsive" src="imgs/landscape.jpg"> <div class="card-block"> <h4 class="card-title">Name</h4> <p class="card-text">About text</p> <a href="#" class="btn btn-primary">Can add buttons</a> </div> </div>
For the preceding code, the output will look like what is shown in the following screenshot. As we can see, the Card component is pretty simple and straightforward. The component offers some other options as well, but we will talk about that when needed.

Like the famous quote, if you have lemons, make lemonade, in Bootstrap version 3, we do not have the Card component. However, we have the tools needed to make our own Card component for sure! So let's have some lemonade!
We will use the same classes and structures of Bootstrap 4, playing with only the CSS. Therefore, if you are using version 3, you will see the page render like this for the use of the same HTML from version 4:

To squeeze the first lemon, let's create the CSS for the .card
class:
.card { position: relative; border: 0.1rem solid #e5e5e5; border-radius: 0.4rem; background-color: #FFF; }
Following this, just add two CSS rules for img.card-img-top
and .card-block
, as shown here:
.card-img-top { border-radius: 0.4rem 0.4rem 0 0; } .card-block { padding: 1.25rem; }
Done! We have our own card component ready for Bootstrap 3. The next screenshot presents the final result. Of course, there are some differences of typography and button color, but these are the differences because of the version; the component is perfectly done.

Getting back to the web application, let's add the Card components inside div#profile
, at the main container. The HTML code for this section will be as follows:
<div id="profile-resume" class="card"> <img class="card-img-top img-responsive" src="imgs/landscape.jpg"> <div class="card-block"> <img src="imgs/jon.png" class="card-img"> <h4 class="card-title">Jonny Doo <small>@jonnydoo</small></h4> <p class="card-text">Dog goes woofy. Did you said squitly?</p> <ul class="list-inline list-unstyled"> <li id="card-tweets"> <a href="#"> <span class="profile-stats">Tweets</span> <span class="profile-value">99k</span> </a> </li> <li class="card-following"> <a href="#"> <span class="profile-stats">Following</span> <span class="profile-value">7</span> </a> </li> <li class="card-followers"> <a href="#"> <span class="profile-stats">Followers</span> <span class="profile-value">132k</span> </a> </li> </ul> </div> </div>
Breaking down the code, we added some components to .card-block
. First of all is the .card-img
element, which will represent the profile photography. Following this, we changed .card-title
by adding a <small>
tag inside <h4>
. The last change is the addition of the <ul>
list, representing some stats for the profile.
There is no secret in this HTML piece; we just added some elements in a straightforward way. Now it's time for the CSS rules. First, change the position and size of the img.card-img
element:
.card-block img.card-img { top: 50%; margin-top: -36px; width: 72px; border: 3px solid #FFF; border-radius: 0.4rem; float: left; position: relative; z-index: 99; }
Since it is in the right place, let's correctly align .card-title
and add some padding to .card-text
:
.card-block .card-title { float: left; margin: 0; margin-left: 0.5em; } .card-block .card-title small { display: block; } .card-block .card-text { clear: both; padding-top: 0.25em; margin-bottom: 1.5em; }
Tip
Can you change the card block to use flexbox?
Another challenge appears here. Since you have already learned about the usage of flexbox, try to replace the floats in the previous code with some flexbox CSS rules. Just keep in mind that it is recommended for Bootstrap 4 and works only on new browsers.
It is almost looking like the Twitter card on the left; we just need to change the list style inside the profile card. Add this CSS:
.card-block ul a:hover { text-decoration: none; } .card-block ul .profile-stats { color: #777; display: block; text-transform: uppercase; font-size: 0.63em; } .card-block ul .profile-value { font-size: 1.2em; font-weight: bold; color: #2F92CA; }
Well done! It looks prettier than the Twitter component. In the following screenshot, we present the expected result:

After the #profile-resume
card, we will create another one named #profile-photo
, which will contain photos of the user. Use the same cards methodology to place this new one after #profile-resume
with the following HTML code:
<div id="profile-photo" class="card"> <div class="card-header">Photos</div> <div class="card-block"> <ul class="list-inline list-unstyled"> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-02.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-03.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-04.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-05.jpg"></a> </li> </ul> </div> </div>
In this card we will create a new card element, .card-header
. In Bootstrap 4, you can use the regarding class, but in version 3, you will need this CSS rule:
.card .card-header { border-radius: 0.4rem 0.4rem 0 0; padding: .75rem 1.25rem; background-color: #f5f5f5; border-bottom: 0.1em solid #e5e5e5; color: #4e5665; font-weight: bold; }
Moving on, the rest of CSS for this card is simple. Just change the image's width and adjust some margins and paddings:
#profile-photo { margin-top: 2rem; } #profile-photo ul { margin: 0; } #profile-photo li { width: 48%; padding: 0; }
Also note that we are using the .thumbnail
class in the <a>
tag that wraps the images. This class is useful for nicely styled thumbnail images. It can also be used to wrap text along with an image.
The photo card should look like what is shown in the following screenshot. Again, we will use some more cards in this web application, although we'll talk about that later, when needed.

Learning cards in Bootstrap 4
As was mentioned before, Bootstrap 4 provides Cards components. To make use of them, create a div.card
element and start adding elements such as .card-block
and .card-img-top
:
<div class="card"> <img class="card-img-top img-responsive" src="imgs/landscape.jpg"> <div class="card-block"> <h4 class="card-title">Name</h4> <p class="card-text">About text</p> <a href="#" class="btn btn-primary">Can add buttons</a> </div> </div>
For the preceding code, the output will look like what is shown in the following screenshot. As we can see, the Card component is pretty simple and straightforward. The component offers some other options as well, but we will talk about that when needed.

Like the famous quote, if you have lemons, make lemonade, in Bootstrap version 3, we do not have the Card component. However, we have the tools needed to make our own Card component for sure! So let's have some lemonade!
We will use the same classes and structures of Bootstrap 4, playing with only the CSS. Therefore, if you are using version 3, you will see the page render like this for the use of the same HTML from version 4:

To squeeze the first lemon, let's create the CSS for the .card
class:
.card { position: relative; border: 0.1rem solid #e5e5e5; border-radius: 0.4rem; background-color: #FFF; }
Following this, just add two CSS rules for img.card-img-top
and .card-block
, as shown here:
.card-img-top { border-radius: 0.4rem 0.4rem 0 0; } .card-block { padding: 1.25rem; }
Done! We have our own card component ready for Bootstrap 3. The next screenshot presents the final result. Of course, there are some differences of typography and button color, but these are the differences because of the version; the component is perfectly done.

Getting back to the web application, let's add the Card components inside div#profile
, at the main container. The HTML code for this section will be as follows:
<div id="profile-resume" class="card"> <img class="card-img-top img-responsive" src="imgs/landscape.jpg"> <div class="card-block"> <img src="imgs/jon.png" class="card-img"> <h4 class="card-title">Jonny Doo <small>@jonnydoo</small></h4> <p class="card-text">Dog goes woofy. Did you said squitly?</p> <ul class="list-inline list-unstyled"> <li id="card-tweets"> <a href="#"> <span class="profile-stats">Tweets</span> <span class="profile-value">99k</span> </a> </li> <li class="card-following"> <a href="#"> <span class="profile-stats">Following</span> <span class="profile-value">7</span> </a> </li> <li class="card-followers"> <a href="#"> <span class="profile-stats">Followers</span> <span class="profile-value">132k</span> </a> </li> </ul> </div> </div>
Breaking down the code, we added some components to .card-block
. First of all is the .card-img
element, which will represent the profile photography. Following this, we changed .card-title
by adding a <small>
tag inside <h4>
. The last change is the addition of the <ul>
list, representing some stats for the profile.
There is no secret in this HTML piece; we just added some elements in a straightforward way. Now it's time for the CSS rules. First, change the position and size of the img.card-img
element:
.card-block img.card-img { top: 50%; margin-top: -36px; width: 72px; border: 3px solid #FFF; border-radius: 0.4rem; float: left; position: relative; z-index: 99; }
Since it is in the right place, let's correctly align .card-title
and add some padding to .card-text
:
.card-block .card-title { float: left; margin: 0; margin-left: 0.5em; } .card-block .card-title small { display: block; } .card-block .card-text { clear: both; padding-top: 0.25em; margin-bottom: 1.5em; }
Tip
Can you change the card block to use flexbox?
Another challenge appears here. Since you have already learned about the usage of flexbox, try to replace the floats in the previous code with some flexbox CSS rules. Just keep in mind that it is recommended for Bootstrap 4 and works only on new browsers.
It is almost looking like the Twitter card on the left; we just need to change the list style inside the profile card. Add this CSS:
.card-block ul a:hover { text-decoration: none; } .card-block ul .profile-stats { color: #777; display: block; text-transform: uppercase; font-size: 0.63em; } .card-block ul .profile-value { font-size: 1.2em; font-weight: bold; color: #2F92CA; }
Well done! It looks prettier than the Twitter component. In the following screenshot, we present the expected result:

After the #profile-resume
card, we will create another one named #profile-photo
, which will contain photos of the user. Use the same cards methodology to place this new one after #profile-resume
with the following HTML code:
<div id="profile-photo" class="card"> <div class="card-header">Photos</div> <div class="card-block"> <ul class="list-inline list-unstyled"> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-02.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-03.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-04.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-05.jpg"></a> </li> </ul> </div> </div>
In this card we will create a new card element, .card-header
. In Bootstrap 4, you can use the regarding class, but in version 3, you will need this CSS rule:
.card .card-header { border-radius: 0.4rem 0.4rem 0 0; padding: .75rem 1.25rem; background-color: #f5f5f5; border-bottom: 0.1em solid #e5e5e5; color: #4e5665; font-weight: bold; }
Moving on, the rest of CSS for this card is simple. Just change the image's width and adjust some margins and paddings:
#profile-photo { margin-top: 2rem; } #profile-photo ul { margin: 0; } #profile-photo li { width: 48%; padding: 0; }
Also note that we are using the .thumbnail
class in the <a>
tag that wraps the images. This class is useful for nicely styled thumbnail images. It can also be used to wrap text along with an image.
The photo card should look like what is shown in the following screenshot. Again, we will use some more cards in this web application, although we'll talk about that later, when needed.

Creating your own cards
Like the famous quote, if you have lemons, make lemonade, in Bootstrap version 3, we do not have the Card component. However, we have the tools needed to make our own Card component for sure! So let's have some lemonade!
We will use the same classes and structures of Bootstrap 4, playing with only the CSS. Therefore, if you are using version 3, you will see the page render like this for the use of the same HTML from version 4:

To squeeze the first lemon, let's create the CSS for the .card
class:
.card { position: relative; border: 0.1rem solid #e5e5e5; border-radius: 0.4rem; background-color: #FFF; }
Following this, just add two CSS rules for img.card-img-top
and .card-block
, as shown here:
.card-img-top { border-radius: 0.4rem 0.4rem 0 0; } .card-block { padding: 1.25rem; }
Done! We have our own card component ready for Bootstrap 3. The next screenshot presents the final result. Of course, there are some differences of typography and button color, but these are the differences because of the version; the component is perfectly done.

Getting back to the web application, let's add the Card components inside div#profile
, at the main container. The HTML code for this section will be as follows:
<div id="profile-resume" class="card"> <img class="card-img-top img-responsive" src="imgs/landscape.jpg"> <div class="card-block"> <img src="imgs/jon.png" class="card-img"> <h4 class="card-title">Jonny Doo <small>@jonnydoo</small></h4> <p class="card-text">Dog goes woofy. Did you said squitly?</p> <ul class="list-inline list-unstyled"> <li id="card-tweets"> <a href="#"> <span class="profile-stats">Tweets</span> <span class="profile-value">99k</span> </a> </li> <li class="card-following"> <a href="#"> <span class="profile-stats">Following</span> <span class="profile-value">7</span> </a> </li> <li class="card-followers"> <a href="#"> <span class="profile-stats">Followers</span> <span class="profile-value">132k</span> </a> </li> </ul> </div> </div>
Breaking down the code, we added some components to .card-block
. First of all is the .card-img
element, which will represent the profile photography. Following this, we changed .card-title
by adding a <small>
tag inside <h4>
. The last change is the addition of the <ul>
list, representing some stats for the profile.
There is no secret in this HTML piece; we just added some elements in a straightforward way. Now it's time for the CSS rules. First, change the position and size of the img.card-img
element:
.card-block img.card-img { top: 50%; margin-top: -36px; width: 72px; border: 3px solid #FFF; border-radius: 0.4rem; float: left; position: relative; z-index: 99; }
Since it is in the right place, let's correctly align .card-title
and add some padding to .card-text
:
.card-block .card-title { float: left; margin: 0; margin-left: 0.5em; } .card-block .card-title small { display: block; } .card-block .card-text { clear: both; padding-top: 0.25em; margin-bottom: 1.5em; }
Tip
Can you change the card block to use flexbox?
Another challenge appears here. Since you have already learned about the usage of flexbox, try to replace the floats in the previous code with some flexbox CSS rules. Just keep in mind that it is recommended for Bootstrap 4 and works only on new browsers.
It is almost looking like the Twitter card on the left; we just need to change the list style inside the profile card. Add this CSS:
.card-block ul a:hover { text-decoration: none; } .card-block ul .profile-stats { color: #777; display: block; text-transform: uppercase; font-size: 0.63em; } .card-block ul .profile-value { font-size: 1.2em; font-weight: bold; color: #2F92CA; }
Well done! It looks prettier than the Twitter component. In the following screenshot, we present the expected result:

After the #profile-resume
card, we will create another one named #profile-photo
, which will contain photos of the user. Use the same cards methodology to place this new one after #profile-resume
with the following HTML code:
<div id="profile-photo" class="card"> <div class="card-header">Photos</div> <div class="card-block"> <ul class="list-inline list-unstyled"> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-02.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-03.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-04.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-05.jpg"></a> </li> </ul> </div> </div>
In this card we will create a new card element, .card-header
. In Bootstrap 4, you can use the regarding class, but in version 3, you will need this CSS rule:
.card .card-header { border-radius: 0.4rem 0.4rem 0 0; padding: .75rem 1.25rem; background-color: #f5f5f5; border-bottom: 0.1em solid #e5e5e5; color: #4e5665; font-weight: bold; }
Moving on, the rest of CSS for this card is simple. Just change the image's width and adjust some margins and paddings:
#profile-photo { margin-top: 2rem; } #profile-photo ul { margin: 0; } #profile-photo li { width: 48%; padding: 0; }
Also note that we are using the .thumbnail
class in the <a>
tag that wraps the images. This class is useful for nicely styled thumbnail images. It can also be used to wrap text along with an image.
The photo card should look like what is shown in the following screenshot. Again, we will use some more cards in this web application, although we'll talk about that later, when needed.

Adding Cards to our web application
Getting back to the web application, let's add the Card components inside div#profile
, at the main container. The HTML code for this section will be as follows:
<div id="profile-resume" class="card"> <img class="card-img-top img-responsive" src="imgs/landscape.jpg"> <div class="card-block"> <img src="imgs/jon.png" class="card-img"> <h4 class="card-title">Jonny Doo <small>@jonnydoo</small></h4> <p class="card-text">Dog goes woofy. Did you said squitly?</p> <ul class="list-inline list-unstyled"> <li id="card-tweets"> <a href="#"> <span class="profile-stats">Tweets</span> <span class="profile-value">99k</span> </a> </li> <li class="card-following"> <a href="#"> <span class="profile-stats">Following</span> <span class="profile-value">7</span> </a> </li> <li class="card-followers"> <a href="#"> <span class="profile-stats">Followers</span> <span class="profile-value">132k</span> </a> </li> </ul> </div> </div>
Breaking down the code, we added some components to .card-block
. First of all is the .card-img
element, which will represent the profile photography. Following this, we changed .card-title
by adding a <small>
tag inside <h4>
. The last change is the addition of the <ul>
list, representing some stats for the profile.
There is no secret in this HTML piece; we just added some elements in a straightforward way. Now it's time for the CSS rules. First, change the position and size of the img.card-img
element:
.card-block img.card-img { top: 50%; margin-top: -36px; width: 72px; border: 3px solid #FFF; border-radius: 0.4rem; float: left; position: relative; z-index: 99; }
Since it is in the right place, let's correctly align .card-title
and add some padding to .card-text
:
.card-block .card-title { float: left; margin: 0; margin-left: 0.5em; } .card-block .card-title small { display: block; } .card-block .card-text { clear: both; padding-top: 0.25em; margin-bottom: 1.5em; }
Tip
Can you change the card block to use flexbox?
Another challenge appears here. Since you have already learned about the usage of flexbox, try to replace the floats in the previous code with some flexbox CSS rules. Just keep in mind that it is recommended for Bootstrap 4 and works only on new browsers.
It is almost looking like the Twitter card on the left; we just need to change the list style inside the profile card. Add this CSS:
.card-block ul a:hover { text-decoration: none; } .card-block ul .profile-stats { color: #777; display: block; text-transform: uppercase; font-size: 0.63em; } .card-block ul .profile-value { font-size: 1.2em; font-weight: bold; color: #2F92CA; }
Well done! It looks prettier than the Twitter component. In the following screenshot, we present the expected result:

After the #profile-resume
card, we will create another one named #profile-photo
, which will contain photos of the user. Use the same cards methodology to place this new one after #profile-resume
with the following HTML code:
<div id="profile-photo" class="card"> <div class="card-header">Photos</div> <div class="card-block"> <ul class="list-inline list-unstyled"> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-02.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-03.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-04.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-05.jpg"></a> </li> </ul> </div> </div>
In this card we will create a new card element, .card-header
. In Bootstrap 4, you can use the regarding class, but in version 3, you will need this CSS rule:
.card .card-header { border-radius: 0.4rem 0.4rem 0 0; padding: .75rem 1.25rem; background-color: #f5f5f5; border-bottom: 0.1em solid #e5e5e5; color: #4e5665; font-weight: bold; }
Moving on, the rest of CSS for this card is simple. Just change the image's width and adjust some margins and paddings:
#profile-photo { margin-top: 2rem; } #profile-photo ul { margin: 0; } #profile-photo li { width: 48%; padding: 0; }
Also note that we are using the .thumbnail
class in the <a>
tag that wraps the images. This class is useful for nicely styled thumbnail images. It can also be used to wrap text along with an image.
The photo card should look like what is shown in the following screenshot. Again, we will use some more cards in this web application, although we'll talk about that later, when needed.

Another card using thumbnails
After the #profile-resume
card, we will create another one named #profile-photo
, which will contain photos of the user. Use the same cards methodology to place this new one after #profile-resume
with the following HTML code:
<div id="profile-photo" class="card"> <div class="card-header">Photos</div> <div class="card-block"> <ul class="list-inline list-unstyled"> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-02.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-03.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-04.jpg"></a> </li> <li> <a href="#" class="thumbnail"><img class="img-responsive" src="imgs/landscape-05.jpg"></a> </li> </ul> </div> </div>
In this card we will create a new card element, .card-header
. In Bootstrap 4, you can use the regarding class, but in version 3, you will need this CSS rule:
.card .card-header { border-radius: 0.4rem 0.4rem 0 0; padding: .75rem 1.25rem; background-color: #f5f5f5; border-bottom: 0.1em solid #e5e5e5; color: #4e5665; font-weight: bold; }
Moving on, the rest of CSS for this card is simple. Just change the image's width and adjust some margins and paddings:
#profile-photo { margin-top: 2rem; } #profile-photo ul { margin: 0; } #profile-photo li { width: 48%; padding: 0; }
Also note that we are using the .thumbnail
class in the <a>
tag that wraps the images. This class is useful for nicely styled thumbnail images. It can also be used to wrap text along with an image.
The photo card should look like what is shown in the following screenshot. Again, we will use some more cards in this web application, although we'll talk about that later, when needed.

Moving on, we will implement the main content in the middle of the page. This content will hold the feeds while allowing new tweets.
We need to create the input to send a new message. To do this, create the following HTML code at the div#main
element:
<div id="main" class="col-sm-12 col-md-6"> <div id="main-card" class="card"> <form id="new-message"> <div class="input-group"> <input type="text" class="form-control" placeholder="What is happening?"> <span class="input-group-addon"> <span class="glyphicon glyphicon-camera" aria-hidden="true"></span> </span> </div> </form> </div> </div>
For that, we created a form, again making use of input groups, icons, and cards. Can you see the ease provided by Bootstrap again? We just placed the elements with the right classes and everything went perfect. The next CSS takes place with some rules regarding the color and padding of the form:
form#new-message { border-radius: 0.4rem 0.4rem 0 0; padding: 1em; border-bottom: 0.1em solid #CEE4F5; background-color: #EBF4FB; } form#new-message .input-group-addon { background-color: #FFF; }
At this point, the result should be as shown in the following screenshot. Next up, we will create the other elements.

We have made cool things so far, but the feed is the core of the page. We will create a nice and friendly feed for our web app.
As usual, let's create the HTML code first. The feed will work inside a stacked list. With that in mind, let's create the first element in the list:
<div id="main" class="col-sm-12 col-md-6"> <div id="main-card" class="card"> <form id="new-message"> <div class="input-group"> <input type="text" class="form-control" placeholder="What is happening?"> <span class="input-group-addon"> <span class="glyphicon glyphicon-camera" aria-hidden="true"></span> </span> </div> </form> <ul id="feed" class="list-unstyled"> <li> <img src="imgs/doge.jpg" class="feed-avatar img-circle"> <div class="feed-post"> <h5>Name <small>@namex - 3h</small></h5> <p> You can't hold a dog down without staying down with him!</p> </div> <div class="action-list"> <a href="#"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </a> <a href="#"> <span class="glyphicon glyphicon-refresh " aria-hidden="true"></span> <span class="retweet-count">6</span> </a> <a href="#"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> </a> </div> </li> </ul> </div> </div>
The highlighted code is the code added for the list. To understand it, we created an element in the list containing the common stuff inside a post, such as an image, a name, text, and options. Add the .img-circle
class to the image in the list to style it using Bootstrap image styles.
With the CSS, we will correctly style the page. For the list and the image, apply the following rules:
ul#feed { margin: 0; } ul#feed li { padding: 1em 1em; } ul#feed .feed-avatar { width: 13%; display: inline-block; vertical-align: top; }
By doing this, you will be correcting the margins and padding while adjusting the size of the image avatar. For the post section, use this CSS:
ul#feed .feed-post { width: 80%; display: inline-block; margin-left: 2%; } ul#feed .feed-post h5 { font-weight: bold; margin-bottom: 0.5rem; } ul#feed .feed-post h5 > small { font-size: 1.2rem; }
Finally, with regard to .action-list
, set the following styles:
ul#feed .action-list { margin-left: 13%; padding-left: 1em; } ul#feed .action-list a { width: 15%; display: inline-block; } ul#feed .action-list a:hover { text-decoration: none; } ul#feed .action-list .retweet-count { padding-left: 0.2em; font-weight: bold; }
Refresh your browser and you will get this result:

Awesome! Note that for the post, we did all the spacing using percentage values. This is also a great option because the page will resize with respect to the user's resolution very smoothly.
We have only one problem now. Add another post and you will see that there is no divisor between the posts. To illustrate this, add a second post in the HTML code:
<ul id="feed" class="list-unstyled"> <li> <img src="imgs/doge.jpg" class="feed-avatar img-circle"> <div class="feed-post"> <h5>Doge <small>@dogeoficial - 3h</small></h5> <p>You can't hold a dog down without staying down with him!</p> </div> <div class="action-list"> <a href="#"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </a> <a href="#"> <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> <span class="retweet-count">6</span> </a> <a href="#"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> </a> </div> </li> <li> <img src="imgs/laika.jpg" class="feed-avatar img-circle"> <div class="feed-post"> <h5>Laika <small>@spacesog - 4h</small></h5> <p>That's one small step for a dog, one giant leap for giant</p> </div> <div class="action-list"> <a href="#"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </a> <a href="#"> <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> <span class="retweet-count">6</span> </a> <a href="#"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> </a> </div> </li> </ul>
At the CSS, change it a little to correct the padding and add a border between the items, as follows:
ul#feed li { padding: 1em 1em; border-bottom: 0.1rem solid #e5e5e5; } ul#feed li:last-child { border-bottom: none; }
The output results will be like this:

Okay, I know that web applications such as Twitter usually use infinite loading and not pagination, but we need to learn that! Bootstrap offers incredible options for pagination, so let's use some of them right now.
From the start, create the HTML code for the component and insert it just after div.main-card
:
<nav class="text-center"> <ul class="pagination pagination-lg"> <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">«</span></a></li> <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li> <li><a href="#">2</a></li> <li class="disabled"><a href="#">...</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#" aria-label="Next"><span aria-hidden="true">»</span></a></li> </ul> </nav>
Thus, we must consider a few things here. Firstly, to center the pagination, we used the helper class from Bootstrap, .text-center
. This is because ul.pagination
does apply the display: inline-block
style.
Secondly, we created a <ul>
with the .pagination
class, determined by the framework. We also added the .pagination-lg
class, which is an option of pagination for making it bigger.
Lastly, the .disabled
class is present in two items of the list, the previous link and the ellipsis ...
one. Also, the list on page 1 is marked as active, changing its background color.
Check out the result of adding pagination in this screenshot:

Making your feed
We have made cool things so far, but the feed is the core of the page. We will create a nice and friendly feed for our web app.
As usual, let's create the HTML code first. The feed will work inside a stacked list. With that in mind, let's create the first element in the list:
<div id="main" class="col-sm-12 col-md-6"> <div id="main-card" class="card"> <form id="new-message"> <div class="input-group"> <input type="text" class="form-control" placeholder="What is happening?"> <span class="input-group-addon"> <span class="glyphicon glyphicon-camera" aria-hidden="true"></span> </span> </div> </form> <ul id="feed" class="list-unstyled"> <li> <img src="imgs/doge.jpg" class="feed-avatar img-circle"> <div class="feed-post"> <h5>Name <small>@namex - 3h</small></h5> <p> You can't hold a dog down without staying down with him!</p> </div> <div class="action-list"> <a href="#"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </a> <a href="#"> <span class="glyphicon glyphicon-refresh " aria-hidden="true"></span> <span class="retweet-count">6</span> </a> <a href="#"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> </a> </div> </li> </ul> </div> </div>
The highlighted code is the code added for the list. To understand it, we created an element in the list containing the common stuff inside a post, such as an image, a name, text, and options. Add the .img-circle
class to the image in the list to style it using Bootstrap image styles.
With the CSS, we will correctly style the page. For the list and the image, apply the following rules:
ul#feed { margin: 0; } ul#feed li { padding: 1em 1em; } ul#feed .feed-avatar { width: 13%; display: inline-block; vertical-align: top; }
By doing this, you will be correcting the margins and padding while adjusting the size of the image avatar. For the post section, use this CSS:
ul#feed .feed-post { width: 80%; display: inline-block; margin-left: 2%; } ul#feed .feed-post h5 { font-weight: bold; margin-bottom: 0.5rem; } ul#feed .feed-post h5 > small { font-size: 1.2rem; }
Finally, with regard to .action-list
, set the following styles:
ul#feed .action-list { margin-left: 13%; padding-left: 1em; } ul#feed .action-list a { width: 15%; display: inline-block; } ul#feed .action-list a:hover { text-decoration: none; } ul#feed .action-list .retweet-count { padding-left: 0.2em; font-weight: bold; }
Refresh your browser and you will get this result:

Awesome! Note that for the post, we did all the spacing using percentage values. This is also a great option because the page will resize with respect to the user's resolution very smoothly.
We have only one problem now. Add another post and you will see that there is no divisor between the posts. To illustrate this, add a second post in the HTML code:
<ul id="feed" class="list-unstyled"> <li> <img src="imgs/doge.jpg" class="feed-avatar img-circle"> <div class="feed-post"> <h5>Doge <small>@dogeoficial - 3h</small></h5> <p>You can't hold a dog down without staying down with him!</p> </div> <div class="action-list"> <a href="#"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </a> <a href="#"> <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> <span class="retweet-count">6</span> </a> <a href="#"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> </a> </div> </li> <li> <img src="imgs/laika.jpg" class="feed-avatar img-circle"> <div class="feed-post"> <h5>Laika <small>@spacesog - 4h</small></h5> <p>That's one small step for a dog, one giant leap for giant</p> </div> <div class="action-list"> <a href="#"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </a> <a href="#"> <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> <span class="retweet-count">6</span> </a> <a href="#"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> </a> </div> </li> </ul>
At the CSS, change it a little to correct the padding and add a border between the items, as follows:
ul#feed li { padding: 1em 1em; border-bottom: 0.1rem solid #e5e5e5; } ul#feed li:last-child { border-bottom: none; }
The output results will be like this:

Okay, I know that web applications such as Twitter usually use infinite loading and not pagination, but we need to learn that! Bootstrap offers incredible options for pagination, so let's use some of them right now.
From the start, create the HTML code for the component and insert it just after div.main-card
:
<nav class="text-center"> <ul class="pagination pagination-lg"> <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">«</span></a></li> <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li> <li><a href="#">2</a></li> <li class="disabled"><a href="#">...</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#" aria-label="Next"><span aria-hidden="true">»</span></a></li> </ul> </nav>
Thus, we must consider a few things here. Firstly, to center the pagination, we used the helper class from Bootstrap, .text-center
. This is because ul.pagination
does apply the display: inline-block
style.
Secondly, we created a <ul>
with the .pagination
class, determined by the framework. We also added the .pagination-lg
class, which is an option of pagination for making it bigger.
Lastly, the .disabled
class is present in two items of the list, the previous link and the ellipsis ...
one. Also, the list on page 1 is marked as active, changing its background color.
Check out the result of adding pagination in this screenshot:

Doing some pagination
Okay, I know that web applications such as Twitter usually use infinite loading and not pagination, but we need to learn that! Bootstrap offers incredible options for pagination, so let's use some of them right now.
From the start, create the HTML code for the component and insert it just after div.main-card
:
<nav class="text-center"> <ul class="pagination pagination-lg"> <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">«</span></a></li> <li class="active"><a href="#">1 <span class="sr-only">(current)</span></a></li> <li><a href="#">2</a></li> <li class="disabled"><a href="#">...</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#" aria-label="Next"><span aria-hidden="true">»</span></a></li> </ul> </nav>
Thus, we must consider a few things here. Firstly, to center the pagination, we used the helper class from Bootstrap, .text-center
. This is because ul.pagination
does apply the display: inline-block
style.
Secondly, we created a <ul>
with the .pagination
class, determined by the framework. We also added the .pagination-lg
class, which is an option of pagination for making it bigger.
Lastly, the .disabled
class is present in two items of the list, the previous link and the ellipsis ...
one. Also, the list on page 1 is marked as active, changing its background color.
Check out the result of adding pagination in this screenshot:

To make use of Bootstrap breadcrumbs, we will add it to our web app. Note that we will do this step for learning purposes so that you will be able to create it when you need it.
Like pagination, Bootstrap offers a component for breadcrumbs as well. For that, create an ordered list just after the open tag div#main
:
<div id="main" class="col-sm-12 col-md-6"> <ol class="breadcrumb card"> <li><a href="#">Home</a></li> <li><a href="#">Profile</a></li> <li class="active">Feed</li> </ol> … </div>
The cool thing about Bootstrap breadcrumbs is that the separator bars are automatically added through :before
and the content
CSS option, so you do not need to worry about them.
Note that the .card
class was added to the breadcrumbs component to keep the web app style. The following screenshot presents the result of breadcrumbs:

Well, we are almost done. It is time to create the right-hand-side content of our web app. The right-hand-side content contains information such as Whom to follow and the about page. Let's create it!
Coming to the HTML, let's create another Card component inside div.right-content
, as follows:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <div id="who-follow" class="card"> <div class="card-header"> Who to follow </div> <div class="card-block"> </div> </div> </div>
Inside .card-block
, create a vertical list:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <div id="who-follow" class="card"> <div class="card-header"> Who to follow </div> <div class="card-block"> <ul class="list-unstyled"> <li> <img src="imgs/cat.jpg" class="img-rounded"> <div class="info"> <strong>Crazy cats</strong> <button class="btn btn-default"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Follow </button> </div> </li> <li> <img src="imgs/ration.jpg" class="img-rounded"> <div class="info"> <strong>Free ration alert</strong> <button class="btn btn-default"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Follow </button> </div> </li> </ul> </div> </div> </div>
So, the result without the CSS is not good, as shown in the following screenshot. We need to fix it.

First, we add margins for the items in the list:
div#who-follow li { margin-bottom: 2em; } div#who-follow li:last-child { margin-bottom: 0; }
Then, we adjust the size of the image and the following text:
div#who-follow li img { width: 26%; display: inline-block; vertical-align: top; margin-right: 2%; } div#who-follow li .info { width: 68%; display: inline-block; }
To finish this, we adjust the content inside the .info
element:
div#who-follow li .info strong { display: block; overflow:hidden; text-overflow: ellipsis; } div#who-follow li .info .glyphicon { color: #2F92CA; }
The result should look like what is shown here:

To end the main web page content, let's create another card that has content about the web app, such as help, privacy, and so on. After the div#who-follow
, create another card:
<div id="app-info" class="card"> <div class="card-block"> © 2015 SampleApp <ul class="list-unstyled list-inline"> <li><a href="#">About</a></li> <li><a href="#">Terms and Privacy</a></li> <li><a href="#">Help</a></li> <li><a href="#">Status</a></li> <li><a href="#">Contact</a></li> </ul> </div> <div class="card-footer"> <a href="#">Connect other address book</a> </div> </div>
First of all, note that we have just used .card-footer
for this card. If you are using Bootstrap 3, add the next CSS:
.card .card-footer { border-radius: 0 0 0.4rem 0.4rem; padding: .75rem 1.25rem; background-color: #f5f5f5; border-top: 0.1em solid #e5e5e5; color: #4e5665; }
For this card, we also need to add some margin within the card above:
div#app-info { margin-top: 2rem; }
That looks great! We have finished the majority of the components in our web application! The next image shows the final result that we will cover at this chapter. Great work!

In this chapter, we started the development of another example—an awesome web application like Twitter. We started creating every component with the help of Bootstrap, while also customizing each one. By the end of the chapter, we were done with the major part of the components to be added.
First, we created a fully customized navigation bar that works on any device. Just like at every component, we took special care with different visualizations for mobiles and desktops.
We talked a lot about cards. This is a new component in Bootstrap 4, but we created our own for version 3, so we nailed it all. Cards are present in every column, having different content and placements of items.
We also discussed the use of other Bootstrap components by making use of breadcrumbs, pagination, and thumbnails.
I hope now you feel confident about web application development, because in the next chapter, we will take a step further in this kind of development by using other Bootstrap components and more customization.
In this chapter, we will complete the elements of our web app with the use of other Bootstrap elements and components. By the end of this chapter, we will have covered the majority of elements present in Bootstrap, making you almost an expert as well as answering this question from the last chapter: can you build a web app? Of course you can!
We will cover some more complex Bootstrap components and elements. These are the key points of this chapter, and you will learn how to:
- Use Bootstrap alerts
- Customize alerts
- Progress bars
- CSS key frames
- Navigation components
- Tabs
- Labels and badges
- List groups
Even though these seem to be a lot of key points, they are easy to learn and master. So, I am sure you will be able to nail all of them.
In the last chapter, we did almost everything related to page components. Now we will create some components that interact with the user. To start this, we will introduce alerts, which are very common components of every web app.
In order to learn about alerts, we should create some of them. The pattern for creation is pretty simple; just remember to import Bootstrap JavaScript as we have been doing all throughout the book.
The main class needed to create alerts is .alert
. You can just follow this class with some other, regarding the type of alert, such as .alert-success
for a success message. There are other classes available as well, such as .alert-info
and .alert-danger
. Just replace the suffix of .alert
with the one that you want to use.
It's time to create our first alert! Keeping the same code of the web app from the last chapter, right before div#main
, you must have your ol.breadcrumb
. Replace ol.breadcrumb
with your .alert
, like what is shown in this screenshot:

The HTML code for creating this alert is really simple:
<div class="alert alert-success" role="alert"> You have made a new Tweet. </div>
As mentioned before, just create an element with the .alert
class in combination with the state of the alert, .alert-success
in this case.
Tip
Why do we use the role attribute?
In the preceding example, we made use of the role="alert"
attribute in our .alert
component. The role attribute was incorporated into HTML 5, coming from the ARIA 1.0 specification. The reason for using that is to keep the semantics for different items, for example, in this case, where we used a common <div>
to describe a more semantic element that is an alert.
Bootstrap is incredible! Did you realize that? We created an alert with just three lines of code!
Well, another reason to think about that is to create dismissible alerts. Just add the highlighted line to the alert component and you will get the expected result:
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
You have made a new Tweet.
</div>
This will create a close button that will dismiss the component using the data-dismiss="alert"
attribute. Refresh the web page and you will see the alert like this:

Now, it's time for us to create our recipe for the alert. We have two tasks: add a title to .alert
and use the links inside it.
First, create a heading element inside the alert:
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<h3>Tweet alert</h3>
You have made a new Tweet.
</div>
Then, adjust the CSS for the heading inside the alert:
.alert h3 { margin: 0 0 1rem; font-size: 1.4em; }
The final result of adding the title must be like what is shown in this screenshot:

For the second task, we have to add some links inside the component. Bootstrap can give us a little shortcut for this using the .alert-link
class in the link. The class will give the correctly matching color for the link in response to the kind of the alert shown.
Therefore, the HTML code is simple:
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<h3>Tweet alert</h3>
You have made a new Tweet.
<a href="#" class="alert-link">Click here to review your tweets.</a>
</div>
To finish our first alert usage, let's just add one last fancy thing in the CSS, refresh the browser after that, and check the final result, as shown in the next screenshot:
.alert { border-left-width: 0.5rem; }

Progress bars are very useful in web applications in cases where, for example, you need to wait for an action to be sent to the server while maintaining a feedback for the user that something is being done in the background.
For instance, we can create a progress bar to present the user that a new tweet is being posted. Likewise, other scenarios can suit well for a progress bar, for example, when you are uploading a file on the server or when the web client is loading some information.
To exemplify this, we will create another alert that will contain a progress bar inside for a new tweet post feedback, subliminally saying "Hey, wait until I finish my task!"
We replace the .alert
code that we just created with the new one presented here:
<div class="alert alert-info" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button> <h3>Posting new Tweet</h3> </div>
This will produce a blue alert using the colors from .alert-info
. In the new element, create the following code for the progress bar:
<div class="alert alert-info" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button> <h3>Posting new Tweet</h3> <div class="progress"> <div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100" style="width: 25%"> </div> </div> </div>
The result of the progress bar in shown in the next screenshot. Let's understand each part of the new component:

We created a div.progress
inside our alert component, which is the gray rectangle to be filled during the progress. Inside it, we have another tag, div.progress-bar
, to create the inside filler that contains the .progress-bar-info
class to make the bar blue, following the .info
contextual color.
The progress bar also has some aria-*
attributes and its size is set by the width: 25%
style. To change its size, just change the width style.
Just like alerts, progress bars have the same contextual colors of Bootstrap. Just use the .progress-bar-*
prefix while using the suffix of one of the contextual colors. It is also possible to apply stripe marks to the progress bar with the .progress-bar-striped
class:
<div class="alert alert-info" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<h3>Posting new Tweet</h3>
<div class="progress">
<div class="progress-bar progress-bar-info progress-bar-striped active" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100" style="width: 25%">
</div>
</div>
</div>
Finally, you can also animate the strip using the .active
class in conjunction with the .progress-bar-striped
class. Check out the next screenshot to see the result of addition of the classes:

Now we have a good opportunity to use the CSS @keyframes
animations.
If you check out the CSS code when you add the .progress-bar-striped
and .active
classes, Bootstrap will load the following animation:
.progress-bar.active { animation: progress-bar-stripes 2s linear infinite; }
This animation applies to the CSS selector, the @keyframe
defined at progress-bar-stripes
:
@keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } }
This means that the striped background will move from a position of 40 pixels to 0, repeating it every 2 seconds.
Well, nice to meet you progress-bar-stripes
, but I can do another animation! Create the following @keyframe
:
@keyframes w70 { from { width: 0%; } to { width: 70%; } }
The goal of this key frame is to change the width of our progress bar from 0% to 70% of the maximum when the page loads. Now apply the new animation to .progress-bar.active
:
.progress-bar.active { animation: w70 1s ease forwards, progress-bar-stripes 2s linear infinite; }
So, our animation will last 1 second and execute just once, since we defined it to be just forwards
. Note that we must override the animations, so after the new animation, which is w70
, add the current animation, which is progress-bar-stripes
. Refresh the page and see this fancy effect.
Progress bar options
Just like alerts, progress bars have the same contextual colors of Bootstrap. Just use the .progress-bar-*
prefix while using the suffix of one of the contextual colors. It is also possible to apply stripe marks to the progress bar with the .progress-bar-striped
class:
<div class="alert alert-info" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<h3>Posting new Tweet</h3>
<div class="progress">
<div class="progress-bar progress-bar-info progress-bar-striped active" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100" style="width: 25%">
</div>
</div>
</div>
Finally, you can also animate the strip using the .active
class in conjunction with the .progress-bar-striped
class. Check out the next screenshot to see the result of addition of the classes:

Now we have a good opportunity to use the CSS @keyframes
animations.
If you check out the CSS code when you add the .progress-bar-striped
and .active
classes, Bootstrap will load the following animation:
.progress-bar.active { animation: progress-bar-stripes 2s linear infinite; }
This animation applies to the CSS selector, the @keyframe
defined at progress-bar-stripes
:
@keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } }
This means that the striped background will move from a position of 40 pixels to 0, repeating it every 2 seconds.
Well, nice to meet you progress-bar-stripes
, but I can do another animation! Create the following @keyframe
:
@keyframes w70 { from { width: 0%; } to { width: 70%; } }
The goal of this key frame is to change the width of our progress bar from 0% to 70% of the maximum when the page loads. Now apply the new animation to .progress-bar.active
:
.progress-bar.active { animation: w70 1s ease forwards, progress-bar-stripes 2s linear infinite; }
So, our animation will last 1 second and execute just once, since we defined it to be just forwards
. Note that we must override the animations, so after the new animation, which is w70
, add the current animation, which is progress-bar-stripes
. Refresh the page and see this fancy effect.
Animating the progress bar
Now we have a good opportunity to use the CSS @keyframes
animations.
If you check out the CSS code when you add the .progress-bar-striped
and .active
classes, Bootstrap will load the following animation:
.progress-bar.active { animation: progress-bar-stripes 2s linear infinite; }
This animation applies to the CSS selector, the @keyframe
defined at progress-bar-stripes
:
@keyframes progress-bar-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } }
This means that the striped background will move from a position of 40 pixels to 0, repeating it every 2 seconds.
Well, nice to meet you progress-bar-stripes
, but I can do another animation! Create the following @keyframe
:
@keyframes w70 { from { width: 0%; } to { width: 70%; } }
The goal of this key frame is to change the width of our progress bar from 0% to 70% of the maximum when the page loads. Now apply the new animation to .progress-bar.active
:
.progress-bar.active { animation: w70 1s ease forwards, progress-bar-stripes 2s linear infinite; }
So, our animation will last 1 second and execute just once, since we defined it to be just forwards
. Note that we must override the animations, so after the new animation, which is w70
, add the current animation, which is progress-bar-stripes
. Refresh the page and see this fancy effect.
Moving on with our web app example, it is time to create a settings page for the application. We have already created a link for this in the navigation bar, inside the button group. Do you remember?
So, in the same folder as that of the web app HTML file, create another one named settings.html
and update the link at the navigation bar:
<div id="nav-options" class="btn-group pull-right hidden-xs">
<button type="button" class="btn btn-default dropdown-toggle thumbnail" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img src="imgs/jon.png">
</button>
<ul class="dropdown-menu">
<li><a href="#">Profile</a></li>
<li><a href="settings.html">Setting</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Logout</a></li>
</ul>
</div>
In this page, we use the same template that we used in the web application, copying the navigation bar, the grid layout, and the left-hand side #profile
column. So, the settings page will look like this:

Now we will add some content to this page. Our main goal here is to use some other navigation Bootstrap components that will be handy for us.
The first navigation menu that we will use here is Pills, using the vertical stack option. Pills are a Bootstrap component used to create menus that can be horizontal or vertical. Many web apps use them for side menus, just as we will soon do.
The basic usage for navigation components is the use of the .nav
class followed by another one regarding the navigation option. In our case, we will use the .nav-pills
class to create the desired effect in conjunction with the .nav-stacked
class to vertically stack the pills. Create a .card
element just after #profile
and add the code related to the pills navigation:
<div id="profile-settings" class="card"> <ul class="nav nav-pills nav-stacked"> <li role="presentation" class="active"> <a href="#"> Account <span class="glyphicon glyphicon-chevron-right pull-right" aria-hidden="true"></span> </a> </li> <li role="presentation"> <a href="#"> Security <span class="glyphicon glyphicon-chevron-right pull-right" aria-hidden="true"></span> </a> </li> <li role="presentation"> <a href="#"> Notifications <span class="glyphicon glyphicon-chevron-right pull-right" aria-hidden="true"></span> </a> </li> <li role="presentation"> <a href="#"> Design <span class="glyphicon glyphicon-chevron-right pull-right" aria-hidden="true"></span> </a> </li> </ul> </div>
In the CSS file, also add the following rule:
.row .card + .card { margin-top: 2rem; }
With this, every .card
element followed by another .card
element will automatically create a margin, because of the use of the +
selector. Open the settings page, and you will see the result like what is shown in the following screenshot:

Basically, we created a list with the mentioned classes: .nav
, .nav-pills
, and .nav-stacked
. The list is composed of four items, containing a link and a left arrow icon. To place the arrows at the right-hand side, we again used the .pull-right
helper together with the .glyphicon-chevron-right
icon. In the first item, we added the .active
class, which turned this item blue and changed the colors of both the text and the icon.
This is almost awesome! It just needs some adjustments in the CSS to look perfect. Let's use some :nth-child
selectors to style some elements based on their position, such as the first item in the menu (:first-child
) and the last item (:last-child
). Add the following CSS:
#profile-settings .nav-stacked li { border-bottom: 1px solid #e5e5e5; margin: 0; } #profile-settings .nav-stacked a { border-radius: 0; } #profile-settings .nav-stacked li:first-child a { border-radius: 0.4rem 0.4rem 0 0; } #profile-settings .nav-stacked li:last-child { border-bottom: 0; } #profile-settings .nav-stacked li:last-child a { border-radius: 0 0 0.4rem 0.4rem; }
We just removed unwanted margins and the border radius, while adding a border bottom to all elements in the list, except the last one. This is because of the #profile-settings .nav-stacked li:last-child
selector, where we a specific rule only for the last item element.
We also changed border-radius
for the first element and the last element to create a rounded border in the pill list. The .nav-pill
menu will appear like what is shown in the next screenshot:

In the #main
column, we must create a tab option with the settings content. Bootstrap also offers a tabs component with the navigation components. First, we will work with the markup and CSS style and use it with JavaScript.
Therefore, inside the #main
tag, place the following markup, corresponding to the Bootstrap tabs:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user">User info</a> </li> <li role="presentation"> <a href="#account-language">Language</a> </li> <li role="presentation"> <a href="#account-mobile">Mobile</a> </li> </ul>
Just like the Pills, to use tabs, create a list with the .nav
and .nav-tabs
classes. We used the .nav-justified
class as well to make the tabs equally distributed over the component.
Moreover, we populated the list with some items. Each link of the item contains an identifier, which will be used to link each tab to the corresponding content. Keep that information at the moment.
Let's add some CSS rules to keep the same border colors that we are using:
#account-tabs > li { border-bottom: 0.1rem solid #e5e5e5; } #account-tabs a { border-bottom: 0; } #account-tabs li.active { border-bottom: 0; }
Refresh the web page and you should see it like this:

To add the tab content, we use the named tab panes. Each tab must be placed in an element with the .tab-pane
class and have the corresponding identifier in the tab component. After the tab list, add the HTML code for the tab panes:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user">User info</a> </li> <li role="presentation"> <a href="#account-language">Language</a> </li> <li role="presentation"> <a href="#account-mobile">Mobile</a> </li> </ul> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="account-user"> User info tab pane </div> <div role="tabpanel" class="tab-pane" id="account-language"> Language tab pane </div> <div role="tabpanel" class="tab-pane" id="account-mobile"> Mobile tab pane </div> </div>
Refresh the web page and you will see only the content of #account-user
appearing, although clicking on other tabs will not cause any switch between them. This is because we have not initialized the component through JavaScript yet.
We can initialize the tabs with simple JavaScript code, like what is presented next. However, we will do that in a smarter way using data markup:
$('#account-tabs a').click(function (e) { e.preventDefault() $(this).tab('show') })
For data markup, we must add the data-toggle="tab"
attribute on the link elements, inside the list. Change the list markup for the following:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user" data-toggle="tab">User info</a> </li> <li role="presentation"> <a href="#account-language" data-toggle="tab">Language</a> </li> <li role="presentation"> <a href="#account-mobile" data-toggle="tab">Mobile</a> </li> </ul>
Refresh the web browser and switch between the tabs. It works like a charm! To make it even fancier, add the .fade
class to each .tab-pane
to create a fade effect when changing tabs.
Inside the .tab-pane
identified by #account-user
, let's add some content. Since it is a configuration menu, we will create a form to set the user settings. Again, we will work with some forms in Bootstrap. Do you remember how to use them?
In the form, we will have three inputs (name, username, and e-mail) followed by a button to save the changes. We will use the .form-horizontal
class to make each form input next its label and stacked by each other. So, place the following code inside the #account-user
element:
<div id="account-user" role="tabpanel" class="tab-pane active" > <form class="form-horizontal"> <div class="form-group"> <label class="col-sm-3 control-label">Name</label> <div class="col-sm-9"> <input type="text" class="form-control" value="Jonny Doo"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Username</label> <div class="col-sm-9"> <div class="input-group"> <div class="input-group-addon">@</div> <input type="text" class="form-control" value="jonnydoo"> </div> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Email</label> <div class="col-sm-9"> <input type="email" class="form-control" value="jonnydoo@dogmail.com"> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-primary"> Save changes </button> </div> </div> </form> </div>
Break through the code, we set the labels to fill a quarter of the form row, while the input fills the rest. We again used the input groups to add the @
sign before the username field.
Each label has the .col-sm-3
class and the input the .col-sm-9
class. As we said, the forms respect the grid system layout, so we can apply the same classes here. We also added the .col-sm-offset-3
class to the submit button for a correct offset.
Right now, the page should look like the following screenshot. Isn't it looking nicer?

CSS turn! We must make it look prettier, so let's play with some paddings. However, before anything, add the class to .card
to the .tab-content
. Next, let's fix the borders and margins in .tab-content
by adding some padding and some negative margin, as follows:
#main .tab-content { padding: 2em; margin-top: -0.1rem; }
Then, remove the border from the tab list and change the z-index
of the tabs:
#account-tabs > li { border-bottom: 0; } #account-tabs { position: relative; z-index: 99; }
Finally, remove the margin from the save changes button using another nth
recipe, as follows:
#main .form-horizontal .form-group:last-child { margin-bottom: 0; }
Nice! Refresh the web app and see the result, like this:

With these changes, we have made the form from .tab-content
look like a card. We also added some margins and padding to correct the designs. Lastly, with the margin top and z-index, we make the selected tab blend correctly with the content.
To finalize the settings page, we must fill the right column of the web app. To do this, we will create a menu that presents some general statistics about the user.
In order to do that, we will use the Bootstrap List group component. List group is powerful in Bootstrap as it can seem similar to Bootstrap Cards, but it has more specific options for menu list generation, such as headers, disabled items, and much more.
So let's start doing this! Create the HTML markup at the #right-content
element:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides </li> <li class="list-group-item"> Captured mice </li> <li class="list-group-item"> Postmen frightened </li> <li class="list-group-item"> Always alert badge </li> </ul> </div>
It is a simple list and we just added the .list-group
class to the list, while adding the .list-group-item
class for each item in the list. For the first item, we used the .list-group-item-info
contextual color class to make it blue, according to the Bootstrap contextual colors.
Before we continue, we have to change the colors of the borders from list group to respect the same border color that we have been using:
.list-group-item { border-color: #e5e5e5; }
The result that you should see right know is like the one presented in the next screenshot. List groups is a very handy component that we can use to achieve almost the same effect that we got using Pills, but here we are using fewer CSS rules.

Labels and badges are Bootstrap components that can easily highlight some text or information. They can be used in any place, as we did in the navigation bar, on the notification item.
Just like most of Bootstrap's components, labels follow the contextual colors of Bootstrap, while badges do not have this option. To consolidate their utilization, let's add some of them to the right menu, regarding the statistics, because after all we want to know our stats!
It will be pretty easy since we have worked with this before. For the three first items, we will use labels, and for the last one, we will use a badge with an icon. Just add the highlighted code to the current .list-group
:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides <span class="label label-success">3</span> </li> <li class="list-group-item"> Captured mice <span class="label label-danger">87</span> </li> <li class="list-group-item"> Postmen frightened <span class="label label-default">2</span> </li> <li class="list-group-item"> Always alert badge <span class="badge glyphicon glyphicon-star" aria-hidden="true"> </span> </li> </ul> </div>
We must pay attention to some points here. The first is that we used the .label
class together with the contextual color class, like this: .label-*
. Here, *
is the name of the contextual class.
The second thing is that if you refresh your web page right now, you will see that Bootstrap does have a CSS for aligning all badges on the right, but it does not apply the same rule for labels. So, add the next CSS:
#right-content .list-group .label { float: right; }
The third point is that we used badges and icons in the same span. This is possible, and then we just need to adjust the CSS render:
#right-content .list-group .label { padding: 0.3rem 0.6rem; } #right-content .list-group .badge.glyphicon-star { background-color: #f0ad4e; padding: 0.4rem; padding-left: 0.5rem; }
By adding these rules, we adjusted the padding for the labels, adjusted the padding for the badge, and correctly set the yellow background for the star badge. See the result in the browser; it must look like this:

Cool! We've done another page for our web app. The stats menu looks cute. We will not cover the other page settings menus in this book, since they follow almost the same structure that we showed in this example. Try doing that as homework.
Pills of stack
The first navigation menu that we will use here is Pills, using the vertical stack option. Pills are a Bootstrap component used to create menus that can be horizontal or vertical. Many web apps use them for side menus, just as we will soon do.
The basic usage for navigation components is the use of the .nav
class followed by another one regarding the navigation option. In our case, we will use the .nav-pills
class to create the desired effect in conjunction with the .nav-stacked
class to vertically stack the pills. Create a .card
element just after #profile
and add the code related to the pills navigation:
<div id="profile-settings" class="card"> <ul class="nav nav-pills nav-stacked"> <li role="presentation" class="active"> <a href="#"> Account <span class="glyphicon glyphicon-chevron-right pull-right" aria-hidden="true"></span> </a> </li> <li role="presentation"> <a href="#"> Security <span class="glyphicon glyphicon-chevron-right pull-right" aria-hidden="true"></span> </a> </li> <li role="presentation"> <a href="#"> Notifications <span class="glyphicon glyphicon-chevron-right pull-right" aria-hidden="true"></span> </a> </li> <li role="presentation"> <a href="#"> Design <span class="glyphicon glyphicon-chevron-right pull-right" aria-hidden="true"></span> </a> </li> </ul> </div>
In the CSS file, also add the following rule:
.row .card + .card { margin-top: 2rem; }
With this, every .card
element followed by another .card
element will automatically create a margin, because of the use of the +
selector. Open the settings page, and you will see the result like what is shown in the following screenshot:

Basically, we created a list with the mentioned classes: .nav
, .nav-pills
, and .nav-stacked
. The list is composed of four items, containing a link and a left arrow icon. To place the arrows at the right-hand side, we again used the .pull-right
helper together with the .glyphicon-chevron-right
icon. In the first item, we added the .active
class, which turned this item blue and changed the colors of both the text and the icon.
This is almost awesome! It just needs some adjustments in the CSS to look perfect. Let's use some :nth-child
selectors to style some elements based on their position, such as the first item in the menu (:first-child
) and the last item (:last-child
). Add the following CSS:
#profile-settings .nav-stacked li { border-bottom: 1px solid #e5e5e5; margin: 0; } #profile-settings .nav-stacked a { border-radius: 0; } #profile-settings .nav-stacked li:first-child a { border-radius: 0.4rem 0.4rem 0 0; } #profile-settings .nav-stacked li:last-child { border-bottom: 0; } #profile-settings .nav-stacked li:last-child a { border-radius: 0 0 0.4rem 0.4rem; }
We just removed unwanted margins and the border radius, while adding a border bottom to all elements in the list, except the last one. This is because of the #profile-settings .nav-stacked li:last-child
selector, where we a specific rule only for the last item element.
We also changed border-radius
for the first element and the last element to create a rounded border in the pill list. The .nav-pill
menu will appear like what is shown in the next screenshot:

In the #main
column, we must create a tab option with the settings content. Bootstrap also offers a tabs component with the navigation components. First, we will work with the markup and CSS style and use it with JavaScript.
Therefore, inside the #main
tag, place the following markup, corresponding to the Bootstrap tabs:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user">User info</a> </li> <li role="presentation"> <a href="#account-language">Language</a> </li> <li role="presentation"> <a href="#account-mobile">Mobile</a> </li> </ul>
Just like the Pills, to use tabs, create a list with the .nav
and .nav-tabs
classes. We used the .nav-justified
class as well to make the tabs equally distributed over the component.
Moreover, we populated the list with some items. Each link of the item contains an identifier, which will be used to link each tab to the corresponding content. Keep that information at the moment.
Let's add some CSS rules to keep the same border colors that we are using:
#account-tabs > li { border-bottom: 0.1rem solid #e5e5e5; } #account-tabs a { border-bottom: 0; } #account-tabs li.active { border-bottom: 0; }
Refresh the web page and you should see it like this:

To add the tab content, we use the named tab panes. Each tab must be placed in an element with the .tab-pane
class and have the corresponding identifier in the tab component. After the tab list, add the HTML code for the tab panes:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user">User info</a> </li> <li role="presentation"> <a href="#account-language">Language</a> </li> <li role="presentation"> <a href="#account-mobile">Mobile</a> </li> </ul> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="account-user"> User info tab pane </div> <div role="tabpanel" class="tab-pane" id="account-language"> Language tab pane </div> <div role="tabpanel" class="tab-pane" id="account-mobile"> Mobile tab pane </div> </div>
Refresh the web page and you will see only the content of #account-user
appearing, although clicking on other tabs will not cause any switch between them. This is because we have not initialized the component through JavaScript yet.
We can initialize the tabs with simple JavaScript code, like what is presented next. However, we will do that in a smarter way using data markup:
$('#account-tabs a').click(function (e) { e.preventDefault() $(this).tab('show') })
For data markup, we must add the data-toggle="tab"
attribute on the link elements, inside the list. Change the list markup for the following:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user" data-toggle="tab">User info</a> </li> <li role="presentation"> <a href="#account-language" data-toggle="tab">Language</a> </li> <li role="presentation"> <a href="#account-mobile" data-toggle="tab">Mobile</a> </li> </ul>
Refresh the web browser and switch between the tabs. It works like a charm! To make it even fancier, add the .fade
class to each .tab-pane
to create a fade effect when changing tabs.
Inside the .tab-pane
identified by #account-user
, let's add some content. Since it is a configuration menu, we will create a form to set the user settings. Again, we will work with some forms in Bootstrap. Do you remember how to use them?
In the form, we will have three inputs (name, username, and e-mail) followed by a button to save the changes. We will use the .form-horizontal
class to make each form input next its label and stacked by each other. So, place the following code inside the #account-user
element:
<div id="account-user" role="tabpanel" class="tab-pane active" > <form class="form-horizontal"> <div class="form-group"> <label class="col-sm-3 control-label">Name</label> <div class="col-sm-9"> <input type="text" class="form-control" value="Jonny Doo"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Username</label> <div class="col-sm-9"> <div class="input-group"> <div class="input-group-addon">@</div> <input type="text" class="form-control" value="jonnydoo"> </div> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Email</label> <div class="col-sm-9"> <input type="email" class="form-control" value="jonnydoo@dogmail.com"> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-primary"> Save changes </button> </div> </div> </form> </div>
Break through the code, we set the labels to fill a quarter of the form row, while the input fills the rest. We again used the input groups to add the @
sign before the username field.
Each label has the .col-sm-3
class and the input the .col-sm-9
class. As we said, the forms respect the grid system layout, so we can apply the same classes here. We also added the .col-sm-offset-3
class to the submit button for a correct offset.
Right now, the page should look like the following screenshot. Isn't it looking nicer?

CSS turn! We must make it look prettier, so let's play with some paddings. However, before anything, add the class to .card
to the .tab-content
. Next, let's fix the borders and margins in .tab-content
by adding some padding and some negative margin, as follows:
#main .tab-content { padding: 2em; margin-top: -0.1rem; }
Then, remove the border from the tab list and change the z-index
of the tabs:
#account-tabs > li { border-bottom: 0; } #account-tabs { position: relative; z-index: 99; }
Finally, remove the margin from the save changes button using another nth
recipe, as follows:
#main .form-horizontal .form-group:last-child { margin-bottom: 0; }
Nice! Refresh the web app and see the result, like this:

With these changes, we have made the form from .tab-content
look like a card. We also added some margins and padding to correct the designs. Lastly, with the margin top and z-index, we make the selected tab blend correctly with the content.
To finalize the settings page, we must fill the right column of the web app. To do this, we will create a menu that presents some general statistics about the user.
In order to do that, we will use the Bootstrap List group component. List group is powerful in Bootstrap as it can seem similar to Bootstrap Cards, but it has more specific options for menu list generation, such as headers, disabled items, and much more.
So let's start doing this! Create the HTML markup at the #right-content
element:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides </li> <li class="list-group-item"> Captured mice </li> <li class="list-group-item"> Postmen frightened </li> <li class="list-group-item"> Always alert badge </li> </ul> </div>
It is a simple list and we just added the .list-group
class to the list, while adding the .list-group-item
class for each item in the list. For the first item, we used the .list-group-item-info
contextual color class to make it blue, according to the Bootstrap contextual colors.
Before we continue, we have to change the colors of the borders from list group to respect the same border color that we have been using:
.list-group-item { border-color: #e5e5e5; }
The result that you should see right know is like the one presented in the next screenshot. List groups is a very handy component that we can use to achieve almost the same effect that we got using Pills, but here we are using fewer CSS rules.

Labels and badges are Bootstrap components that can easily highlight some text or information. They can be used in any place, as we did in the navigation bar, on the notification item.
Just like most of Bootstrap's components, labels follow the contextual colors of Bootstrap, while badges do not have this option. To consolidate their utilization, let's add some of them to the right menu, regarding the statistics, because after all we want to know our stats!
It will be pretty easy since we have worked with this before. For the three first items, we will use labels, and for the last one, we will use a badge with an icon. Just add the highlighted code to the current .list-group
:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides <span class="label label-success">3</span> </li> <li class="list-group-item"> Captured mice <span class="label label-danger">87</span> </li> <li class="list-group-item"> Postmen frightened <span class="label label-default">2</span> </li> <li class="list-group-item"> Always alert badge <span class="badge glyphicon glyphicon-star" aria-hidden="true"> </span> </li> </ul> </div>
We must pay attention to some points here. The first is that we used the .label
class together with the contextual color class, like this: .label-*
. Here, *
is the name of the contextual class.
The second thing is that if you refresh your web page right now, you will see that Bootstrap does have a CSS for aligning all badges on the right, but it does not apply the same rule for labels. So, add the next CSS:
#right-content .list-group .label { float: right; }
The third point is that we used badges and icons in the same span. This is possible, and then we just need to adjust the CSS render:
#right-content .list-group .label { padding: 0.3rem 0.6rem; } #right-content .list-group .badge.glyphicon-star { background-color: #f0ad4e; padding: 0.4rem; padding-left: 0.5rem; }
By adding these rules, we adjusted the padding for the labels, adjusted the padding for the badge, and correctly set the yellow background for the star badge. See the result in the browser; it must look like this:

Cool! We've done another page for our web app. The stats menu looks cute. We will not cover the other page settings menus in this book, since they follow almost the same structure that we showed in this example. Try doing that as homework.
Tabs in the middle
In the #main
column, we must create a tab option with the settings content. Bootstrap also offers a tabs component with the navigation components. First, we will work with the markup and CSS style and use it with JavaScript.
Therefore, inside the #main
tag, place the following markup, corresponding to the Bootstrap tabs:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user">User info</a> </li> <li role="presentation"> <a href="#account-language">Language</a> </li> <li role="presentation"> <a href="#account-mobile">Mobile</a> </li> </ul>
Just like the Pills, to use tabs, create a list with the .nav
and .nav-tabs
classes. We used the .nav-justified
class as well to make the tabs equally distributed over the component.
Moreover, we populated the list with some items. Each link of the item contains an identifier, which will be used to link each tab to the corresponding content. Keep that information at the moment.
Let's add some CSS rules to keep the same border colors that we are using:
#account-tabs > li { border-bottom: 0.1rem solid #e5e5e5; } #account-tabs a { border-bottom: 0; } #account-tabs li.active { border-bottom: 0; }
Refresh the web page and you should see it like this:

To add the tab content, we use the named tab panes. Each tab must be placed in an element with the .tab-pane
class and have the corresponding identifier in the tab component. After the tab list, add the HTML code for the tab panes:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user">User info</a> </li> <li role="presentation"> <a href="#account-language">Language</a> </li> <li role="presentation"> <a href="#account-mobile">Mobile</a> </li> </ul> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="account-user"> User info tab pane </div> <div role="tabpanel" class="tab-pane" id="account-language"> Language tab pane </div> <div role="tabpanel" class="tab-pane" id="account-mobile"> Mobile tab pane </div> </div>
Refresh the web page and you will see only the content of #account-user
appearing, although clicking on other tabs will not cause any switch between them. This is because we have not initialized the component through JavaScript yet.
We can initialize the tabs with simple JavaScript code, like what is presented next. However, we will do that in a smarter way using data markup:
$('#account-tabs a').click(function (e) { e.preventDefault() $(this).tab('show') })
For data markup, we must add the data-toggle="tab"
attribute on the link elements, inside the list. Change the list markup for the following:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user" data-toggle="tab">User info</a> </li> <li role="presentation"> <a href="#account-language" data-toggle="tab">Language</a> </li> <li role="presentation"> <a href="#account-mobile" data-toggle="tab">Mobile</a> </li> </ul>
Refresh the web browser and switch between the tabs. It works like a charm! To make it even fancier, add the .fade
class to each .tab-pane
to create a fade effect when changing tabs.
Inside the .tab-pane
identified by #account-user
, let's add some content. Since it is a configuration menu, we will create a form to set the user settings. Again, we will work with some forms in Bootstrap. Do you remember how to use them?
In the form, we will have three inputs (name, username, and e-mail) followed by a button to save the changes. We will use the .form-horizontal
class to make each form input next its label and stacked by each other. So, place the following code inside the #account-user
element:
<div id="account-user" role="tabpanel" class="tab-pane active" > <form class="form-horizontal"> <div class="form-group"> <label class="col-sm-3 control-label">Name</label> <div class="col-sm-9"> <input type="text" class="form-control" value="Jonny Doo"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Username</label> <div class="col-sm-9"> <div class="input-group"> <div class="input-group-addon">@</div> <input type="text" class="form-control" value="jonnydoo"> </div> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Email</label> <div class="col-sm-9"> <input type="email" class="form-control" value="jonnydoo@dogmail.com"> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-primary"> Save changes </button> </div> </div> </form> </div>
Break through the code, we set the labels to fill a quarter of the form row, while the input fills the rest. We again used the input groups to add the @
sign before the username field.
Each label has the .col-sm-3
class and the input the .col-sm-9
class. As we said, the forms respect the grid system layout, so we can apply the same classes here. We also added the .col-sm-offset-3
class to the submit button for a correct offset.
Right now, the page should look like the following screenshot. Isn't it looking nicer?

CSS turn! We must make it look prettier, so let's play with some paddings. However, before anything, add the class to .card
to the .tab-content
. Next, let's fix the borders and margins in .tab-content
by adding some padding and some negative margin, as follows:
#main .tab-content { padding: 2em; margin-top: -0.1rem; }
Then, remove the border from the tab list and change the z-index
of the tabs:
#account-tabs > li { border-bottom: 0; } #account-tabs { position: relative; z-index: 99; }
Finally, remove the margin from the save changes button using another nth
recipe, as follows:
#main .form-horizontal .form-group:last-child { margin-bottom: 0; }
Nice! Refresh the web app and see the result, like this:

With these changes, we have made the form from .tab-content
look like a card. We also added some margins and padding to correct the designs. Lastly, with the margin top and z-index, we make the selected tab blend correctly with the content.
To finalize the settings page, we must fill the right column of the web app. To do this, we will create a menu that presents some general statistics about the user.
In order to do that, we will use the Bootstrap List group component. List group is powerful in Bootstrap as it can seem similar to Bootstrap Cards, but it has more specific options for menu list generation, such as headers, disabled items, and much more.
So let's start doing this! Create the HTML markup at the #right-content
element:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides </li> <li class="list-group-item"> Captured mice </li> <li class="list-group-item"> Postmen frightened </li> <li class="list-group-item"> Always alert badge </li> </ul> </div>
It is a simple list and we just added the .list-group
class to the list, while adding the .list-group-item
class for each item in the list. For the first item, we used the .list-group-item-info
contextual color class to make it blue, according to the Bootstrap contextual colors.
Before we continue, we have to change the colors of the borders from list group to respect the same border color that we have been using:
.list-group-item { border-color: #e5e5e5; }
The result that you should see right know is like the one presented in the next screenshot. List groups is a very handy component that we can use to achieve almost the same effect that we got using Pills, but here we are using fewer CSS rules.

Labels and badges are Bootstrap components that can easily highlight some text or information. They can be used in any place, as we did in the navigation bar, on the notification item.
Just like most of Bootstrap's components, labels follow the contextual colors of Bootstrap, while badges do not have this option. To consolidate their utilization, let's add some of them to the right menu, regarding the statistics, because after all we want to know our stats!
It will be pretty easy since we have worked with this before. For the three first items, we will use labels, and for the last one, we will use a badge with an icon. Just add the highlighted code to the current .list-group
:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides <span class="label label-success">3</span> </li> <li class="list-group-item"> Captured mice <span class="label label-danger">87</span> </li> <li class="list-group-item"> Postmen frightened <span class="label label-default">2</span> </li> <li class="list-group-item"> Always alert badge <span class="badge glyphicon glyphicon-star" aria-hidden="true"> </span> </li> </ul> </div>
We must pay attention to some points here. The first is that we used the .label
class together with the contextual color class, like this: .label-*
. Here, *
is the name of the contextual class.
The second thing is that if you refresh your web page right now, you will see that Bootstrap does have a CSS for aligning all badges on the right, but it does not apply the same rule for labels. So, add the next CSS:
#right-content .list-group .label { float: right; }
The third point is that we used badges and icons in the same span. This is possible, and then we just need to adjust the CSS render:
#right-content .list-group .label { padding: 0.3rem 0.6rem; } #right-content .list-group .badge.glyphicon-star { background-color: #f0ad4e; padding: 0.4rem; padding-left: 0.5rem; }
By adding these rules, we adjusted the padding for the labels, adjusted the padding for the badge, and correctly set the yellow background for the star badge. See the result in the browser; it must look like this:

Cool! We've done another page for our web app. The stats menu looks cute. We will not cover the other page settings menus in this book, since they follow almost the same structure that we showed in this example. Try doing that as homework.
Adding the tab content
To add the tab content, we use the named tab panes. Each tab must be placed in an element with the .tab-pane
class and have the corresponding identifier in the tab component. After the tab list, add the HTML code for the tab panes:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user">User info</a> </li> <li role="presentation"> <a href="#account-language">Language</a> </li> <li role="presentation"> <a href="#account-mobile">Mobile</a> </li> </ul> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="account-user"> User info tab pane </div> <div role="tabpanel" class="tab-pane" id="account-language"> Language tab pane </div> <div role="tabpanel" class="tab-pane" id="account-mobile"> Mobile tab pane </div> </div>
Refresh the web page and you will see only the content of #account-user
appearing, although clicking on other tabs will not cause any switch between them. This is because we have not initialized the component through JavaScript yet.
We can initialize the tabs with simple JavaScript code, like what is presented next. However, we will do that in a smarter way using data markup:
$('#account-tabs a').click(function (e) { e.preventDefault() $(this).tab('show') })
For data markup, we must add the data-toggle="tab"
attribute on the link elements, inside the list. Change the list markup for the following:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user" data-toggle="tab">User info</a> </li> <li role="presentation"> <a href="#account-language" data-toggle="tab">Language</a> </li> <li role="presentation"> <a href="#account-mobile" data-toggle="tab">Mobile</a> </li> </ul>
Refresh the web browser and switch between the tabs. It works like a charm! To make it even fancier, add the .fade
class to each .tab-pane
to create a fade effect when changing tabs.
Inside the .tab-pane
identified by #account-user
, let's add some content. Since it is a configuration menu, we will create a form to set the user settings. Again, we will work with some forms in Bootstrap. Do you remember how to use them?
In the form, we will have three inputs (name, username, and e-mail) followed by a button to save the changes. We will use the .form-horizontal
class to make each form input next its label and stacked by each other. So, place the following code inside the #account-user
element:
<div id="account-user" role="tabpanel" class="tab-pane active" > <form class="form-horizontal"> <div class="form-group"> <label class="col-sm-3 control-label">Name</label> <div class="col-sm-9"> <input type="text" class="form-control" value="Jonny Doo"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Username</label> <div class="col-sm-9"> <div class="input-group"> <div class="input-group-addon">@</div> <input type="text" class="form-control" value="jonnydoo"> </div> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Email</label> <div class="col-sm-9"> <input type="email" class="form-control" value="jonnydoo@dogmail.com"> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-primary"> Save changes </button> </div> </div> </form> </div>
Break through the code, we set the labels to fill a quarter of the form row, while the input fills the rest. We again used the input groups to add the @
sign before the username field.
Each label has the .col-sm-3
class and the input the .col-sm-9
class. As we said, the forms respect the grid system layout, so we can apply the same classes here. We also added the .col-sm-offset-3
class to the submit button for a correct offset.
Right now, the page should look like the following screenshot. Isn't it looking nicer?

CSS turn! We must make it look prettier, so let's play with some paddings. However, before anything, add the class to .card
to the .tab-content
. Next, let's fix the borders and margins in .tab-content
by adding some padding and some negative margin, as follows:
#main .tab-content { padding: 2em; margin-top: -0.1rem; }
Then, remove the border from the tab list and change the z-index
of the tabs:
#account-tabs > li { border-bottom: 0; } #account-tabs { position: relative; z-index: 99; }
Finally, remove the margin from the save changes button using another nth
recipe, as follows:
#main .form-horizontal .form-group:last-child { margin-bottom: 0; }
Nice! Refresh the web app and see the result, like this:

With these changes, we have made the form from .tab-content
look like a card. We also added some margins and padding to correct the designs. Lastly, with the margin top and z-index, we make the selected tab blend correctly with the content.
To finalize the settings page, we must fill the right column of the web app. To do this, we will create a menu that presents some general statistics about the user.
In order to do that, we will use the Bootstrap List group component. List group is powerful in Bootstrap as it can seem similar to Bootstrap Cards, but it has more specific options for menu list generation, such as headers, disabled items, and much more.
So let's start doing this! Create the HTML markup at the #right-content
element:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides </li> <li class="list-group-item"> Captured mice </li> <li class="list-group-item"> Postmen frightened </li> <li class="list-group-item"> Always alert badge </li> </ul> </div>
It is a simple list and we just added the .list-group
class to the list, while adding the .list-group-item
class for each item in the list. For the first item, we used the .list-group-item-info
contextual color class to make it blue, according to the Bootstrap contextual colors.
Before we continue, we have to change the colors of the borders from list group to respect the same border color that we have been using:
.list-group-item { border-color: #e5e5e5; }
The result that you should see right know is like the one presented in the next screenshot. List groups is a very handy component that we can use to achieve almost the same effect that we got using Pills, but here we are using fewer CSS rules.

Labels and badges are Bootstrap components that can easily highlight some text or information. They can be used in any place, as we did in the navigation bar, on the notification item.
Just like most of Bootstrap's components, labels follow the contextual colors of Bootstrap, while badges do not have this option. To consolidate their utilization, let's add some of them to the right menu, regarding the statistics, because after all we want to know our stats!
It will be pretty easy since we have worked with this before. For the three first items, we will use labels, and for the last one, we will use a badge with an icon. Just add the highlighted code to the current .list-group
:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides <span class="label label-success">3</span> </li> <li class="list-group-item"> Captured mice <span class="label label-danger">87</span> </li> <li class="list-group-item"> Postmen frightened <span class="label label-default">2</span> </li> <li class="list-group-item"> Always alert badge <span class="badge glyphicon glyphicon-star" aria-hidden="true"> </span> </li> </ul> </div>
We must pay attention to some points here. The first is that we used the .label
class together with the contextual color class, like this: .label-*
. Here, *
is the name of the contextual class.
The second thing is that if you refresh your web page right now, you will see that Bootstrap does have a CSS for aligning all badges on the right, but it does not apply the same rule for labels. So, add the next CSS:
#right-content .list-group .label { float: right; }
The third point is that we used badges and icons in the same span. This is possible, and then we just need to adjust the CSS render:
#right-content .list-group .label { padding: 0.3rem 0.6rem; } #right-content .list-group .badge.glyphicon-star { background-color: #f0ad4e; padding: 0.4rem; padding-left: 0.5rem; }
By adding these rules, we adjusted the padding for the labels, adjusted the padding for the badge, and correctly set the yellow background for the star badge. See the result in the browser; it must look like this:

Cool! We've done another page for our web app. The stats menu looks cute. We will not cover the other page settings menus in this book, since they follow almost the same structure that we showed in this example. Try doing that as homework.
Using the Bootstrap tabs plugin
We can initialize the tabs with simple JavaScript code, like what is presented next. However, we will do that in a smarter way using data markup:
$('#account-tabs a').click(function (e) { e.preventDefault() $(this).tab('show') })
For data markup, we must add the data-toggle="tab"
attribute on the link elements, inside the list. Change the list markup for the following:
<ul id="account-tabs" class="nav nav-tabs nav-justified"> <li role="presentation" class="active"> <a href="#account-user" data-toggle="tab">User info</a> </li> <li role="presentation"> <a href="#account-language" data-toggle="tab">Language</a> </li> <li role="presentation"> <a href="#account-mobile" data-toggle="tab">Mobile</a> </li> </ul>
Refresh the web browser and switch between the tabs. It works like a charm! To make it even fancier, add the .fade
class to each .tab-pane
to create a fade effect when changing tabs.
Inside the .tab-pane
identified by #account-user
, let's add some content. Since it is a configuration menu, we will create a form to set the user settings. Again, we will work with some forms in Bootstrap. Do you remember how to use them?
In the form, we will have three inputs (name, username, and e-mail) followed by a button to save the changes. We will use the .form-horizontal
class to make each form input next its label and stacked by each other. So, place the following code inside the #account-user
element:
<div id="account-user" role="tabpanel" class="tab-pane active" > <form class="form-horizontal"> <div class="form-group"> <label class="col-sm-3 control-label">Name</label> <div class="col-sm-9"> <input type="text" class="form-control" value="Jonny Doo"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Username</label> <div class="col-sm-9"> <div class="input-group"> <div class="input-group-addon">@</div> <input type="text" class="form-control" value="jonnydoo"> </div> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Email</label> <div class="col-sm-9"> <input type="email" class="form-control" value="jonnydoo@dogmail.com"> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-primary"> Save changes </button> </div> </div> </form> </div>
Break through the code, we set the labels to fill a quarter of the form row, while the input fills the rest. We again used the input groups to add the @
sign before the username field.
Each label has the .col-sm-3
class and the input the .col-sm-9
class. As we said, the forms respect the grid system layout, so we can apply the same classes here. We also added the .col-sm-offset-3
class to the submit button for a correct offset.
Right now, the page should look like the following screenshot. Isn't it looking nicer?

CSS turn! We must make it look prettier, so let's play with some paddings. However, before anything, add the class to .card
to the .tab-content
. Next, let's fix the borders and margins in .tab-content
by adding some padding and some negative margin, as follows:
#main .tab-content { padding: 2em; margin-top: -0.1rem; }
Then, remove the border from the tab list and change the z-index
of the tabs:
#account-tabs > li { border-bottom: 0; } #account-tabs { position: relative; z-index: 99; }
Finally, remove the margin from the save changes button using another nth
recipe, as follows:
#main .form-horizontal .form-group:last-child { margin-bottom: 0; }
Nice! Refresh the web app and see the result, like this:

With these changes, we have made the form from .tab-content
look like a card. We also added some margins and padding to correct the designs. Lastly, with the margin top and z-index, we make the selected tab blend correctly with the content.
To finalize the settings page, we must fill the right column of the web app. To do this, we will create a menu that presents some general statistics about the user.
In order to do that, we will use the Bootstrap List group component. List group is powerful in Bootstrap as it can seem similar to Bootstrap Cards, but it has more specific options for menu list generation, such as headers, disabled items, and much more.
So let's start doing this! Create the HTML markup at the #right-content
element:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides </li> <li class="list-group-item"> Captured mice </li> <li class="list-group-item"> Postmen frightened </li> <li class="list-group-item"> Always alert badge </li> </ul> </div>
It is a simple list and we just added the .list-group
class to the list, while adding the .list-group-item
class for each item in the list. For the first item, we used the .list-group-item-info
contextual color class to make it blue, according to the Bootstrap contextual colors.
Before we continue, we have to change the colors of the borders from list group to respect the same border color that we have been using:
.list-group-item { border-color: #e5e5e5; }
The result that you should see right know is like the one presented in the next screenshot. List groups is a very handy component that we can use to achieve almost the same effect that we got using Pills, but here we are using fewer CSS rules.

Labels and badges are Bootstrap components that can easily highlight some text or information. They can be used in any place, as we did in the navigation bar, on the notification item.
Just like most of Bootstrap's components, labels follow the contextual colors of Bootstrap, while badges do not have this option. To consolidate their utilization, let's add some of them to the right menu, regarding the statistics, because after all we want to know our stats!
It will be pretty easy since we have worked with this before. For the three first items, we will use labels, and for the last one, we will use a badge with an icon. Just add the highlighted code to the current .list-group
:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides <span class="label label-success">3</span> </li> <li class="list-group-item"> Captured mice <span class="label label-danger">87</span> </li> <li class="list-group-item"> Postmen frightened <span class="label label-default">2</span> </li> <li class="list-group-item"> Always alert badge <span class="badge glyphicon glyphicon-star" aria-hidden="true"> </span> </li> </ul> </div>
We must pay attention to some points here. The first is that we used the .label
class together with the contextual color class, like this: .label-*
. Here, *
is the name of the contextual class.
The second thing is that if you refresh your web page right now, you will see that Bootstrap does have a CSS for aligning all badges on the right, but it does not apply the same rule for labels. So, add the next CSS:
#right-content .list-group .label { float: right; }
The third point is that we used badges and icons in the same span. This is possible, and then we just need to adjust the CSS render:
#right-content .list-group .label { padding: 0.3rem 0.6rem; } #right-content .list-group .badge.glyphicon-star { background-color: #f0ad4e; padding: 0.4rem; padding-left: 0.5rem; }
By adding these rules, we adjusted the padding for the labels, adjusted the padding for the badge, and correctly set the yellow background for the star badge. See the result in the browser; it must look like this:

Cool! We've done another page for our web app. The stats menu looks cute. We will not cover the other page settings menus in this book, since they follow almost the same structure that we showed in this example. Try doing that as homework.
Creating content in the user info tab
Inside the .tab-pane
identified by #account-user
, let's add some content. Since it is a configuration menu, we will create a form to set the user settings. Again, we will work with some forms in Bootstrap. Do you remember how to use them?
In the form, we will have three inputs (name, username, and e-mail) followed by a button to save the changes. We will use the .form-horizontal
class to make each form input next its label and stacked by each other. So, place the following code inside the #account-user
element:
<div id="account-user" role="tabpanel" class="tab-pane active" > <form class="form-horizontal"> <div class="form-group"> <label class="col-sm-3 control-label">Name</label> <div class="col-sm-9"> <input type="text" class="form-control" value="Jonny Doo"> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Username</label> <div class="col-sm-9"> <div class="input-group"> <div class="input-group-addon">@</div> <input type="text" class="form-control" value="jonnydoo"> </div> </div> </div> <div class="form-group"> <label class="col-sm-3 control-label">Email</label> <div class="col-sm-9"> <input type="email" class="form-control" value="jonnydoo@dogmail.com"> </div> </div> <div class="form-group"> <div class="col-sm-offset-3 col-sm-9"> <button type="submit" class="btn btn-primary"> Save changes </button> </div> </div> </form> </div>
Break through the code, we set the labels to fill a quarter of the form row, while the input fills the rest. We again used the input groups to add the @
sign before the username field.
Each label has the .col-sm-3
class and the input the .col-sm-9
class. As we said, the forms respect the grid system layout, so we can apply the same classes here. We also added the .col-sm-offset-3
class to the submit button for a correct offset.
Right now, the page should look like the following screenshot. Isn't it looking nicer?

CSS turn! We must make it look prettier, so let's play with some paddings. However, before anything, add the class to .card
to the .tab-content
. Next, let's fix the borders and margins in .tab-content
by adding some padding and some negative margin, as follows:
#main .tab-content { padding: 2em; margin-top: -0.1rem; }
Then, remove the border from the tab list and change the z-index
of the tabs:
#account-tabs > li { border-bottom: 0; } #account-tabs { position: relative; z-index: 99; }
Finally, remove the margin from the save changes button using another nth
recipe, as follows:
#main .form-horizontal .form-group:last-child { margin-bottom: 0; }
Nice! Refresh the web app and see the result, like this:

With these changes, we have made the form from .tab-content
look like a card. We also added some margins and padding to correct the designs. Lastly, with the margin top and z-index, we make the selected tab blend correctly with the content.
To finalize the settings page, we must fill the right column of the web app. To do this, we will create a menu that presents some general statistics about the user.
In order to do that, we will use the Bootstrap List group component. List group is powerful in Bootstrap as it can seem similar to Bootstrap Cards, but it has more specific options for menu list generation, such as headers, disabled items, and much more.
So let's start doing this! Create the HTML markup at the #right-content
element:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides </li> <li class="list-group-item"> Captured mice </li> <li class="list-group-item"> Postmen frightened </li> <li class="list-group-item"> Always alert badge </li> </ul> </div>
It is a simple list and we just added the .list-group
class to the list, while adding the .list-group-item
class for each item in the list. For the first item, we used the .list-group-item-info
contextual color class to make it blue, according to the Bootstrap contextual colors.
Before we continue, we have to change the colors of the borders from list group to respect the same border color that we have been using:
.list-group-item { border-color: #e5e5e5; }
The result that you should see right know is like the one presented in the next screenshot. List groups is a very handy component that we can use to achieve almost the same effect that we got using Pills, but here we are using fewer CSS rules.

Labels and badges are Bootstrap components that can easily highlight some text or information. They can be used in any place, as we did in the navigation bar, on the notification item.
Just like most of Bootstrap's components, labels follow the contextual colors of Bootstrap, while badges do not have this option. To consolidate their utilization, let's add some of them to the right menu, regarding the statistics, because after all we want to know our stats!
It will be pretty easy since we have worked with this before. For the three first items, we will use labels, and for the last one, we will use a badge with an icon. Just add the highlighted code to the current .list-group
:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides <span class="label label-success">3</span> </li> <li class="list-group-item"> Captured mice <span class="label label-danger">87</span> </li> <li class="list-group-item"> Postmen frightened <span class="label label-default">2</span> </li> <li class="list-group-item"> Always alert badge <span class="badge glyphicon glyphicon-star" aria-hidden="true"> </span> </li> </ul> </div>
We must pay attention to some points here. The first is that we used the .label
class together with the contextual color class, like this: .label-*
. Here, *
is the name of the contextual class.
The second thing is that if you refresh your web page right now, you will see that Bootstrap does have a CSS for aligning all badges on the right, but it does not apply the same rule for labels. So, add the next CSS:
#right-content .list-group .label { float: right; }
The third point is that we used badges and icons in the same span. This is possible, and then we just need to adjust the CSS render:
#right-content .list-group .label { padding: 0.3rem 0.6rem; } #right-content .list-group .badge.glyphicon-star { background-color: #f0ad4e; padding: 0.4rem; padding-left: 0.5rem; }
By adding these rules, we adjusted the padding for the labels, adjusted the padding for the badge, and correctly set the yellow background for the star badge. See the result in the browser; it must look like this:

Cool! We've done another page for our web app. The stats menu looks cute. We will not cover the other page settings menus in this book, since they follow almost the same structure that we showed in this example. Try doing that as homework.
The stats column
To finalize the settings page, we must fill the right column of the web app. To do this, we will create a menu that presents some general statistics about the user.
In order to do that, we will use the Bootstrap List group component. List group is powerful in Bootstrap as it can seem similar to Bootstrap Cards, but it has more specific options for menu list generation, such as headers, disabled items, and much more.
So let's start doing this! Create the HTML markup at the #right-content
element:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides </li> <li class="list-group-item"> Captured mice </li> <li class="list-group-item"> Postmen frightened </li> <li class="list-group-item"> Always alert badge </li> </ul> </div>
It is a simple list and we just added the .list-group
class to the list, while adding the .list-group-item
class for each item in the list. For the first item, we used the .list-group-item-info
contextual color class to make it blue, according to the Bootstrap contextual colors.
Before we continue, we have to change the colors of the borders from list group to respect the same border color that we have been using:
.list-group-item { border-color: #e5e5e5; }
The result that you should see right know is like the one presented in the next screenshot. List groups is a very handy component that we can use to achieve almost the same effect that we got using Pills, but here we are using fewer CSS rules.

Labels and badges are Bootstrap components that can easily highlight some text or information. They can be used in any place, as we did in the navigation bar, on the notification item.
Just like most of Bootstrap's components, labels follow the contextual colors of Bootstrap, while badges do not have this option. To consolidate their utilization, let's add some of them to the right menu, regarding the statistics, because after all we want to know our stats!
It will be pretty easy since we have worked with this before. For the three first items, we will use labels, and for the last one, we will use a badge with an icon. Just add the highlighted code to the current .list-group
:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides <span class="label label-success">3</span> </li> <li class="list-group-item"> Captured mice <span class="label label-danger">87</span> </li> <li class="list-group-item"> Postmen frightened <span class="label label-default">2</span> </li> <li class="list-group-item"> Always alert badge <span class="badge glyphicon glyphicon-star" aria-hidden="true"> </span> </li> </ul> </div>
We must pay attention to some points here. The first is that we used the .label
class together with the contextual color class, like this: .label-*
. Here, *
is the name of the contextual class.
The second thing is that if you refresh your web page right now, you will see that Bootstrap does have a CSS for aligning all badges on the right, but it does not apply the same rule for labels. So, add the next CSS:
#right-content .list-group .label { float: right; }
The third point is that we used badges and icons in the same span. This is possible, and then we just need to adjust the CSS render:
#right-content .list-group .label { padding: 0.3rem 0.6rem; } #right-content .list-group .badge.glyphicon-star { background-color: #f0ad4e; padding: 0.4rem; padding-left: 0.5rem; }
By adding these rules, we adjusted the padding for the labels, adjusted the padding for the badge, and correctly set the yellow background for the star badge. See the result in the browser; it must look like this:

Cool! We've done another page for our web app. The stats menu looks cute. We will not cover the other page settings menus in this book, since they follow almost the same structure that we showed in this example. Try doing that as homework.
Labels and badges
Labels and badges are Bootstrap components that can easily highlight some text or information. They can be used in any place, as we did in the navigation bar, on the notification item.
Just like most of Bootstrap's components, labels follow the contextual colors of Bootstrap, while badges do not have this option. To consolidate their utilization, let's add some of them to the right menu, regarding the statistics, because after all we want to know our stats!
It will be pretty easy since we have worked with this before. For the three first items, we will use labels, and for the last one, we will use a badge with an icon. Just add the highlighted code to the current .list-group
:
<div id="right-content" class="col-md-3 hidden-sm hidden-xs"> <ul class="list-group"> <li class="list-group-item list-group-item-info"> Dog stats </li> <li class="list-group-item"> Number of day rides <span class="label label-success">3</span> </li> <li class="list-group-item"> Captured mice <span class="label label-danger">87</span> </li> <li class="list-group-item"> Postmen frightened <span class="label label-default">2</span> </li> <li class="list-group-item"> Always alert badge <span class="badge glyphicon glyphicon-star" aria-hidden="true"> </span> </li> </ul> </div>
We must pay attention to some points here. The first is that we used the .label
class together with the contextual color class, like this: .label-*
. Here, *
is the name of the contextual class.
The second thing is that if you refresh your web page right now, you will see that Bootstrap does have a CSS for aligning all badges on the right, but it does not apply the same rule for labels. So, add the next CSS:
#right-content .list-group .label { float: right; }
The third point is that we used badges and icons in the same span. This is possible, and then we just need to adjust the CSS render:
#right-content .list-group .label { padding: 0.3rem 0.6rem; } #right-content .list-group .badge.glyphicon-star { background-color: #f0ad4e; padding: 0.4rem; padding-left: 0.5rem; }
By adding these rules, we adjusted the padding for the labels, adjusted the padding for the badge, and correctly set the yellow background for the star badge. See the result in the browser; it must look like this:

Cool! We've done another page for our web app. The stats menu looks cute. We will not cover the other page settings menus in this book, since they follow almost the same structure that we showed in this example. Try doing that as homework.
In this chapter, we covered a bunch of Bootstrap components. Now you can say that you know all of the most important Bootstrap components, even the new ones in version 4. This chapter was a challenging one, since you had to learn so many details about different components, so congratulations!
First, we started working with alerts. We only used the component alert with data attributes, but in the coming chapters, we will use it as a JavaScript plugin, with more options and animations. Don't worry! This is a glimpse of future chapters.
Next, you learned about progress bars and made use of some customization, and using animations by CSS. With that, we achieved a cool result at the end and are now able to use progress bars when needed.
After that, we switched to the settings page. There, taking advantage of the same web application structure, we changed the layout. We did this by creating a menu using the pills navigator, and created a main component that used tabs.
For tabs, that was the first time we presented how to use a Bootstrap plugin by using JavaScript, but do not worry about this either. We will go deep into this subject in the next chapter.
To finish the chapter, we worked with other component, called list group. This component offers some more capabilities for creating stacked menus.
Inside the items, we studied the use of labels and badges, which are nice things that Bootstrap offers to us.
In the next chapter, we will start working with some Bootstrap JavaScript plugins. We will go back to the main web application page and play with some posts on the timeline. It will be fun. See you there!
The whole Internet would not have been the same without JavaScript, and so is Bootstrap. The JavaScript plugins from Bootstrap account for a chunk of Bootstrap's success. By having them, Bootstrap has allowed all of us to use modals, alerts, tooltips, and other plugins out of the box.
Therefore, the main focus of this chapter is to explain the main Bootstrap JavaScript plugins by using them in our web application. In the previous chapters, we used a few plugins. The purpose of this chapter is to go deep into this subject. The key points that we will cover now are:
- General usage of Bootstrap JavaScript plugins
- Data attributes
- Modals
- Tooltips
- Popover
- Affix
As I said, Bootstrap offers a lot of JavaScript plugins. They all come together when we download the framework, and all of them are ready for use when the bootstrap.js
file is loaded in HTML, although each plugin can be downloaded individually as well from the Bootstrap website.
While we were setting up our development environment, we spoke about the need to import the jQuery library. Actually, jQuery is now the only required external dependency for Bootstrap.
Check out the bower.json
file in the Bootstrap repository for further information about dependencies.
HTML5 introduced the idea of adding custom attributes to document tags in order to store custom information. Therefore, you can add an attribute to a tag with the data-*
prefix, retrieve the information in JavaScript, and not get started with some plugin in your browser. An overwhelming majority of web browsers do support the use of custom data attributes.
With that ideology, Bootstrap implemented all the plugins to be used with just data attributes. This goes towards the framework idea to increase the speed of development and prototyping. This is because you can make use of plugins without typing JavaScript code.
To control that methodology, Bootstrap implemented an API so that you can access all plugins through only data attributes. Sometimes, however, you may want to turn off access through the API. To do so, insert the following command at the beginning of your JavaScript code:
$(document).off('.data-api');
To disable the API for some specific plugins, prepend the plugin namespace. For instance, to disable the alerts API, type this:
$(document).off('.alert.data-api');
There is a set of events that Bootstrap produces for each plugin. They are triggered usually before and after the event starts. To exemplify this, let's say that we have a Bootstrap modal (you will learn about using modals in this chapter; don't worry) and we will call it to open by JavaScript:
$('#some-modal').modal();
When this happens, Bootstrap triggers the events called show.bs.modal
and shown.bs.modal
. The first one is called before the open modal call and the other is called after the action. Let's say we want to customize our modal before it is shown. To do this, we must use the first event:
$('#some-modal').on('shown.bs.modal', function(e) { // do some customization before shown });
The events can be used for all plugins. Just change the namespace (in this case, .modal
is the namespace) to achieve the result.
It's time to learn how to use modals! Modals are really present nowadays in web development and Bootstrap plugins, for that is really complete and easy to use. To use it, let's go back to our main web application page, the one containing the feeds.
First, we add the .hide
helper class to the div.alert
that we created at the #main
column. We will play with alerts later. Now, go to the #tweet
button on the navigation bar. We want to open a modal for tweets when clicking on this button. So, add the markup to the element:
<!-- modal launch button -->
<button id="tweet" class="btn btn-default pull-right visible-xs-block" data-toggle="modal" data-target="#tweet-modal">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
What we did is the call to open a modal, recognized by the #tweet-modal
ID and the data-toggle="modal"
data attribute. We could also have done that via JavaScript with this code:
$('#tweet-modal').modal();
Create the modal by adding the next HTML code. We have created all the modals at the end of our HTML code, outside of all Bootstrap elements and right before the loading of the JavaScript libraries:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> Modal content </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal"> Close </button> <button type="button" class="btn btn-primary"> Save changes </button> </div> </div> </div> </div>
Reload the web application, click on the Tweet button and see the magic happen! This code is a little more complex, so let's explain each part separately. The following screenshot shows what the first draft of our modal looks like. Now let's understand what we did.

The first tag used to initiate a modal is a <div>
with the .modal
class. Note that we also added the .fade
class to create the effect of fade in and fade out when the modal appears and disappears.
Inside the .modal
element, we created two more nested tags. The first one is .modal-dialog
, which will wrap all of the modal dialog. Inside it, we created .modal-content
, which will hold the content of the modal itself.
Next, inside .modal-content
we have the .modal-header
element. In the modal header, we can add some title information about the modal. In our example, we have also added a close button that hides the modal using a data-dismiss="modal"
data attribute.
The modal body is where you should place the main content of the modal. A cool feature inside the modal is the ability to use scaffolding.
To use the grid system inside the modal body, you do not need to create a container. Just create a .row
inside .modal-body
and start adding columns, as shown in the following example in bold:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-sm-2">Use</div> <div class="col-sm-4">the</div> <div class="col-sm-6">grid system</div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal"> Close </button> <button type="button" class="btn btn-primary"> Save changes </button> </div> </div> </div> </div>
Modal general and content
The first tag used to initiate a modal is a <div>
with the .modal
class. Note that we also added the .fade
class to create the effect of fade in and fade out when the modal appears and disappears.
Inside the .modal
element, we created two more nested tags. The first one is .modal-dialog
, which will wrap all of the modal dialog. Inside it, we created .modal-content
, which will hold the content of the modal itself.
Next, inside .modal-content
we have the .modal-header
element. In the modal header, we can add some title information about the modal. In our example, we have also added a close button that hides the modal using a data-dismiss="modal"
data attribute.
The modal body is where you should place the main content of the modal. A cool feature inside the modal is the ability to use scaffolding.
To use the grid system inside the modal body, you do not need to create a container. Just create a .row
inside .modal-body
and start adding columns, as shown in the following example in bold:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-sm-2">Use</div> <div class="col-sm-4">the</div> <div class="col-sm-6">grid system</div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal"> Close </button> <button type="button" class="btn btn-primary"> Save changes </button> </div> </div> </div> </div>
The modal header
Next, inside .modal-content
we have the .modal-header
element. In the modal header, we can add some title information about the modal. In our example, we have also added a close button that hides the modal using a data-dismiss="modal"
data attribute.
The modal body is where you should place the main content of the modal. A cool feature inside the modal is the ability to use scaffolding.
To use the grid system inside the modal body, you do not need to create a container. Just create a .row
inside .modal-body
and start adding columns, as shown in the following example in bold:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-sm-2">Use</div> <div class="col-sm-4">the</div> <div class="col-sm-6">grid system</div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal"> Close </button> <button type="button" class="btn btn-primary"> Save changes </button> </div> </div> </div> </div>
The modal body
The modal body is where you should place the main content of the modal. A cool feature inside the modal is the ability to use scaffolding.
To use the grid system inside the modal body, you do not need to create a container. Just create a .row
inside .modal-body
and start adding columns, as shown in the following example in bold:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-sm-2">Use</div> <div class="col-sm-4">the</div> <div class="col-sm-6">grid system</div> </div> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal"> Close </button> <button type="button" class="btn btn-primary"> Save changes </button> </div> </div> </div> </div>
Now that you have learned how to use a Bootstrap modal, let's customize it for our example. First, let's add some content inside our .modal-body
and edit .modal-header
and .modal-footer
a little:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title">Dog a new tweet</h4> </div> <div class="modal-body"> <textarea class="form-control" rows="4" placeholder="What you want to bark?" maxlength="140"></textarea> </div> <div class="modal-footer"> <span class="char-count pull-left" data-max="140">140</span> <button type="button" class="btn btn-default" data-dismiss="modal"> Close </button> <button type="button" class="btn btn-primary"> Tweet </button> </div> </div> </div> </div>
Here, we added a heading to .modal-header
, a textarea in .modal-body
and a <span>
element with the .char-count
class in the footer.
The goal here is to type a tweet inside the textarea
element and update the character count in the footer to show how many characters are left for the user to enter.
For styling, go to the CSS and add a style rule for .char-count
:
#tweet-modal .char-count { padding: 0.7rem 0; }
Refresh the web browser and see the result of the tweet modal, as shown in the following screenshot. Now, we need to add some JavaScript to count the number of remaining characters to tweet.

So, for the JavaScript for the character count, open (or create it if you do not have it yet) the main.js
file. Ensure that you have the document ready to create the script, by having the following code in your file:
$(document).ready(function() { // add code here });
Then, we must create a function that updates the remaining characters each time a letter is typed. Therefore, let's create an event handler for keyup
.
The keyup
event came from jQuery, which has a lot of event handlers that are triggered on different actions. There are also other events such as click
, hover
, and so on. In this case, keyup
will trigger when you release a key that you pressed.
The basic usage to create a bind event is from a selector, call the .on
function passing at the first argument of the event type (in this case, keyup
), followed by the handler (in our case, a function). Here, we have presented the JavaScript code, and the event handler is in bold so as to highlight the usage:
$(document).ready(function() {
var $charCount, maxCharCount;
$charCount = $('#tweet-modal .char-count')
maxCharCount = parseInt($charCount.data('max'), 10);
$('#tweet-modal textarea').on('keyup', function(e) {
var tweetLength = $(e.currentTarget).val().length;
$charCount.html(maxCharCount - tweetLength);
});
});
Tooltips are a very useful component for describing in detail an element or a web page. For example, when you have an image and want to describe it further, you add a tooltip. When users hover over the image, they see further information.
In our case, we will use tooltips for the buttons present in every tweet, such as Reply
, Retweet
, and Start
. This Bootstrap plugin component is pretty simple and useful in many cases. To start it, just add the markup in bold to the tweets in the middle column (<li>
in the ul#feed
element):
<ul id="feed" class="list-unstyled"> <li> <img src="imgs/doge.jpg" class="feed-avatar img-circle"> <div class="feed-post"> <h5>Doge <small>@dogeoficial - 3h</small></h5> <p>You can't hold a dog down without staying down with him!</p> </div> <div class="action-list"> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Reply"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </a> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Retweet"> <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> <span class="retweet-count">6</span> </a> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Start"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> </a> </div> </li> <li> <img src="imgs/laika.jpg" class="feed-avatar img-circle"> <div class="feed-post"> <h5>Laika <small>@spacesog - 4h</small></h5> <p>That's one small step for a dog, one giant leap for giant</p> </div> <div class="action-list"> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Reply"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </a> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Retweet"> <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> <span class="retweet-count">6</span> </a> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Star"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> </a> </div> </li> </ul>
As you can notice, by using data attributes, you just need to add three of them to make a tooltip. The first one is data-toggle
, which says the type of toggle. In our case, it is tooltip
. The data-placement
attribute is concerned with the placement of the tooltip (obviously). In this case, we set it to appear at the bottom, but we can set it to left
, top
, bottom
, right
, or auto
. Finally, we add the title
attribute, which is not a data attribute, because HTML already has the attribute title, so we can call it by this attribute.
Refresh the web app in the browser, hover the icon and you will see that… nothing happens! Unlike the other plugins, the tooltip and popover Bootstrap plugins cannot be activated simply through data attributes. They did this because of some issues, so it must be initialized through a JavaScript command. Therefore, add the following line to the main.js
file:
$(document).ready(function() { ... // to rest of the code $('[data-toggle="tooltip"]').tooltip(); });
The [data-toggle="tooltip"]
selector will retrieve all the tooltip elements and start it. You can also pass some options inside while calling the .tooltip()
start function. The next table shows some main options (to see all of them, refer to the official documentation of Bootstrap) that can be passed through JavaScript or data attributes:
Option |
Type |
Default |
Description |
---|---|---|---|
|
Boolean |
|
This adds fade in and fade out animation to a tooltip. |
|
String or function |
|
This is the placement position of the tooltip. The options are the same as those mentioned for the usage with data attributes ( |
|
String |
|
If you provide a selector, the tooltip will be delegated to the specified target. |
|
String |
|
The trigger to the tooltip will be shown. The options are |
The tooltip plugin also has some useful methods for doing things such as showing all tooltips. You can call them using the .tooltip()
method. As mentioned, if you want to show all tooltips, just use $('.tooltip-selector').tooltip('show')
. The other options are hide
, toggle
, and destroy
.
In some cases, you may want to show more information that does not fit in a simple tooltip component. For that, Bootstrap has created popovers, which are components that create small overlays of content to show detailed secondary information.
The popover plugin is an extension of the tooltip plugin, so if you are using separate plugins, you must load both to make it work. Also, just like tooltips, popovers cannot be activated simply through data attributes. You must call them via JavaScript to make them work.
Let's use a popover in our web app example, on the right-hand-side column, the one identified by div#who-follow
. We will add the popover to the Follow buttons, and for that, we need to do two things. The first one is to change the <button>
element to an <a>
element and then add the popover markup.
First, about the <buttons>
inside the div#who-follow
element. Change them to <a>
elements in the HTML. Also add the role="button"
and tabindex="-1"
attributes to the links to fix the issue of cross-browser compatibility:
<div id="who-follow" class="card"> <div class="card-header"> Who to follow </div> <div class="card-block"> <ul class="list-unstyled"> <li> <img src="imgs/cat.jpg" class="img-rounded"> <div class="info"> <strong>Crazy cats</strong> <a href="#" role="button" tabindex="-1" class="btn btn-default"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Follow </a> </div> </li> <li> <img src="imgs/ration.jpg" class="img-rounded"> <div class="info"> <strong>Free ration alert</strong> <a href="#" role="button" tabindex="-1" class="btn btn-default"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Follow </a> </div> </li> </ul> </div>
The code in bold refers to the changes from button to link. Now, we must add the popover markup. It is pretty simple and follows most of the data attributes presented in the tooltip plugin:
<div id="who-follow" class="card"> <div class="card-header"> Who to follow </div> <div class="card-block"> <ul class="list-unstyled"> <li> <img src="imgs/cat.jpg" class="img-rounded"> <div class="info"> <strong>Crazy cats</strong> <a href="#" role="button" tabindex="-1" class="btn btn-default" data-toggle="popover" data-trigger="focus" title="You may want to follow"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Follow </a> </div> </li> <li> <img src="imgs/ration.jpg" class="img-rounded"> <div class="info"> <strong>Free ration alert</strong> <a href="#" role="button" tabindex="-1" class="btn btn-default" data-toggle="popover" data-trigger="focus" title="You may want to follow"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Follow </a> </div> </li> </ul> </div>
Just like the popover, add the following line to the JavaScript code to make popovers appear:
$(document).ready(function() { … // the rest of the JavaScript $('[data-toggle="popover"]').popover(); });
Refresh the web browser, click on the Follow button and see the popover appearing to the right of the button. Now we will make some changes using the options to customize it. First of all, let's create the content that will appear inside the popover and change its placement in JavaScript:
$(document).ready(function() { … // rest of the JavaScript var popoverContentTemplate = '' + '<img src="imgs/breed.jpg" class="img-rounded">' + '<div class="info">' + '<strong>Dog Breeds</strong>' + '<a href="#" class="btn btn-default">' + '<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>' + 'Follow' + '</a>' + '</div>'; $('[data-toggle="popover"]').popover({ placement: 'bottom', html: true, content: function() { return popoverContentTemplate; } }); });
In the preceding code, we changed the placement of the popover to bottom
and set the content that will appear inside the popover to be HTML with the html: true
option. The content was provided by a function that simply returned the popoverContentTemplate
variable.
For instance, we could have used the template in very different ways that are more optimized, but we did this to show the method of adding HTML content onto a popover via JavaScript and using a function for that. We could have called and used some options of the target clicked button inside the function by accessing the current scope in the this
variable.
Popovers and tooltips provide some nice events. As was said before, Bootstrap triggers some events when plugin elements appear, hide, and are inserted. To play with these, let's use the show.bs.popover
event, which is an event that is fired immediately when the popover
is show
. In this case, we want to create an action before the popover
is show
. We want to change the text of the Follow button that we clicked on to Following, while changing the icon next to the text from a plus sign to an okay sign. We can take advantage of the show.bs.popover
Bootstrap event to make these changes. In the JavaScript file, insert the following delegation to the popovers:
$(document).ready(function() { … // the rest of the JavaScript code $('[data-toggle="popover"]').on('show.bs.popover', function() { var $icon = $(this).find('span.glyphicon'); $icon.removeClass('glyphicon-plus').addClass('glyphicon-ok'); $(this).append('ing'); }); });
The scope of this event is the element of data-toggle
, which is the Follow button. We query the icon inside the button, and change it from glyphicon-plus
to glyphicon-ok
. Finally, we append the infinitive ing
to Follow, which means that we are now following Crazy cats or Free ration alert suggestions:
To add a cherry to the pie, let's change the color of the icon from blue to green when the okay icon appears:
div#who-follow li .info .glyphicon-ok { color: #5cb85c; }
Refresh the web browser and click on the Follow button. You should see something similar to this screenshot:

There are many other places where the Bootstrap events can be used. This is a nice example where we want to change the element that we are interacting with. Keep in mind to change it whenever you need some related interaction.
Popover events
Popovers and tooltips provide some nice events. As was said before, Bootstrap triggers some events when plugin elements appear, hide, and are inserted. To play with these, let's use the show.bs.popover
event, which is an event that is fired immediately when the popover
is show
. In this case, we want to create an action before the popover
is show
. We want to change the text of the Follow button that we clicked on to Following, while changing the icon next to the text from a plus sign to an okay sign. We can take advantage of the show.bs.popover
Bootstrap event to make these changes. In the JavaScript file, insert the following delegation to the popovers:
$(document).ready(function() { … // the rest of the JavaScript code $('[data-toggle="popover"]').on('show.bs.popover', function() { var $icon = $(this).find('span.glyphicon'); $icon.removeClass('glyphicon-plus').addClass('glyphicon-ok'); $(this).append('ing'); }); });
The scope of this event is the element of data-toggle
, which is the Follow button. We query the icon inside the button, and change it from glyphicon-plus
to glyphicon-ok
. Finally, we append the infinitive ing
to Follow, which means that we are now following Crazy cats or Free ration alert suggestions:
To add a cherry to the pie, let's change the color of the icon from blue to green when the okay icon appears:
div#who-follow li .info .glyphicon-ok { color: #5cb85c; }
Refresh the web browser and click on the Follow button. You should see something similar to this screenshot:

There are many other places where the Bootstrap events can be used. This is a nice example where we want to change the element that we are interacting with. Keep in mind to change it whenever you need some related interaction.
The affix plugin is present only in version 3 of Bootstrap (it was removed in version 4), and it aims to toggle the position of an element between fixed and relative, emulating the effect of position: sticky
, which is not present in all browsers.
We will apply the sticky effect the left #profile
element although we do not have enough elements to make a scroll on our web page. Therefore, to make it simple, replicate the <li>
in ul#feed
to increase the number of items in the list. Do this three times or more to make a scroll in your web browser.
In div#profile
, add the markup related to affix:
<div id="profile" class="col-md-3 hidden-sm hidden-xs" data-spy="affix" data-offset-top="0">
…
// rest of the profile HTML
</div>
Refresh the web browser. You will see that the affix is not working yet. Since we are making the left column with a fixed position with the affix plugin, it is removing the entire column from the grid, making the columns glitch from left to right.
So, we need a workaround for that. We must create some piece of JavaScript code using the events triggered for the plugin.
Let's use the
affix.bs.affix
event, which is an event fired just before the affixing of the element:
$(document).ready(function() { … // rest of the JavaScript code $('#profile').on('affix.bs.affix', function() { $(this).width($(this).width() - 1); $('#main').addClass('col-md-offset-3'); }).on('affix-top.bs.affix', function() { $(this).css('width', ''); $('#main').removeClass('col-md-offset-3'); }); });
Thus, we have played with some tricks in the preceding JavaScript code.
In the first delegated event, .on('affix.bs.affix', handler)
,when the element switches to position: fixed
, we keep the width of the left column. It would change the width because the .col-md-3
class does not have a fixed width; it uses a percentage width.
We also added the offset to the middle column, corresponding to the detached left column, the .col-md-offset-3
class.
The affix-top.bs.affix
event does the opposite action, firing when the element returns to the original top position and removing the custom width and the offset class in the middle column.
To remove the fixed width and return to the .col-md-3
percentage width, just add the $(this).css('width', '')
line. Also remove the .col-md-offset-3
class from the #main
content.
Refresh the web browser, scroll the page, and see the result, exemplified in the next screenshot. Note that the profile is fixed on the left while the rest of the content scrolls with the page:

To finish the web application example, we just need to create another modal when we click on the Messages link at the navigation bar.
To create it, we will use the same methodology used to create the modal for the Tweet button. So, add the data attributes' markups to the Messages link in .nav.navbar-nav
, as follows:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#" role="button" data-toggle="modal" data-target="#messages-modal">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
<li class="visible-xs-inline">
<a href="#">
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
Profile
</a>
</li>
<li class="visible-xs-inline">
<a href="#">
<span class="glyphicon glyphicon-off" aria-hidden="true"></span>
Logout
</a>
</li>
</ul>
The highlighted code says that this link plays the role
button, toggling a modal identified by the #messages-modal
ID. Create the base of this modal at the end of the HTML code, just after #tweet-modal
:
<div id="messages-modal" class="modal fade" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title">Dog messages</h4> <button type="button" class="btn btn-primary btn-message">New message</button> </div> <div class="modal-body"> </div> </div> </div> </div>
We made some changes in comparison to #tweet-modal
. Firstly, we removed .modal-footer
from this modal, since we do not need these options in the modal. Like almost the entire framework, Bootstrap allows us to include or exclude elements as per our wishes.
Secondly, we created a new button, New message, in the header, identified by the .btn-message
class. To present the button correctly, create the following CSS style:
#messages-modal .btn-message { position: absolute; right: 3em; top: 0.75em; }
Now let's create the content inside the modal. We will add a list of messages in the modal. Check out the HTML with the content added:
<div class="modal fade" id="messages-modal" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> <h4 class="modal-title">Dog messages</h4> <button type="button" class="btn btn-primary btn-message">New message</button> </div> <div class="modal-body"> <ul class="list-unstyled"> <li> <a href="#"> <img src="imgs/laika.jpg" class="img-circle"> <div class="msg-content"> <h5>Laika <small>@spacesog</small></h5> <p>Hey Jonny, how is down there?</p> </div> </a> </li> <li> <a href="#"> <img src="imgs/doge.jpg" class="img-circle"> <div class="msg-content"> <h5>Doge <small>@dogeoficial </small></h5> <p>Wow! How did I turned in to a meme?</p> </div> </a> </li> <li> <a href="#"> <img src="imgs/cat.jpg" class="img-circle"> <div class="msg-content"> <h5>Cat <small>@crazycat</small></h5> <p>You will never catch me!</p> </div> </a> </li> <li> <a href="#"> <img src="imgs/laika.jpg" class="img-circle"> <div class="msg-content"> <h5>Laika <small>@spacesog</small></h5> <p>I think I saw you in Jupiter! Have you been there recently?</p> </div> </a> </li> </ul> </div> </div> </div> </div>
To finish our job, we just create some style in the CSS in order to display our list correctly:
#messages-modal .modal-body { max-height: 32rem; overflow: auto; } #messages-modal li { padding: 0.75rem; border-bottom: 0.1rem solid #E6E6E6; } #messages-modal li:hover { background-color: #E6E6E6; } #messages-modal li a:hover { text-decoration: none; } #messages-modal li img { max-width: 15%; } #messages-modal .msg-content { display: inline-block; color: #000; } #messages-modal .msg-content h5 { font-size: 1em; font-weight: bold; }
In this CSS, we simply set a maximum height for the modal body, while adding a scroll overflow. For the list and the link, we changed the style for hover and adjusted the font weight, size, and color for display.
Refresh the web browser, click on the Messages link in the navigation bar and see your nice modal, as follows:

In this chapter, we finished our web application example. The main objective here was to learn about the Bootstrap plugins that we had not described before.
First, you learned about data attributes and how to use them with Bootstrap. After that, we saw both the possible ways to call plugins: via pure JavaScript or just through data attributes APIs.
We started and finished plugins with modals. Modals are one of the main plugins in Bootstrap because they are very versatile and customizable. Thus, they are fit for multiple contexts where you need some interaction with the user but do not want to move to another page.
In the middle of the chapter, we talked about two plugins that are closely related. They are the tooltip and the popover. Both came from the same initial plugin but with different contexts. Tooltips are used for auxiliary content, and popovers are something midway between a modal and a tooltip, so they can display more content compared to tooltips, but not too much intrusive like modals.
Creating a web application that is Twitter-like is an important kind of knowledge, since this can be replicated to different sources. Web applications have revolutionized the Web in different ways, and Bootstrap has taken the lead by helping us create faster and more beautiful web pages.
In the next chapter, we will step into an even more challenging example—we will build a dashboard web application from scratch! Just like the web application presented in this chapter, web dashboards are very popular across the Internet, and building one will place us at the same stratum as some of the best web developers. Ready for the advanced level?
Alright, there is no more time to spend on testing our skills. Now it's time to truly test ourselves with a big challenge: creating an admin dashboard using Bootstrap. Now Bootstrap can help us, but we must know how to handle the majority of the framework to deliver professional work.
We need a plan to build this dashboard from scratch to its final form. Therefore, we will follow a designer template and recreate it from an image to a web page. Following this concept, you will learn about:
- The fluid container
- The flexbox layout
- Bootstrap custom stacked navigation
- The collapse plugin
- Bootstrap and advanced CSS
- External plugin integration
- Single-page application loading
This is the final example of the book. Let's face it and nail the Bootstrap framework. I know you are thoroughly able to defeat this final boss!
As I mentioned, this is a professional job and it deserves a professional treatment. Now we will have a design guideline to follow. Up next is a screenshot of the dashboard that we have to reproduce by code:

As you can see, the dashboard is composed of a navigation header containing some information, a search bar, and notifications. On the left-hand side is a menu with the sections of the web application. In the center is a set of charts about the page status. It looks good in the screenshot and will look even better in the browser!
The page scaffolding consists of the following:
First of all, before you create any element, create a new file using the same structure that we pointed out for starting every example in the book (refer to the Bootstrap required tags section in Chapter 1, Getting Started, for more information). Create a file named dashboard.html
and apply the default starter HTML to the file. Now we are ready to go!
You may be bored of doing navigation bars; however, because of the acquired experience, we will do this one very quickly, taking advantage of the code written in previous examples.
Create a <nav>
element, and inside it, create a .container-fluid
and a .row
:
<nav class="navbar navbar-fixed-top"> <div class="container-fluid"> <div class="row"> </div> </div> </nav>
This .row
element will have two columns, just as we mentioned that will be done for the main container. On the first one, let's create the dashboard title and a refresh button, as follows:
<nav class="navbar navbar-fixed-top"> <div class="container-fluid"> <div class="row"> <div class="col-sm-3 top-left-menu"> <div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <h1>dashboard</h1> </a> </div> <a href="#" data-toggle="tooltip" data-placement="bottom" data-delay="500" title="Refresh data" class="header-refresh pull-right"> <span class="glyphicon glyphicon-repeat" aria-hidden="true"></span> </a> </div> </div> </div> </nav>
Note that for the refresh button, we have used .glyphicon
and added a tooltip. Do not forget to activate the tooltip in the main.js
file that you have loaded:
$(document).ready(function() { $('[data-toggle="tooltip"]').tooltip(); });
In the tooltip, we added a delay to it show up with the data-delay="500"
attribute. We mentioned this as an option for tooltip, but haven't made use of it so far. This will just delay the appearance of the tooltip for 500 milliseconds, while hovering the refresh link.
Inside .nav-header
, add .navbar-toggle
, which will be displayed for small screens and collapse the menu:
<nav class="navbar navbar-fixed-top"> <div class="container-fluid"> <div class="row"> <div class="col-sm-3 top-left-menu"> <div class="navbar-header"> <a class="navbar-brand" href="webapp.html"> <h1>dashboard</h1> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> </div> <a href="#" data-toggle="tooltip" data-placement="bottom" data-delay="500" title="Refresh data" class="header-refresh pull-right"> <span class="glyphicon glyphicon-repeat" aria-hidden="true"></span> </a> </div> </div> </div> </nav>
So far, we have no secrets. We have just replicated components that we used before. Following our pipeline, we should create some CSS rules to style our page, although first let's create some common CSS style. At the beginning of base.css
, which is loaded in our HTML, we add the style:
.transition, .transition:hover, .transition:focus { -webkit-transition: all 150ms ease-in-out; -moz-transition: all 150ms ease-in-out; -ms-transition: all 150ms ease-in-out; -o-transition: all 150ms ease-in-out; transition: all 150ms ease-in-out; } html, body { position: relative; height: 100%; background-color: #e5e9ec; }
First, we created a common .transition
class to be used in multiples cases (we will use it in the chapter). Transitions were introduced in CSS3 and they allow us to create transition effects. In this case, it's an effect of ease-in-out
for any element that has this class.
Also, for html
and body
, we changed the background and set the position and height to fill the entire screen.
Next, we must add the CSS for the navigation header:
nav.navbar-fixed-top { background-color: #FFF; border: none; } nav .top-left-menu { background-color: #252830; display: -webkit-flex; display: flex; align-items: center; } .navbar-brand { height: auto; } .navbar-brand h1 { margin: 0; font-size: 1.5em; font-weight: 300; color: #FFF; } nav .header-refresh { margin-left: auto; color: #FFF; }
Here, we changed the color of the elements. But the most important thing here is the usage of the flexbox
rules (do you remember flexbox, which we discussed in Chapter 5, Making It Fancy, in the Understanding flexbox section?). Remember that Bootstrap 4 will support flex display, so it is nice to keep using it, since it should be the standard in the near future for every browser.
The result of this part must look like what is shown in the following screenshot:

Following our design, we have to create a search form. So, just after the closure of .top-left-menu
, add the form code, such as the portion in bold:
<nav class="navbar navbar-fixed-top"> <div class="container-fluid"> <div class="row"> <div class="col-sm-3 top-left-menu"> ... </div> <form id="search" role="search" class="hidden-xs col-sm-3"> <div class="input-group"> <span class="glyphicon glyphicon-search" aria-hidden="true"></span> <input type="text" class="form-control transition" placeholder="Search..."> </div> </form> </div> </div> </nav>
As usual, it's CSS time:
nav form#search { padding: 0.9em; } nav form#search .input-group { display: -webkit-flex; display: flex; align-items: center; } nav form#search .input-group .form-control { border-radius: 0.25em; border: none; width: 70%; padding-left: 1.9em; background-color: #F3F3F3; box-shadow: none; } nav form#search .input-group .form-control:focus { width: 100%; box-shadow: none; } nav form#search .glyphicon-search { z-index: 99; left: 1.7em; }
In this CSS, we have again used the display: flex
property. In addition to this, we created a pseudo-class rule for .form-control
. The :focus
, which is activated whenever the input has focus, in other words, is receiving some text. This :focus
rule will change the width of the input when you focus the input, which happens when you click on it.
Refresh the web page and click on the input on the search form. Note that we applied the .transition
class in this element, so when we focus it, the change of width is smoothed in a transition. The result should look like this:

To finish the navigation bar, we have to create the right-hand-side content of the navigation bar, which we call #nav-menu
. This menu will hold the notification list, placed as a button dropdown.
After <form>
, place the presented HTML:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> </ul> </div>
Inside this <ul>
tag, we will place the notifications. Right now, we just have this option, but with this list, we can add multiple items in the navigation bar. So, add the following code for the item:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> <li> <div id="btn-notifications" class="btn-group"> <span class="badge">3</span> <button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Notifications </button> </div> </li> </ul> </div>
Explaining this item, we can say that it is a button for the notification. There is a wrapper element named #btn-notifications
. Inside it is a .badge
to verbalize the number of new notifications, and a button.btn
that must seem like a link, so we applied the .btn-link
class to it. The button also contains the tags needed for a Bootstrap drop-down button, such as the .dropdown-toggle
class and the data-toggle="dropdown"
data property.
Therefore, every
button.dropdown-toggle
button needs a ul.dropdown-menu
. Just after <button>
, create the list:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> <li> <div id="btn-notifications" class="btn-group"> <span class="badge">3</span> <button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Notifications </button> <ul id="notification-list" class="dropdown-menu pull-right"> <li> <a href="#"> <span class="badge"></span> <img src="imgs/laika.jpg" class="img-circle"> <div class="notification-message"> <strong>Laika</strong> <p>Hey! How are you?</p> <em class="since">2h ago</em> </div> </a> </li> <li> <a href="#"> <span class="badge"></span> <img src="imgs/cat.jpg" class="img-circle"> <div class="notification-message"> <strong>Devil cat</strong> <p>I will never forgive you...</p> <em class="since">6h ago</em> </div> </a> </li> <li> <a href="#"> <span class="badge"></span> <img src="imgs/doge.jpg" class="img-circle"> <div class="notification-message"> <strong>Doge</strong> <p>What are you doing? So scare. It's alright now.</p> <em class="since">yesterday</em> </div> </a> </li> </ul> </div> </li> </ul> </div>
The new list element is pointed out in bold. Even though the content seems long, it is just a repetition of three items with different contents inside our notification list.
Refresh the page, open the dropdown, and you will feel an uncontrollable desire to add some CSS and stop the dropdown from being ugly anymore:
/*nav menu*/ nav #nav-menu { padding: 0.4em; padding-right: 1em; } /*nav menu and notifications*/ #nav-menu #btn-notifications > .badge { color: #FFF; background-color: #f35958; font-size: 0.7em; padding: 0.3rem 0.55rem 0.3rem 0.5rem; position: absolute; right: -0.4rem; top: 1rem; z-index: 99; } #btn-notifications .btn-link { padding-top: 1.5rem; color: #252830; font-weight: 500; } #btn-notifications .btn-link:hover { text-decoration: none; }
Great! This will make the button and notification badge appear more beautiful. Then it's time for #notification-list
:
#notification-list { max-height: 20em; overflow: auto; } #notification-list a { display: -webkit-flex; display: flex; opacity: 0.7; margin: 1.5rem; border-radius: 0.5rem; padding: 0.5rem 1.3rem; background-color: #EFEFEF; position: relative; } #notification-list a:hover { color: #262626; text-decoration: none; opacity: 1; } #notification-list img { display: inline-block; height: 35px; width: 35px; margin-right: 1em; margin-top: 1em; } #notification-list .notification-message { display: inline-block; white-space: normal; min-width: 25rem; } #notification-list .badge:empty { display: inline-block; position: absolute; right: 0.5rem; top: 0.5rem; background-color: #f35958; height: 1.4rem; } #notification-list em.since { font-size: 0.7em; color: #646C82; }
For the notification, we did just some common rules, such as spacing, color, and so on. The only different thing is, again, the use of flexbox
to align the content. See this screenshot for the final result of the navigation bar:

In the navigation bar, the last present component is a picture that, when you click on it, opens a user menu, just like what we did in the example of the web application. With no further delay, place the next HTML just after the <ul>
of #nav-menu
:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> … </ul> <div id="nav-profile" class="btn-group pull-right"> <button type="button" class="btn btn-link dropdown-toggle thumbnail" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <img src="imgs/jon.png" class="img-circle"> </button> <ul class="dropdown-menu"> <li><a href="#">Profile</a></li> <li><a href="settings.html">Setting</a></li> <li role="separator" class="divider"></li> <li><a href="#">Logout</a></li> </ul> </div> </div>
So, it is another button dropdown. The CSS for this HTML is as follows:
#nav-profile { margin: 0.5em; margin-left: 1em; } #nav-profile button.thumbnail { margin: 0; padding: 0; border: 0; } #nav-profile img { max-height: 2.3em; }
We are done! Refresh the web browser and see the result, which should be like what is shown in this screenshot:

The navigation search
Following our design, we have to create a search form. So, just after the closure of .top-left-menu
, add the form code, such as the portion in bold:
<nav class="navbar navbar-fixed-top"> <div class="container-fluid"> <div class="row"> <div class="col-sm-3 top-left-menu"> ... </div> <form id="search" role="search" class="hidden-xs col-sm-3"> <div class="input-group"> <span class="glyphicon glyphicon-search" aria-hidden="true"></span> <input type="text" class="form-control transition" placeholder="Search..."> </div> </form> </div> </div> </nav>
As usual, it's CSS time:
nav form#search { padding: 0.9em; } nav form#search .input-group { display: -webkit-flex; display: flex; align-items: center; } nav form#search .input-group .form-control { border-radius: 0.25em; border: none; width: 70%; padding-left: 1.9em; background-color: #F3F3F3; box-shadow: none; } nav form#search .input-group .form-control:focus { width: 100%; box-shadow: none; } nav form#search .glyphicon-search { z-index: 99; left: 1.7em; }
In this CSS, we have again used the display: flex
property. In addition to this, we created a pseudo-class rule for .form-control
. The :focus
, which is activated whenever the input has focus, in other words, is receiving some text. This :focus
rule will change the width of the input when you focus the input, which happens when you click on it.
Refresh the web page and click on the input on the search form. Note that we applied the .transition
class in this element, so when we focus it, the change of width is smoothed in a transition. The result should look like this:

To finish the navigation bar, we have to create the right-hand-side content of the navigation bar, which we call #nav-menu
. This menu will hold the notification list, placed as a button dropdown.
After <form>
, place the presented HTML:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> </ul> </div>
Inside this <ul>
tag, we will place the notifications. Right now, we just have this option, but with this list, we can add multiple items in the navigation bar. So, add the following code for the item:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> <li> <div id="btn-notifications" class="btn-group"> <span class="badge">3</span> <button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Notifications </button> </div> </li> </ul> </div>
Explaining this item, we can say that it is a button for the notification. There is a wrapper element named #btn-notifications
. Inside it is a .badge
to verbalize the number of new notifications, and a button.btn
that must seem like a link, so we applied the .btn-link
class to it. The button also contains the tags needed for a Bootstrap drop-down button, such as the .dropdown-toggle
class and the data-toggle="dropdown"
data property.
Therefore, every
button.dropdown-toggle
button needs a ul.dropdown-menu
. Just after <button>
, create the list:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> <li> <div id="btn-notifications" class="btn-group"> <span class="badge">3</span> <button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Notifications </button> <ul id="notification-list" class="dropdown-menu pull-right"> <li> <a href="#"> <span class="badge"></span> <img src="imgs/laika.jpg" class="img-circle"> <div class="notification-message"> <strong>Laika</strong> <p>Hey! How are you?</p> <em class="since">2h ago</em> </div> </a> </li> <li> <a href="#"> <span class="badge"></span> <img src="imgs/cat.jpg" class="img-circle"> <div class="notification-message"> <strong>Devil cat</strong> <p>I will never forgive you...</p> <em class="since">6h ago</em> </div> </a> </li> <li> <a href="#"> <span class="badge"></span> <img src="imgs/doge.jpg" class="img-circle"> <div class="notification-message"> <strong>Doge</strong> <p>What are you doing? So scare. It's alright now.</p> <em class="since">yesterday</em> </div> </a> </li> </ul> </div> </li> </ul> </div>
The new list element is pointed out in bold. Even though the content seems long, it is just a repetition of three items with different contents inside our notification list.
Refresh the page, open the dropdown, and you will feel an uncontrollable desire to add some CSS and stop the dropdown from being ugly anymore:
/*nav menu*/ nav #nav-menu { padding: 0.4em; padding-right: 1em; } /*nav menu and notifications*/ #nav-menu #btn-notifications > .badge { color: #FFF; background-color: #f35958; font-size: 0.7em; padding: 0.3rem 0.55rem 0.3rem 0.5rem; position: absolute; right: -0.4rem; top: 1rem; z-index: 99; } #btn-notifications .btn-link { padding-top: 1.5rem; color: #252830; font-weight: 500; } #btn-notifications .btn-link:hover { text-decoration: none; }
Great! This will make the button and notification badge appear more beautiful. Then it's time for #notification-list
:
#notification-list { max-height: 20em; overflow: auto; } #notification-list a { display: -webkit-flex; display: flex; opacity: 0.7; margin: 1.5rem; border-radius: 0.5rem; padding: 0.5rem 1.3rem; background-color: #EFEFEF; position: relative; } #notification-list a:hover { color: #262626; text-decoration: none; opacity: 1; } #notification-list img { display: inline-block; height: 35px; width: 35px; margin-right: 1em; margin-top: 1em; } #notification-list .notification-message { display: inline-block; white-space: normal; min-width: 25rem; } #notification-list .badge:empty { display: inline-block; position: absolute; right: 0.5rem; top: 0.5rem; background-color: #f35958; height: 1.4rem; } #notification-list em.since { font-size: 0.7em; color: #646C82; }
For the notification, we did just some common rules, such as spacing, color, and so on. The only different thing is, again, the use of flexbox
to align the content. See this screenshot for the final result of the navigation bar:

In the navigation bar, the last present component is a picture that, when you click on it, opens a user menu, just like what we did in the example of the web application. With no further delay, place the next HTML just after the <ul>
of #nav-menu
:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> … </ul> <div id="nav-profile" class="btn-group pull-right"> <button type="button" class="btn btn-link dropdown-toggle thumbnail" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <img src="imgs/jon.png" class="img-circle"> </button> <ul class="dropdown-menu"> <li><a href="#">Profile</a></li> <li><a href="settings.html">Setting</a></li> <li role="separator" class="divider"></li> <li><a href="#">Logout</a></li> </ul> </div> </div>
So, it is another button dropdown. The CSS for this HTML is as follows:
#nav-profile { margin: 0.5em; margin-left: 1em; } #nav-profile button.thumbnail { margin: 0; padding: 0; border: 0; } #nav-profile img { max-height: 2.3em; }
We are done! Refresh the web browser and see the result, which should be like what is shown in this screenshot:

The menu needs navigation
To finish the navigation bar, we have to create the right-hand-side content of the navigation bar, which we call #nav-menu
. This menu will hold the notification list, placed as a button dropdown.
After <form>
, place the presented HTML:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> </ul> </div>
Inside this <ul>
tag, we will place the notifications. Right now, we just have this option, but with this list, we can add multiple items in the navigation bar. So, add the following code for the item:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> <li> <div id="btn-notifications" class="btn-group"> <span class="badge">3</span> <button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Notifications </button> </div> </li> </ul> </div>
Explaining this item, we can say that it is a button for the notification. There is a wrapper element named #btn-notifications
. Inside it is a .badge
to verbalize the number of new notifications, and a button.btn
that must seem like a link, so we applied the .btn-link
class to it. The button also contains the tags needed for a Bootstrap drop-down button, such as the .dropdown-toggle
class and the data-toggle="dropdown"
data property.
Therefore, every
button.dropdown-toggle
button needs a ul.dropdown-menu
. Just after <button>
, create the list:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> <li> <div id="btn-notifications" class="btn-group"> <span class="badge">3</span> <button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Notifications </button> <ul id="notification-list" class="dropdown-menu pull-right"> <li> <a href="#"> <span class="badge"></span> <img src="imgs/laika.jpg" class="img-circle"> <div class="notification-message"> <strong>Laika</strong> <p>Hey! How are you?</p> <em class="since">2h ago</em> </div> </a> </li> <li> <a href="#"> <span class="badge"></span> <img src="imgs/cat.jpg" class="img-circle"> <div class="notification-message"> <strong>Devil cat</strong> <p>I will never forgive you...</p> <em class="since">6h ago</em> </div> </a> </li> <li> <a href="#"> <span class="badge"></span> <img src="imgs/doge.jpg" class="img-circle"> <div class="notification-message"> <strong>Doge</strong> <p>What are you doing? So scare. It's alright now.</p> <em class="since">yesterday</em> </div> </a> </li> </ul> </div> </li> </ul> </div>
The new list element is pointed out in bold. Even though the content seems long, it is just a repetition of three items with different contents inside our notification list.
Refresh the page, open the dropdown, and you will feel an uncontrollable desire to add some CSS and stop the dropdown from being ugly anymore:
/*nav menu*/ nav #nav-menu { padding: 0.4em; padding-right: 1em; } /*nav menu and notifications*/ #nav-menu #btn-notifications > .badge { color: #FFF; background-color: #f35958; font-size: 0.7em; padding: 0.3rem 0.55rem 0.3rem 0.5rem; position: absolute; right: -0.4rem; top: 1rem; z-index: 99; } #btn-notifications .btn-link { padding-top: 1.5rem; color: #252830; font-weight: 500; } #btn-notifications .btn-link:hover { text-decoration: none; }
Great! This will make the button and notification badge appear more beautiful. Then it's time for #notification-list
:
#notification-list { max-height: 20em; overflow: auto; } #notification-list a { display: -webkit-flex; display: flex; opacity: 0.7; margin: 1.5rem; border-radius: 0.5rem; padding: 0.5rem 1.3rem; background-color: #EFEFEF; position: relative; } #notification-list a:hover { color: #262626; text-decoration: none; opacity: 1; } #notification-list img { display: inline-block; height: 35px; width: 35px; margin-right: 1em; margin-top: 1em; } #notification-list .notification-message { display: inline-block; white-space: normal; min-width: 25rem; } #notification-list .badge:empty { display: inline-block; position: absolute; right: 0.5rem; top: 0.5rem; background-color: #f35958; height: 1.4rem; } #notification-list em.since { font-size: 0.7em; color: #646C82; }
For the notification, we did just some common rules, such as spacing, color, and so on. The only different thing is, again, the use of flexbox
to align the content. See this screenshot for the final result of the navigation bar:

In the navigation bar, the last present component is a picture that, when you click on it, opens a user menu, just like what we did in the example of the web application. With no further delay, place the next HTML just after the <ul>
of #nav-menu
:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> … </ul> <div id="nav-profile" class="btn-group pull-right"> <button type="button" class="btn btn-link dropdown-toggle thumbnail" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <img src="imgs/jon.png" class="img-circle"> </button> <ul class="dropdown-menu"> <li><a href="#">Profile</a></li> <li><a href="settings.html">Setting</a></li> <li role="separator" class="divider"></li> <li><a href="#">Logout</a></li> </ul> </div> </div>
So, it is another button dropdown. The CSS for this HTML is as follows:
#nav-profile { margin: 0.5em; margin-left: 1em; } #nav-profile button.thumbnail { margin: 0; padding: 0; border: 0; } #nav-profile img { max-height: 2.3em; }
We are done! Refresh the web browser and see the result, which should be like what is shown in this screenshot:

Checking the profile
In the navigation bar, the last present component is a picture that, when you click on it, opens a user menu, just like what we did in the example of the web application. With no further delay, place the next HTML just after the <ul>
of #nav-menu
:
<div id="nav-menu" class="collapse navbar-collapse pull-right"> <ul class="nav navbar-nav"> … </ul> <div id="nav-profile" class="btn-group pull-right"> <button type="button" class="btn btn-link dropdown-toggle thumbnail" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <img src="imgs/jon.png" class="img-circle"> </button> <ul class="dropdown-menu"> <li><a href="#">Profile</a></li> <li><a href="settings.html">Setting</a></li> <li role="separator" class="divider"></li> <li><a href="#">Logout</a></li> </ul> </div> </div>
So, it is another button dropdown. The CSS for this HTML is as follows:
#nav-profile { margin: 0.5em; margin-left: 1em; } #nav-profile button.thumbnail { margin: 0; padding: 0; border: 0; } #nav-profile img { max-height: 2.3em; }
We are done! Refresh the web browser and see the result, which should be like what is shown in this screenshot:

After the navigation bar, we must fill the main content using a fluid layout. For that, we create a .container-fluid
, just as we did in the <nav>
. Inside the container, we create a single .row
and two columns with spacing three and nine, respectively:
<div class="container-fluid"> <div class="row"> <div id="side-menu" class="col-md-3 hidden-xs"> </div> <div id="main" class="col-md-9"> </div> </div> </div>
It is a common grid, containing one row. In the row, the first column, #side-menu
, is shown from small viewports up to larger ones, while the #main
column fills 9 out of 12 grids for medium resolutions.
However, we must not forget that #side-menu
is actually an affix component. So, let's add the data properties to make it stitch to the top of the page, as we did in the web application example when you were learning this plugin:
<div class="container-fluid"> <div class="row"> <div id="side-menu" class="col-md-3 hidden-xs" data-spy="affix" data-offset-top="0"> </div> <div id="main" class="col-sm-offset-3 col-md-9"> </div> </div> </div>
Note that because of the addition of the affix, we must set an offset in the #main
div with the .col-sm-offset-3
class.
Let's fill #side-menu
with content. At first, we have to create the profile block, which contains the user data. Place the following HTML inside the referred element:
<div id="side-menu" class="col-md-3 hidden-xs" data-spy="affix" data-offset-top="0"> <div class="profile-block"> <img src="imgs/jon.png" class="img-circle"> <h4 class="profile-title">Jonny Doo <small>@jonnydoo</small></h4> </div> </div>
Check out the page in the browser, and you will see that it is not displaying nicely. For the CSS, we must follow this style:
#side-menu { background-color: #1b1e24; padding-top: 7.2rem; height: 100%; position: fixed; } #side-menu .profile-block > * { display: inline-block; } #side-menu .profile-block img { width: 70px; } #side-menu .profile-title { color: #FFF; margin-left: 1rem; font-size: 1.5em; vertical-align: middle; } #side-menu .profile-title small { display: block; }
With that, the #side-menu
should fill the entire left height, but if you resize the browser to a smaller resolution, you will see that #nav-header
does not resize together with the main content. This is a small challenge. Do you know why it is happening?
That was a little prank! Did I get you? In #side-menu
, we applied only the class for medium viewports, that is, the .col-md-3
class. What we should have done was apply the class for small devices as well to make it responsive to small viewports and resize like all the other elements, which needs the .col-sm-*
class. In this case, just change the class of #side-menu
and in the #main
element as well:
<div class="container-fluid">
<div class="row">
<div id="side-menu" class="col-sm-3 hidden-xs" data-spy="affix" data-offset-top="0">
</div>
<div id="main" class="col-sm-offset-3 col-sm-9">
</div>
</div>
</div>
Here is a screenshot that shows the result of the side menu for the moment:

A web application is never a web application if it does not have a menu. After the profile info in #side-menu
, we will add a stacked menu.
Hearing the word "stacked" for a menu, what you remember? Of course, the .nav-stacked
menu from Bootstrap! Let's create a .nav-stacked
component in this menu. Therefore, after #profile-block
, append the following HTML:
<ul class="nav nav-pills nav-stacked"> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-home" aria-hidden="true"></span> Overview </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Audience </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-usd" aria-hidden="true"></span> Finances <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-time" aria-hidden="true"></span> Real time <span class="badge pull-right">12</span> </a> </li> <li class="nav-divider"></li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span> Projects <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> </li> </ul>
No secrets here! Just create a simple stacked list using the .nav
, .nav-pills
, and .nav-stacked
classes. Bootstrap will do the magic for you. You will learn a little trick now—the collapse Bootstrap plugin.
Collapse is another plugin from Bootstrap that toggles the visualization behavior of an element. It will show or collapse an item regarding the trigger of an action.
To add the collapse event to an element, you should add a data attribute called data-toggle="collapse"
. If the element is a link <a>
, point the anchor to the identifier of the element, like this: href="#my-collapsed-element"
. If it is a <button>
, add the data attribute pointing the identifier, like this for instance: data-target="#my-collapsed-element"
. The difference between using href
for a link and data-target
for a button
is because of the semantics of the element. Naturally, every link is expected to have a reference in the href
, although we do not have this requirement in buttons. So, Bootstrap binds the element through a data-target
data attribute.
We will create a sublist in our menu using the collapse plugin for the Finances and Projects entries. After the link of each one of these items, create a secondary list, as is pointed in the following highlighted HTML. Also, since we are using <a>
tags, we add to the href
the identifier of the element that will be collapsed and the data-toggle
corresponding to collapse:
<ul class="nav nav-pills nav-stacked"> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-home" aria-hidden="true"></span> Overview </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Audience </a> </li> <li> <a href="#finances-opts" class="transition" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="finances-opts"> <span class="glyphicon glyphicon-usd" aria-hidden="true"></span> Finances <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> <ul class="collapse list-unstyled" id="finances-opts"> <li> <a href="#" class="transition"> Incomes </a> </li> <li> <a href="#" class="transition"> Outcomes </a> </li> </ul> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-time" aria-hidden="true"></span> Real time <span class="badge pull-right">12</span> </a> </li> <li class="nav-divider"></li> <li> <a href="#projects-opts" class="transition" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="projects-opts"> <span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span> Projects <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> <ul class="collapse list-unstyled" id="projects-opts"> <li> <a href="#" class="transition"> Free ration nation </a> </li> <li> <a href="#" class="transition"> Cats going crazy </a> </li> </ul> </li> </ul>
To make it clear, take as an example the first collapsed menu from Finances. Below the Finances link, we created the list to be collapsed, identified by #finances-opt
. We also added the .collapse
class, which is a Bootstrap class used to collapse elements.
Going back to the Finances link, add to the href
the ID of the collapsed list, #finances-opt
. Also, we added the data-toggle="collapse"
required to Bootstrap Collapse work. Finally, we added the aria attributes, aria-controls
and aria-controls
, for semantic notation.
Refresh the browser and you will see how Bootstrap does almost the entire job for us. In the CSS, we need to add some simple styles for color and spacing:
#side-menu ul.nav { margin-top: 1rem; } #side-menu ul.nav a { color: #8b91a0; } #side-menu ul.nav a:hover, #side-menu ul.nav a:focus { color: #FFF; background-color: inherit; } #side-menu ul.nav a .glyphicon { margin-right: 0.7rem; } #side-menu ul.nav a .glyphicon.pull-right { margin-top: 0.2rem; } #side-menu ul.nav a .badge { background-color: #1ca095; } #side-menu ul.nav .nav-divider { background-color: #252830; } #side-menu ul.nav ul { margin-left: 10%; } #side-menu ul.nav ul a { display: block; background-color: #2b303b; padding: 1rem; margin-bottom: 0.3rem; border-radius: 0.25em; } #side-menu ul.nav ul a:hover { text-decoration: none; background-color: #434857; }
Go to the browser and refresh it to see the result. It should look like what is shown in this screenshot:

Let's add a cherry to this pie while learning other CSS properties. What do you think if we could rotate the arrow of the items that have collapsed menus by 90 degrees anticlockwise to create an opening effect? It would be awesome—even more if we did that with only CSS.
Add the next CSS rule for the effect using the transform
property:
#side-menu ul.nav a:focus .glyphicon.pull-right { -moz-transform: rotate(-90deg); -webkit-transform: rotate(-90deg); -o-transform: rotate(-90deg); -ms-transform: rotate(-90deg); transform: rotate(-90deg); }
This transform
property will do exactly what we want; when the link is in focus (which means it is clicked on), the icon from the arrow will rotate 90 degrees anticlockwise, because of the minus signal.
To be more pro, let's use a supernew property called will-change
. Add the style to the following selector:
#side-menu ul.nav a .glyphicon.pull-right {
margin-top: 0.2rem;
will-change: transform;
}
Tip
The will-change property
The will-change
property optimizes animations by letting the browser know which elements will change and need careful treatment. Currently, this property is not supported by all browsers, but soon it will be. Check out its availability at http://caniuse.com/#feat=will-change.
Click to open a submenu and see the opening menu animation with the arrow rotation. The next screenshot presents an open menu:

From the side stacked menu
Let's fill #side-menu
with content. At first, we have to create the profile block, which contains the user data. Place the following HTML inside the referred element:
<div id="side-menu" class="col-md-3 hidden-xs" data-spy="affix" data-offset-top="0"> <div class="profile-block"> <img src="imgs/jon.png" class="img-circle"> <h4 class="profile-title">Jonny Doo <small>@jonnydoo</small></h4> </div> </div>
Check out the page in the browser, and you will see that it is not displaying nicely. For the CSS, we must follow this style:
#side-menu { background-color: #1b1e24; padding-top: 7.2rem; height: 100%; position: fixed; } #side-menu .profile-block > * { display: inline-block; } #side-menu .profile-block img { width: 70px; } #side-menu .profile-title { color: #FFF; margin-left: 1rem; font-size: 1.5em; vertical-align: middle; } #side-menu .profile-title small { display: block; }
With that, the #side-menu
should fill the entire left height, but if you resize the browser to a smaller resolution, you will see that #nav-header
does not resize together with the main content. This is a small challenge. Do you know why it is happening?
That was a little prank! Did I get you? In #side-menu
, we applied only the class for medium viewports, that is, the .col-md-3
class. What we should have done was apply the class for small devices as well to make it responsive to small viewports and resize like all the other elements, which needs the .col-sm-*
class. In this case, just change the class of #side-menu
and in the #main
element as well:
<div class="container-fluid">
<div class="row">
<div id="side-menu" class="col-sm-3 hidden-xs" data-spy="affix" data-offset-top="0">
</div>
<div id="main" class="col-sm-offset-3 col-sm-9">
</div>
</div>
</div>
Here is a screenshot that shows the result of the side menu for the moment:

A web application is never a web application if it does not have a menu. After the profile info in #side-menu
, we will add a stacked menu.
Hearing the word "stacked" for a menu, what you remember? Of course, the .nav-stacked
menu from Bootstrap! Let's create a .nav-stacked
component in this menu. Therefore, after #profile-block
, append the following HTML:
<ul class="nav nav-pills nav-stacked"> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-home" aria-hidden="true"></span> Overview </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Audience </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-usd" aria-hidden="true"></span> Finances <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-time" aria-hidden="true"></span> Real time <span class="badge pull-right">12</span> </a> </li> <li class="nav-divider"></li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span> Projects <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> </li> </ul>
No secrets here! Just create a simple stacked list using the .nav
, .nav-pills
, and .nav-stacked
classes. Bootstrap will do the magic for you. You will learn a little trick now—the collapse Bootstrap plugin.
Collapse is another plugin from Bootstrap that toggles the visualization behavior of an element. It will show or collapse an item regarding the trigger of an action.
To add the collapse event to an element, you should add a data attribute called data-toggle="collapse"
. If the element is a link <a>
, point the anchor to the identifier of the element, like this: href="#my-collapsed-element"
. If it is a <button>
, add the data attribute pointing the identifier, like this for instance: data-target="#my-collapsed-element"
. The difference between using href
for a link and data-target
for a button
is because of the semantics of the element. Naturally, every link is expected to have a reference in the href
, although we do not have this requirement in buttons. So, Bootstrap binds the element through a data-target
data attribute.
We will create a sublist in our menu using the collapse plugin for the Finances and Projects entries. After the link of each one of these items, create a secondary list, as is pointed in the following highlighted HTML. Also, since we are using <a>
tags, we add to the href
the identifier of the element that will be collapsed and the data-toggle
corresponding to collapse:
<ul class="nav nav-pills nav-stacked"> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-home" aria-hidden="true"></span> Overview </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Audience </a> </li> <li> <a href="#finances-opts" class="transition" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="finances-opts"> <span class="glyphicon glyphicon-usd" aria-hidden="true"></span> Finances <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> <ul class="collapse list-unstyled" id="finances-opts"> <li> <a href="#" class="transition"> Incomes </a> </li> <li> <a href="#" class="transition"> Outcomes </a> </li> </ul> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-time" aria-hidden="true"></span> Real time <span class="badge pull-right">12</span> </a> </li> <li class="nav-divider"></li> <li> <a href="#projects-opts" class="transition" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="projects-opts"> <span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span> Projects <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> <ul class="collapse list-unstyled" id="projects-opts"> <li> <a href="#" class="transition"> Free ration nation </a> </li> <li> <a href="#" class="transition"> Cats going crazy </a> </li> </ul> </li> </ul>
To make it clear, take as an example the first collapsed menu from Finances. Below the Finances link, we created the list to be collapsed, identified by #finances-opt
. We also added the .collapse
class, which is a Bootstrap class used to collapse elements.
Going back to the Finances link, add to the href
the ID of the collapsed list, #finances-opt
. Also, we added the data-toggle="collapse"
required to Bootstrap Collapse work. Finally, we added the aria attributes, aria-controls
and aria-controls
, for semantic notation.
Refresh the browser and you will see how Bootstrap does almost the entire job for us. In the CSS, we need to add some simple styles for color and spacing:
#side-menu ul.nav { margin-top: 1rem; } #side-menu ul.nav a { color: #8b91a0; } #side-menu ul.nav a:hover, #side-menu ul.nav a:focus { color: #FFF; background-color: inherit; } #side-menu ul.nav a .glyphicon { margin-right: 0.7rem; } #side-menu ul.nav a .glyphicon.pull-right { margin-top: 0.2rem; } #side-menu ul.nav a .badge { background-color: #1ca095; } #side-menu ul.nav .nav-divider { background-color: #252830; } #side-menu ul.nav ul { margin-left: 10%; } #side-menu ul.nav ul a { display: block; background-color: #2b303b; padding: 1rem; margin-bottom: 0.3rem; border-radius: 0.25em; } #side-menu ul.nav ul a:hover { text-decoration: none; background-color: #434857; }
Go to the browser and refresh it to see the result. It should look like what is shown in this screenshot:

Let's add a cherry to this pie while learning other CSS properties. What do you think if we could rotate the arrow of the items that have collapsed menus by 90 degrees anticlockwise to create an opening effect? It would be awesome—even more if we did that with only CSS.
Add the next CSS rule for the effect using the transform
property:
#side-menu ul.nav a:focus .glyphicon.pull-right { -moz-transform: rotate(-90deg); -webkit-transform: rotate(-90deg); -o-transform: rotate(-90deg); -ms-transform: rotate(-90deg); transform: rotate(-90deg); }
This transform
property will do exactly what we want; when the link is in focus (which means it is clicked on), the icon from the arrow will rotate 90 degrees anticlockwise, because of the minus signal.
To be more pro, let's use a supernew property called will-change
. Add the style to the following selector:
#side-menu ul.nav a .glyphicon.pull-right {
margin-top: 0.2rem;
will-change: transform;
}
Tip
The will-change property
The will-change
property optimizes animations by letting the browser know which elements will change and need careful treatment. Currently, this property is not supported by all browsers, but soon it will be. Check out its availability at http://caniuse.com/#feat=will-change.
Click to open a submenu and see the opening menu animation with the arrow rotation. The next screenshot presents an open menu:

I heard that the left menu is great!
A web application is never a web application if it does not have a menu. After the profile info in #side-menu
, we will add a stacked menu.
Hearing the word "stacked" for a menu, what you remember? Of course, the .nav-stacked
menu from Bootstrap! Let's create a .nav-stacked
component in this menu. Therefore, after #profile-block
, append the following HTML:
<ul class="nav nav-pills nav-stacked"> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-home" aria-hidden="true"></span> Overview </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Audience </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-usd" aria-hidden="true"></span> Finances <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-time" aria-hidden="true"></span> Real time <span class="badge pull-right">12</span> </a> </li> <li class="nav-divider"></li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span> Projects <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> </li> </ul>
No secrets here! Just create a simple stacked list using the .nav
, .nav-pills
, and .nav-stacked
classes. Bootstrap will do the magic for you. You will learn a little trick now—the collapse Bootstrap plugin.
Collapse is another plugin from Bootstrap that toggles the visualization behavior of an element. It will show or collapse an item regarding the trigger of an action.
To add the collapse event to an element, you should add a data attribute called data-toggle="collapse"
. If the element is a link <a>
, point the anchor to the identifier of the element, like this: href="#my-collapsed-element"
. If it is a <button>
, add the data attribute pointing the identifier, like this for instance: data-target="#my-collapsed-element"
. The difference between using href
for a link and data-target
for a button
is because of the semantics of the element. Naturally, every link is expected to have a reference in the href
, although we do not have this requirement in buttons. So, Bootstrap binds the element through a data-target
data attribute.
We will create a sublist in our menu using the collapse plugin for the Finances and Projects entries. After the link of each one of these items, create a secondary list, as is pointed in the following highlighted HTML. Also, since we are using <a>
tags, we add to the href
the identifier of the element that will be collapsed and the data-toggle
corresponding to collapse:
<ul class="nav nav-pills nav-stacked"> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-home" aria-hidden="true"></span> Overview </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Audience </a> </li> <li> <a href="#finances-opts" class="transition" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="finances-opts"> <span class="glyphicon glyphicon-usd" aria-hidden="true"></span> Finances <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> <ul class="collapse list-unstyled" id="finances-opts"> <li> <a href="#" class="transition"> Incomes </a> </li> <li> <a href="#" class="transition"> Outcomes </a> </li> </ul> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-time" aria-hidden="true"></span> Real time <span class="badge pull-right">12</span> </a> </li> <li class="nav-divider"></li> <li> <a href="#projects-opts" class="transition" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="projects-opts"> <span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span> Projects <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> <ul class="collapse list-unstyled" id="projects-opts"> <li> <a href="#" class="transition"> Free ration nation </a> </li> <li> <a href="#" class="transition"> Cats going crazy </a> </li> </ul> </li> </ul>
To make it clear, take as an example the first collapsed menu from Finances. Below the Finances link, we created the list to be collapsed, identified by #finances-opt
. We also added the .collapse
class, which is a Bootstrap class used to collapse elements.
Going back to the Finances link, add to the href
the ID of the collapsed list, #finances-opt
. Also, we added the data-toggle="collapse"
required to Bootstrap Collapse work. Finally, we added the aria attributes, aria-controls
and aria-controls
, for semantic notation.
Refresh the browser and you will see how Bootstrap does almost the entire job for us. In the CSS, we need to add some simple styles for color and spacing:
#side-menu ul.nav { margin-top: 1rem; } #side-menu ul.nav a { color: #8b91a0; } #side-menu ul.nav a:hover, #side-menu ul.nav a:focus { color: #FFF; background-color: inherit; } #side-menu ul.nav a .glyphicon { margin-right: 0.7rem; } #side-menu ul.nav a .glyphicon.pull-right { margin-top: 0.2rem; } #side-menu ul.nav a .badge { background-color: #1ca095; } #side-menu ul.nav .nav-divider { background-color: #252830; } #side-menu ul.nav ul { margin-left: 10%; } #side-menu ul.nav ul a { display: block; background-color: #2b303b; padding: 1rem; margin-bottom: 0.3rem; border-radius: 0.25em; } #side-menu ul.nav ul a:hover { text-decoration: none; background-color: #434857; }
Go to the browser and refresh it to see the result. It should look like what is shown in this screenshot:

Let's add a cherry to this pie while learning other CSS properties. What do you think if we could rotate the arrow of the items that have collapsed menus by 90 degrees anticlockwise to create an opening effect? It would be awesome—even more if we did that with only CSS.
Add the next CSS rule for the effect using the transform
property:
#side-menu ul.nav a:focus .glyphicon.pull-right { -moz-transform: rotate(-90deg); -webkit-transform: rotate(-90deg); -o-transform: rotate(-90deg); -ms-transform: rotate(-90deg); transform: rotate(-90deg); }
This transform
property will do exactly what we want; when the link is in focus (which means it is clicked on), the icon from the arrow will rotate 90 degrees anticlockwise, because of the minus signal.
To be more pro, let's use a supernew property called will-change
. Add the style to the following selector:
#side-menu ul.nav a .glyphicon.pull-right {
margin-top: 0.2rem;
will-change: transform;
}
Tip
The will-change property
The will-change
property optimizes animations by letting the browser know which elements will change and need careful treatment. Currently, this property is not supported by all browsers, but soon it will be. Check out its availability at http://caniuse.com/#feat=will-change.
Click to open a submenu and see the opening menu animation with the arrow rotation. The next screenshot presents an open menu:

Learning the collapse plugin
Collapse is another plugin from Bootstrap that toggles the visualization behavior of an element. It will show or collapse an item regarding the trigger of an action.
To add the collapse event to an element, you should add a data attribute called data-toggle="collapse"
. If the element is a link <a>
, point the anchor to the identifier of the element, like this: href="#my-collapsed-element"
. If it is a <button>
, add the data attribute pointing the identifier, like this for instance: data-target="#my-collapsed-element"
. The difference between using href
for a link and data-target
for a button
is because of the semantics of the element. Naturally, every link is expected to have a reference in the href
, although we do not have this requirement in buttons. So, Bootstrap binds the element through a data-target
data attribute.
We will create a sublist in our menu using the collapse plugin for the Finances and Projects entries. After the link of each one of these items, create a secondary list, as is pointed in the following highlighted HTML. Also, since we are using <a>
tags, we add to the href
the identifier of the element that will be collapsed and the data-toggle
corresponding to collapse:
<ul class="nav nav-pills nav-stacked"> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-home" aria-hidden="true"></span> Overview </a> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-user" aria-hidden="true"></span> Audience </a> </li> <li> <a href="#finances-opts" class="transition" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="finances-opts"> <span class="glyphicon glyphicon-usd" aria-hidden="true"></span> Finances <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> <ul class="collapse list-unstyled" id="finances-opts"> <li> <a href="#" class="transition"> Incomes </a> </li> <li> <a href="#" class="transition"> Outcomes </a> </li> </ul> </li> <li> <a href="#" class="transition"> <span class="glyphicon glyphicon-time" aria-hidden="true"></span> Real time <span class="badge pull-right">12</span> </a> </li> <li class="nav-divider"></li> <li> <a href="#projects-opts" class="transition" role="button" data-toggle="collapse" aria-expanded="false" aria-controls="projects-opts"> <span class="glyphicon glyphicon-briefcase" aria-hidden="true"></span> Projects <span class="glyphicon glyphicon-menu-left pull-right transition" aria-hidden="true"></span> </a> <ul class="collapse list-unstyled" id="projects-opts"> <li> <a href="#" class="transition"> Free ration nation </a> </li> <li> <a href="#" class="transition"> Cats going crazy </a> </li> </ul> </li> </ul>
To make it clear, take as an example the first collapsed menu from Finances. Below the Finances link, we created the list to be collapsed, identified by #finances-opt
. We also added the .collapse
class, which is a Bootstrap class used to collapse elements.
Going back to the Finances link, add to the href
the ID of the collapsed list, #finances-opt
. Also, we added the data-toggle="collapse"
required to Bootstrap Collapse work. Finally, we added the aria attributes, aria-controls
and aria-controls
, for semantic notation.
Refresh the browser and you will see how Bootstrap does almost the entire job for us. In the CSS, we need to add some simple styles for color and spacing:
#side-menu ul.nav { margin-top: 1rem; } #side-menu ul.nav a { color: #8b91a0; } #side-menu ul.nav a:hover, #side-menu ul.nav a:focus { color: #FFF; background-color: inherit; } #side-menu ul.nav a .glyphicon { margin-right: 0.7rem; } #side-menu ul.nav a .glyphicon.pull-right { margin-top: 0.2rem; } #side-menu ul.nav a .badge { background-color: #1ca095; } #side-menu ul.nav .nav-divider { background-color: #252830; } #side-menu ul.nav ul { margin-left: 10%; } #side-menu ul.nav ul a { display: block; background-color: #2b303b; padding: 1rem; margin-bottom: 0.3rem; border-radius: 0.25em; } #side-menu ul.nav ul a:hover { text-decoration: none; background-color: #434857; }
Go to the browser and refresh it to see the result. It should look like what is shown in this screenshot:

Let's add a cherry to this pie while learning other CSS properties. What do you think if we could rotate the arrow of the items that have collapsed menus by 90 degrees anticlockwise to create an opening effect? It would be awesome—even more if we did that with only CSS.
Add the next CSS rule for the effect using the transform
property:
#side-menu ul.nav a:focus .glyphicon.pull-right { -moz-transform: rotate(-90deg); -webkit-transform: rotate(-90deg); -o-transform: rotate(-90deg); -ms-transform: rotate(-90deg); transform: rotate(-90deg); }
This transform
property will do exactly what we want; when the link is in focus (which means it is clicked on), the icon from the arrow will rotate 90 degrees anticlockwise, because of the minus signal.
To be more pro, let's use a supernew property called will-change
. Add the style to the following selector:
#side-menu ul.nav a .glyphicon.pull-right {
margin-top: 0.2rem;
will-change: transform;
}
Tip
The will-change property
The will-change
property optimizes animations by letting the browser know which elements will change and need careful treatment. Currently, this property is not supported by all browsers, but soon it will be. Check out its availability at http://caniuse.com/#feat=will-change.
Click to open a submenu and see the opening menu animation with the arrow rotation. The next screenshot presents an open menu:

Using some advanced CSS
Let's add a cherry to this pie while learning other CSS properties. What do you think if we could rotate the arrow of the items that have collapsed menus by 90 degrees anticlockwise to create an opening effect? It would be awesome—even more if we did that with only CSS.
Add the next CSS rule for the effect using the transform
property:
#side-menu ul.nav a:focus .glyphicon.pull-right { -moz-transform: rotate(-90deg); -webkit-transform: rotate(-90deg); -o-transform: rotate(-90deg); -ms-transform: rotate(-90deg); transform: rotate(-90deg); }
This transform
property will do exactly what we want; when the link is in focus (which means it is clicked on), the icon from the arrow will rotate 90 degrees anticlockwise, because of the minus signal.
To be more pro, let's use a supernew property called will-change
. Add the style to the following selector:
#side-menu ul.nav a .glyphicon.pull-right {
margin-top: 0.2rem;
will-change: transform;
}
Tip
The will-change property
The will-change
property optimizes animations by letting the browser know which elements will change and need careful treatment. Currently, this property is not supported by all browsers, but soon it will be. Check out its availability at http://caniuse.com/#feat=will-change.
Click to open a submenu and see the opening menu animation with the arrow rotation. The next screenshot presents an open menu:

To finish the content of the first step of our dashboard, we will move on to the main content, referred to by the column identified by #main
. In this section, we will create a set of cards almost similar to the cards made in the web application demo, along with the use of some external plugins for chart generation.
However, before everything else, we need to create some common CSS in our main content. Add the following style to the base.css
file:
#main { padding-top: 7.2rem; display: -webkit-flex; display: flex; align-items: stretch; flex-flow: row wrap; } .card { position: relative; border-radius: 0.25em; box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); background-color: #FFF; margin: 1.25rem; flex-grow: 5; } .card * { color: #252830; } .card-block { padding: 2rem; } .card-block h2 { margin: 0; margin-bottom: 1.5rem; color: #252830; }
As I said, we will play with cards inside this element, so let's create the classes that relate to it almost similarly to what we did in the cards for the web application example. In this case, even though you are using Bootstrap 4, you must add to those classes to correctly style the cards component.
Our first card will be placed inside the #main
element. So, create the following HTML. The first card will be an
Overall analysis card:
<div id="main" class="col-sm-offset-3 col-sm-9"> <div class="card" id="pie-charts"> <div class="card-block"> <h2>Overall analysis</h2> </div> </div> </div>
The first plugin that we will use is called Easy Pie Chart (https://rendro.github.io/easy-pie-chart/). This plugin generates only rounded pie charts. It is a lightweight, single-purpose plugin.
In order to use this plugin, you can get it through bower, through npm, or by simply downloading the ZIP file from the repository. In any case, what you will need to do at the end is load the plugin in the HTML file.
We will use the jQuery version of the plugin, so we place the JavaScript file in our js
folder and load the plugin at the end of our file:
<script src="js/jquery-1.11.3.js"></script>
<script src="js/bootstrap.js"></script>
<script src="js/jquery.easypiechart.min.js"></script>
<script src="js/main.js"></script>
Inside our #pie-charts
card that we just created, let's add some HTML that is needed for the corresponding plugin:
<div class="card" id="pie-charts"> <div class="card-block"> <h2>Overall analysis</h2> <div class="round-chart" data-percent="42"> <span> 42 <small> % <br> recurring </small> </span> </div> <div class="round-chart" data-percent="87"> <span> 87 <small> % <br> aware </small> </span> </div> </div> </div>
To make the Easy Pie Chart plugin work, you must apply it to an element, and you can pass arguments by data attributes. For example, in this case, we have data-percent
, which will say the fill of the chart.
Go to your JavaScript file (the main.js
file), and inside the ready
function (just as we did in Chapter 8, Working with JavaScript, Creating our custom modal), add the following code to initialize the plugin:
$(document).ready(function() { $('.round-chart').easyPieChart({ 'scaleColor': false, 'lineWidth': 20, 'lineCap': 'butt', 'barColor': '#6d5cae', 'trackColor': '#e5e9ec', 'size': 190 }); });
What we are telling here is the style of the chart. But we need more style! We append the following CSS to our base.css
:
.round-chart { display: inline-block; position: relative; } .round-chart + .round-chart { float: right; } .round-chart span { font-size: 3em; font-weight: 100; line-height: 1.7rem; width: 12rem; height: 4.4rem; text-align: center; position: absolute; margin: auto; top: 0; bottom: 0; left: 0; right: 0; } .round-chart span > small { font-size: 2rem; font-weight: 400; }
What we are doing here, besides changing some spacing, is the centralization of the percentage text that we have added. Refresh the page and you should see something like this:

As you can see, the card has filled the entire line. This is because of the flexbox
layout that we are using in the #main
element. Check out the CSS that we used for this element:
#main { padding-top: 7.2rem; display: -webkit-flex; display: flex; align-items: stretch; flex-flow: row wrap; }
With the flex
display, if we use align-items: stretch
, the layout will stretch to fill the content in the cross axis.
The flex-flow
style is a shorthand for flex-direction
and flex-wrap
. By using this property, we can apply both options to specify the direction of the items, in this case as a row
, and set the row to wrap to the next lines.
Also, for each card, we have created the flex-grow: 5
property, which says to the element that it can assume five different sizes inside the #main
container.
The next card contains statistical information and we will create it just by using Bootstrap components. So, after the #pie-charts
card, create another one in HTML:
<div class="card" id="quick-info"> <div class="card-block"> <h2>Quick stats</h2> <div class="quick-stats"> <strong>Today:</strong> <span>78</span> </div> <div class="quick-stats"> <strong>This month:</strong> <span>459</span> </div> <div class="quick-stats"> <strong>All time:</strong> <span>54k</span> </div> <div class="quick-stats"> <strong>Bounce rate:</strong> <span>81.08%</span> </div> <div class="quick-stats"> <strong>Session duration:</strong> <span>00:01:41</span> </div> <div class="quick-stats"> <strong>New session:</strong> <span>63.86%</span> </div> </div> </div>
The #quick-info
card contains only the common elements that will be displayed, each one in a line inside .card
. Add the next CSS style to correctly display this card:
#quick-info .card-block { display: flex; flex-direction: column; } #quick-info .quick-stats { font-size: 2rem; line-height: 3rem; border-bottom: 0.1rem solid #e5e9ec; } #quick-info .quick-stats strong { font-weight: 300; } #quick-info .quick-stats span { font-weight: 300; float: right; color: #8b91a0; }
In the web browser, you should see the following result:

But wait! If you look at the initial layout, you will realize that those two cards should be displayed side by side! What happened here?
This is another advantage of using the flexbox! With a flex display, each item inside the container will adapt for the display. The previous screenshot was taken from a medium viewport. If you take it from a large-resolution screen, you will see how the elements appear side by side, like this:

The next chart is called a spider chart. The Highcharts plugin (http://www.highcharts.com/) is one of the most definitive plugins used to create charts. It provides a wide variety of charts divided over different modules, so you can load only the plugins that you will use.
Just like Easy Pie Chart, you can get Highcharts from different sources. After getting it, let's load the first Highcharts module that we need. Load them along with the other JavaScript files (the plugin is loaded using CDN in this case):
<script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/highcharts-more.js"></script>
Create another .card
in the HTML after #quick-info
, this new one being identified by #performance-eval
:
<div class="card" id="performance-eval"> <div class="card-block"> <h2>Performance evaluation</h2> <div class="spider-chart"></div> </div> </div>
Highcharts does not require too much HTML, but you need to customize it all over JavaScript. To initialize and customize the plugin, add the following code inside the ready
function of the JavaScript:
$('#performance-eval .spider-chart').highcharts({ chart: { polar: true, type: 'area' }, title: { text: '' }, xAxis: { categories: ['Taming', 'Acessory', 'Development', 'Grooming', 'Awareness', 'Ration'], tickmarkPlacement: 'on', lineWidth: 0 }, yAxis: { gridLineInterpolation: 'polygon', lineWidth: 0, min: 0 }, tooltip: { shared: true, pointFormat: '<span style="color:{series.color}">{series.name}: <b>${point.y:,.0f}</b><br/>' }, legend: { align: 'right', verticalAlign: 'top', y: 70, layout: 'vertical' }, series: [{ name: 'Allocated resources', data: [45000, 39000, 58000, 63000, 38000, 93000], pointPlacement: 'on', color: '#676F84' }, { name: 'Spent resources', data: [83000, 49000, 60000, 35000, 77000, 90000], pointPlacement: 'on', color: '#f35958' }] });
In this JavaScript code, we called the highcharts
function for the selector chart #performance-eval .spider-chart
. All the properties are fully described in the official documentation. Just note that we instructed the chart that we want a polar chart with the polar: true
key inside the chart
key option.
The dashboard application must look and feel like this:

Rounding the charts
The first plugin that we will use is called Easy Pie Chart (https://rendro.github.io/easy-pie-chart/). This plugin generates only rounded pie charts. It is a lightweight, single-purpose plugin.
In order to use this plugin, you can get it through bower, through npm, or by simply downloading the ZIP file from the repository. In any case, what you will need to do at the end is load the plugin in the HTML file.
We will use the jQuery version of the plugin, so we place the JavaScript file in our js
folder and load the plugin at the end of our file:
<script src="js/jquery-1.11.3.js"></script>
<script src="js/bootstrap.js"></script>
<script src="js/jquery.easypiechart.min.js"></script>
<script src="js/main.js"></script>
Inside our #pie-charts
card that we just created, let's add some HTML that is needed for the corresponding plugin:
<div class="card" id="pie-charts"> <div class="card-block"> <h2>Overall analysis</h2> <div class="round-chart" data-percent="42"> <span> 42 <small> % <br> recurring </small> </span> </div> <div class="round-chart" data-percent="87"> <span> 87 <small> % <br> aware </small> </span> </div> </div> </div>
To make the Easy Pie Chart plugin work, you must apply it to an element, and you can pass arguments by data attributes. For example, in this case, we have data-percent
, which will say the fill of the chart.
Go to your JavaScript file (the main.js
file), and inside the ready
function (just as we did in Chapter 8, Working with JavaScript, Creating our custom modal), add the following code to initialize the plugin:
$(document).ready(function() { $('.round-chart').easyPieChart({ 'scaleColor': false, 'lineWidth': 20, 'lineCap': 'butt', 'barColor': '#6d5cae', 'trackColor': '#e5e9ec', 'size': 190 }); });
What we are telling here is the style of the chart. But we need more style! We append the following CSS to our base.css
:
.round-chart { display: inline-block; position: relative; } .round-chart + .round-chart { float: right; } .round-chart span { font-size: 3em; font-weight: 100; line-height: 1.7rem; width: 12rem; height: 4.4rem; text-align: center; position: absolute; margin: auto; top: 0; bottom: 0; left: 0; right: 0; } .round-chart span > small { font-size: 2rem; font-weight: 400; }
What we are doing here, besides changing some spacing, is the centralization of the percentage text that we have added. Refresh the page and you should see something like this:

As you can see, the card has filled the entire line. This is because of the flexbox
layout that we are using in the #main
element. Check out the CSS that we used for this element:
#main { padding-top: 7.2rem; display: -webkit-flex; display: flex; align-items: stretch; flex-flow: row wrap; }
With the flex
display, if we use align-items: stretch
, the layout will stretch to fill the content in the cross axis.
The flex-flow
style is a shorthand for flex-direction
and flex-wrap
. By using this property, we can apply both options to specify the direction of the items, in this case as a row
, and set the row to wrap to the next lines.
Also, for each card, we have created the flex-grow: 5
property, which says to the element that it can assume five different sizes inside the #main
container.
The next card contains statistical information and we will create it just by using Bootstrap components. So, after the #pie-charts
card, create another one in HTML:
<div class="card" id="quick-info"> <div class="card-block"> <h2>Quick stats</h2> <div class="quick-stats"> <strong>Today:</strong> <span>78</span> </div> <div class="quick-stats"> <strong>This month:</strong> <span>459</span> </div> <div class="quick-stats"> <strong>All time:</strong> <span>54k</span> </div> <div class="quick-stats"> <strong>Bounce rate:</strong> <span>81.08%</span> </div> <div class="quick-stats"> <strong>Session duration:</strong> <span>00:01:41</span> </div> <div class="quick-stats"> <strong>New session:</strong> <span>63.86%</span> </div> </div> </div>
The #quick-info
card contains only the common elements that will be displayed, each one in a line inside .card
. Add the next CSS style to correctly display this card:
#quick-info .card-block { display: flex; flex-direction: column; } #quick-info .quick-stats { font-size: 2rem; line-height: 3rem; border-bottom: 0.1rem solid #e5e9ec; } #quick-info .quick-stats strong { font-weight: 300; } #quick-info .quick-stats span { font-weight: 300; float: right; color: #8b91a0; }
In the web browser, you should see the following result:

But wait! If you look at the initial layout, you will realize that those two cards should be displayed side by side! What happened here?
This is another advantage of using the flexbox! With a flex display, each item inside the container will adapt for the display. The previous screenshot was taken from a medium viewport. If you take it from a large-resolution screen, you will see how the elements appear side by side, like this:

The next chart is called a spider chart. The Highcharts plugin (http://www.highcharts.com/) is one of the most definitive plugins used to create charts. It provides a wide variety of charts divided over different modules, so you can load only the plugins that you will use.
Just like Easy Pie Chart, you can get Highcharts from different sources. After getting it, let's load the first Highcharts module that we need. Load them along with the other JavaScript files (the plugin is loaded using CDN in this case):
<script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/highcharts-more.js"></script>
Create another .card
in the HTML after #quick-info
, this new one being identified by #performance-eval
:
<div class="card" id="performance-eval"> <div class="card-block"> <h2>Performance evaluation</h2> <div class="spider-chart"></div> </div> </div>
Highcharts does not require too much HTML, but you need to customize it all over JavaScript. To initialize and customize the plugin, add the following code inside the ready
function of the JavaScript:
$('#performance-eval .spider-chart').highcharts({ chart: { polar: true, type: 'area' }, title: { text: '' }, xAxis: { categories: ['Taming', 'Acessory', 'Development', 'Grooming', 'Awareness', 'Ration'], tickmarkPlacement: 'on', lineWidth: 0 }, yAxis: { gridLineInterpolation: 'polygon', lineWidth: 0, min: 0 }, tooltip: { shared: true, pointFormat: '<span style="color:{series.color}">{series.name}: <b>${point.y:,.0f}</b><br/>' }, legend: { align: 'right', verticalAlign: 'top', y: 70, layout: 'vertical' }, series: [{ name: 'Allocated resources', data: [45000, 39000, 58000, 63000, 38000, 93000], pointPlacement: 'on', color: '#676F84' }, { name: 'Spent resources', data: [83000, 49000, 60000, 35000, 77000, 90000], pointPlacement: 'on', color: '#f35958' }] });
In this JavaScript code, we called the highcharts
function for the selector chart #performance-eval .spider-chart
. All the properties are fully described in the official documentation. Just note that we instructed the chart that we want a polar chart with the polar: true
key inside the chart
key option.
The dashboard application must look and feel like this:

Creating a quick statistical card
The next card contains statistical information and we will create it just by using Bootstrap components. So, after the #pie-charts
card, create another one in HTML:
<div class="card" id="quick-info"> <div class="card-block"> <h2>Quick stats</h2> <div class="quick-stats"> <strong>Today:</strong> <span>78</span> </div> <div class="quick-stats"> <strong>This month:</strong> <span>459</span> </div> <div class="quick-stats"> <strong>All time:</strong> <span>54k</span> </div> <div class="quick-stats"> <strong>Bounce rate:</strong> <span>81.08%</span> </div> <div class="quick-stats"> <strong>Session duration:</strong> <span>00:01:41</span> </div> <div class="quick-stats"> <strong>New session:</strong> <span>63.86%</span> </div> </div> </div>
The #quick-info
card contains only the common elements that will be displayed, each one in a line inside .card
. Add the next CSS style to correctly display this card:
#quick-info .card-block { display: flex; flex-direction: column; } #quick-info .quick-stats { font-size: 2rem; line-height: 3rem; border-bottom: 0.1rem solid #e5e9ec; } #quick-info .quick-stats strong { font-weight: 300; } #quick-info .quick-stats span { font-weight: 300; float: right; color: #8b91a0; }
In the web browser, you should see the following result:

But wait! If you look at the initial layout, you will realize that those two cards should be displayed side by side! What happened here?
This is another advantage of using the flexbox! With a flex display, each item inside the container will adapt for the display. The previous screenshot was taken from a medium viewport. If you take it from a large-resolution screen, you will see how the elements appear side by side, like this:

The next chart is called a spider chart. The Highcharts plugin (http://www.highcharts.com/) is one of the most definitive plugins used to create charts. It provides a wide variety of charts divided over different modules, so you can load only the plugins that you will use.
Just like Easy Pie Chart, you can get Highcharts from different sources. After getting it, let's load the first Highcharts module that we need. Load them along with the other JavaScript files (the plugin is loaded using CDN in this case):
<script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/highcharts-more.js"></script>
Create another .card
in the HTML after #quick-info
, this new one being identified by #performance-eval
:
<div class="card" id="performance-eval"> <div class="card-block"> <h2>Performance evaluation</h2> <div class="spider-chart"></div> </div> </div>
Highcharts does not require too much HTML, but you need to customize it all over JavaScript. To initialize and customize the plugin, add the following code inside the ready
function of the JavaScript:
$('#performance-eval .spider-chart').highcharts({ chart: { polar: true, type: 'area' }, title: { text: '' }, xAxis: { categories: ['Taming', 'Acessory', 'Development', 'Grooming', 'Awareness', 'Ration'], tickmarkPlacement: 'on', lineWidth: 0 }, yAxis: { gridLineInterpolation: 'polygon', lineWidth: 0, min: 0 }, tooltip: { shared: true, pointFormat: '<span style="color:{series.color}">{series.name}: <b>${point.y:,.0f}</b><br/>' }, legend: { align: 'right', verticalAlign: 'top', y: 70, layout: 'vertical' }, series: [{ name: 'Allocated resources', data: [45000, 39000, 58000, 63000, 38000, 93000], pointPlacement: 'on', color: '#676F84' }, { name: 'Spent resources', data: [83000, 49000, 60000, 35000, 77000, 90000], pointPlacement: 'on', color: '#f35958' }] });
In this JavaScript code, we called the highcharts
function for the selector chart #performance-eval .spider-chart
. All the properties are fully described in the official documentation. Just note that we instructed the chart that we want a polar chart with the polar: true
key inside the chart
key option.
The dashboard application must look and feel like this:

Getting a spider chart
The next chart is called a spider chart. The Highcharts plugin (http://www.highcharts.com/) is one of the most definitive plugins used to create charts. It provides a wide variety of charts divided over different modules, so you can load only the plugins that you will use.
Just like Easy Pie Chart, you can get Highcharts from different sources. After getting it, let's load the first Highcharts module that we need. Load them along with the other JavaScript files (the plugin is loaded using CDN in this case):
<script src="https://code.highcharts.com/highcharts.js"></script> <script src="https://code.highcharts.com/highcharts-more.js"></script>
Create another .card
in the HTML after #quick-info
, this new one being identified by #performance-eval
:
<div class="card" id="performance-eval"> <div class="card-block"> <h2>Performance evaluation</h2> <div class="spider-chart"></div> </div> </div>
Highcharts does not require too much HTML, but you need to customize it all over JavaScript. To initialize and customize the plugin, add the following code inside the ready
function of the JavaScript:
$('#performance-eval .spider-chart').highcharts({ chart: { polar: true, type: 'area' }, title: { text: '' }, xAxis: { categories: ['Taming', 'Acessory', 'Development', 'Grooming', 'Awareness', 'Ration'], tickmarkPlacement: 'on', lineWidth: 0 }, yAxis: { gridLineInterpolation: 'polygon', lineWidth: 0, min: 0 }, tooltip: { shared: true, pointFormat: '<span style="color:{series.color}">{series.name}: <b>${point.y:,.0f}</b><br/>' }, legend: { align: 'right', verticalAlign: 'top', y: 70, layout: 'vertical' }, series: [{ name: 'Allocated resources', data: [45000, 39000, 58000, 63000, 38000, 93000], pointPlacement: 'on', color: '#676F84' }, { name: 'Spent resources', data: [83000, 49000, 60000, 35000, 77000, 90000], pointPlacement: 'on', color: '#f35958' }] });
In this JavaScript code, we called the highcharts
function for the selector chart #performance-eval .spider-chart
. All the properties are fully described in the official documentation. Just note that we instructed the chart that we want a polar chart with the polar: true
key inside the chart
key option.
The dashboard application must look and feel like this:

Another cool feature from these plugins is that they provide animations for charts, making the final result very user friendly.
By loading the pieces of JavaScript code at the end of the HTML, we will acquire more speed in page rendering for the end user. The side effect of this is that the elements created by the JavaScript libraries will render the page after it is shown to the user, causing some temporary glitches in the screen.
To solve this, many pages use the strategy of creating an overlay loading that will be hidden after the document is ready.
To do this, just after the opening of the <body>
tag, create a <div>
to keep the loading, as follows:
<body> <div class="loading"> </div> … <!—rest of the HTML content --> </body>
We added a loading animated .svg
file in the images folder, so in the CSS, we create the following rules:
.loading { position: fixed; z-index: 999; width: 100%; height: 100%; background-image: url('../imgs/loading.svg'); background-repeat: no-repeat; background-attachment: fixed; background-position: center; background-color: #e5e9ec; }
This will create an overlay element that will appear at the top of all elements, except for the navigation bar. This element will fill the complete width and height of the page, while containing the loading animated image in the center of it.
Refresh the page and you will see the loading on top of your dashboard web application, as follows:

Now we must remove the loading image after the page is ready. So, in the beginning of the JavaScript file, before the first line inside the $(document).ready
function, remove the loading element:
$(document).ready(function() { // when page is loaded, remove the loading $('.loading').remove(); // below goes the rest of the JavaScript code });
Done! Refresh the web browser and you may see the loading screen depending on your computer and network.
The loading element may see an overreaction now, because we still do not have too many cards on our dashboard, but we will keep adding them, so it is cautious to start handling this problem.
We created our page using the principles of mobile-first development, although some of the components here are not appearing properly or are simply not appearing, and we must fix that.
First is the toggle button, .navbar-toggle
, in the navigation bar. It is actually appearing, but with a really bad colorization. Let's fix that with some CSS:
.navbar-toggle { border-color: #252830; background-color: #e5e9ec; margin-top: 13px } .navbar-toggle .icon-bar { background-color: #252830; }
The toggle button should appear like what is shown in the next screenshot, now using gray colors:

As you can see, there are many other things that we can do to improve the visualization in mobiles and small viewports. We will fix all that in the next chapters while adding some more cool effects. Wait and you will see!
In this chapter, we started another example—the dashboard web application.
At first, it may appear a little difficult, but we are breaking down every line of code to explain it while using the top of the methodologies for frontend development.
This time, we have an initial design that we aim to create. This is cool because we do have a guideline on what we must do towards our final goal. Usually, when working in a project, you have this kind of scenario.
First, we created another navigation bar, this one being a little more complicated, using a fluid container. The rest of the navigation was made using almost the same methodology that we used when learning about this Bootstrap component.
On the left-hand-side menu, we customized the Bootstrap stacked navigation component, and you learned how to use the Bootstrap collapse plugin.
In the main content, we started to import external plugins to create nice charts for our dashboard. Also, we used the flex display to increase responsiveness, while using the best of CSS.
Finally, we created a loading element and fixed the first issue regarding viewports. Let's continue fixing this in the upcoming chapters.
Congratulations! The first chapter of the final example is nailed! I am pretty sure that you were able to understand the development concepts and how Bootstrap greatly increases our productivity.
In the next chapter, we will continue the construction of the dashboard—moreover, the main content—adding more external plugins and cards using Bootstrap components. We will also fix known issues for different viewports and explain the remaining Bootstrap plugins.
The last chapter was tough! Although the dashboard is not ready yet, following our layout, we must create three more cards in the main, while fixing issues regarding visualization for multiple viewports. After that, we will move on to creating more components for our dashboard. Let's proceed towards this new challenge!
In this chapter, we will cover the following topics:
- A custom checkbox
- External plugin integration
- Advanced Bootstrap media queries
- The viewport's advanced adjustments
- The Bootstrap Carousel plugin
- The Bootstrap Scrollspy plugin
Taking a look at our layout, we must create three more cards. The first of them is the hardest one, so let's face it!
The following .card
is composed of an area chart with two series and some iOS-styled checkboxes. This screenshot reminds us of what the card must look like:

For the chart area, we will again use the highcharts library, while for the checkbox, we will use a plugin called switchery (https://github.com/abpetkov/switchery). After we've considered the documentation, let's create the following HTML:
<div class="card" id="ration-stock"> <div class="card-block"> <h2>Ration stock info</h2> <div class="stacked-area"></div> <div class="switch"> View main stocks <input type="checkbox" class="swithcery" checked /> <div class="clearfix"></div> </div> <div class="switch"> Hide empty stocks <input type="checkbox" class="swithcery" /> <div class="clearfix"></div> </div> </div> </div>
Breaking the code down, to create the chart, we just have to set the div.stacked-area
element. For the checkbox, we must create an input with type="checkbox"
and the .switchery
class to identify it.
Load the CSS of switchery in <head>
, after the Bootstrap CSS:
<link rel="stylesheet" href="css/switchery.min.css">
Also, in the HTML, import the switchery
library in the bottom part that contains the JavaScript loads:
<script src="js/switchery.min.js"></script>
We do not need much CSS here, since most of it will be created by JavaScript. So, just add the following rules to specify the height of the chart and the font style for the checkbox text:
#ration-stock .stacked-area { height: 200px; } #ration-stock .switch { font-weight: 300; color: #8b91a0; padding: 0.5rem 0; } #ration-stock .switchery { float: right; }
The JavaScript contains the core portion of this card. First, let's initialize the switchery plugin. In main.js
, inside the .ready
function, add these lines:
var elems, switcheryOpts; elems = Array.prototype.slice.call(document.querySelectorAll('.switchery')); switcheryOpts = { color: '#1bc98e' }; elems.forEach(function(el) { var switchery = new Switchery(el, switcheryOpts); });
In elems
, we store the elements that contain the .switchery
class. This plugin does not use jQuery, so we must create a query using native JavaScript. The query needed to select the elements follows the one provided in the documentation, and I recommend that you check it out for further information, since this is not the main focus of the book.
The query is performed by document.querySelectorAll('.switchery')
. Array
is a global JavaScript object used to create high-level list objects present in most recent browsers.
The slice
function chops the array using a shallow copy into another array. In summary, we are getting an array of elements with the .switchery
class.
Next, we set the options for the plugin, in this case just the background color, using the color
property in the switcheryOpts
variable. Finally, we start each Switchery
object inside the forEach
loop.
Refresh the web page and the new card should appear as what is shown in the following screenshot:

To create the next card, we will use the Bootstrap progress bar component, labels, and badges. This card represents some kind of real-time information, and we will create it using the progress bar and make it animated through JavaScript.
First, let's create this new card identified by #real-time
in the HTML. Place the code after the last card, #ration-stock
:
<div class="card" id="real-time"> <div class="card-block"> <h2>Real time information</h2> </div> </div>
After <h2>
, we must create a list containing each item of the information. A label, a badge, a progress bar, and a piece of sample text compose the list. Create it like the highlighted HTML code shown here:
<div class="card" id="real-time"> <div class="card-block"> <h2>Real time information</h2> <ul class="list-unstyled"> <li> Active dogs: <span class="label label-warning pull-right">255</span> </li> <li> Silo status: <span class="badge ok pull-right"> <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> </span> </li> <li> Usage level: <div class="progress"> <div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100" style="width: 25%"> <span class="sr-only">25%</span> </div> <div class="progress-bar progress-bar-warning progress-bar-striped active" role="progressbar" aria-valuenow="38" aria-valuemin="0" aria-valuemax="100" style="width: 38%"> <span class="sr-only">38% alocated</span> </div> <div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="5" aria-valuemin="0" aria-valuemax="100" style="width: 5%"> <span class="sr-only">5% reserved</span> </div> </div> </li> <li> Free space: <span id="free-space" class="pull-right"> 32% </span> </li> </ul> </div> </div>
Because we are mostly using only Bootstrap elements and components, we do not need too much CSS but just the following:
#real-time li { font-size: 1.8rem; font-weight: 300; border-bottom: 0.1rem solid #e5e9ec; padding: 0.5rem 0; } #real-time .badge.ok { background-color: #1bc98e; } #real-time .badge span, #real-time .label { color: #FFF; } #real-time .badge, #real-time .label { margin-top: 0.25rem; }
This CSS will change the font size of the text in the card and the borders from one to another item in the list. Also, for the badge and the labels, we've customized the colors and margins.
Refresh the page and it should look like this:

The new card looks nice! Now let's create some CSS to animate it. Let's change the free space percentage periodically. To do this, create the following JavaScript function:
changeMultiplier = 0.2; window.setInterval(function() { var freeSpacePercentage; freeSpacePercentage = $('#free-space').text(); freeSpacePercentage = parseFloat(freeSpacePercentage); delta = changeMultiplier * (Math.random() < 0.5 ? -1.0 : 1.0); freeSpacePercentage = freeSpacePercentage + freeSpacePercentage * delta; freeSpacePercentage = parseInt(freeSpacePercentage); $('#free-space').text(freeSpacePercentage + '%'); }, 2000);
With this JavaScript code, we are executing a function every 2 seconds. We did this because of the usage of the setInterval
function, and we call it every 2,000 ms (or 2 seconds).
What is done first is just a parse of the text inside the #free-space
percentage element. Then we create a delta that could be 20 percent positive or negative, randomly generated by using the changeMultiplier
parameter.
Finally, we multiply the delta by the current value and update the value in the element. To update the value in the element, we use the .text()
function from jQuery. This function sets the content for the element to the specified text passed as a parameter; in this case, it's the percentage change in freeSpacePercentage
that we randomly generated.
Refresh the page and see the number update every 2 seconds.
The last card in the main content is another plot, this time a pie chart. Just like the last charts, let's again use the Highcharts library. Remember that we must first create a simple HTML card, placed after the last #real-time
card:
<div class="card" id="daily-usage"> <div class="card-block"> <h2>Daily usage</h2> <div class="area-chart"></div> </div> </div>
In the CSS, just set the height of the plot:
#daily-usage .area-chart { height: 200px; }
To complete it—the most important part for this card—create the function calls in the JavaScript:
$('#daily-usage .area-chart').highcharts({ title: { text: '', }, tooltip: { pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>' }, plotOptions: { pie: { dataLabels: { enabled: true, style: { fontWeight: '300' } } } }, series: [{ type: 'pie', name: 'Time share', data: [ ['Front yard', 10.38], ['Closet', 26.33], ['Swim pool', 51.03], ['Like a boss', 4.77], ['Barking', 3.93] ] }] });
As you can see in the preceding code, we set the graph to be of the pie
type and create the share for each segment in the data
array.
The following screenshot shows how the last card must be displayed on the web browser:

And we are done! The main page of the dashboard is complete. Now let's proceed to the next pages in this component.
If you resize the dashboard to a mobile visualization (treated as an extra-small viewport in Bootstrap,) you should see some problems with the elements that are not appearing correctly. As shown in the next screenshot, note that the search appears and the card with the round chart is completely unaligned.
In this visualization mode, we are using the viewport of iPhone 6 in portrait orientation in the Chrome developer inspector:

Regarding the search bar, it will be better if this bar appears just when required, for example, when clicking on a button. So, next to the refresh button, let's create another icon to toggle the search bar.
The HTML for this section must be like the following code:
<div class="col-sm-3 top-left-menu"> <div class="navbar-header"> <a class="navbar-brand" href="dashboard.html"> <h1>dashboard</h1> </a> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#nav-menu" aria-expanded="false"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> </div> <a href="#" id="search-icon" data-toggle="tooltip" data-placement="bottom" data-delay="500" title="Display search bar" class="header-buttons pull-right visible-xs"> <span class="glyphicon glyphicon-search" aria-hidden="true"></span> </a> <a href="#" data-toggle="tooltip" data-placement="bottom" data-delay="500" title="Refresh data" class="header-buttons pull-right"> <span class="glyphicon glyphicon-repeat" aria-hidden="true"></span> </a> </div>
Let's discuss this code. First, we made a change in the class name. The link in the refresh icon was a .header-refresh
. Now, since we have multiple header buttons, we changed it to a .header-button
class for generalization.
We also added the Bootstrap tooltip for this button, just as we did for the refresh icon, displaying the message: "Display search bar"
.
To complete the changes, replace the class names in the CSS as well:
nav .header-buttons {
margin-left: auto;
color: #FFF;
}
Then the header should look like this:

Now we have to fix the search bar. Let's change the classes on the form#search
. Replace the classes from .hidden-sm.col-md-3
to just .col-sm-3
for better visualization.
Now, let's hide the form using a media query in CSS for extra small viewports:
@media(max-width:48em){ form#search { display: none; } }
To toggle the visualization of the search input, let's add some JavaScript events. The first one is for opening the search when we click on the magnifier icon at the header, identified by #search-icon
. So in our main.js
file, we add the following function:
$('#search-icon').on('click', function(e) { e.preventDefault(); $('form#search').slideDown('fast'); $('form#search input:first').focus(); });
What this will do first is prevent the default click action with the e.preventDefault()
caller. Then, we use the .slideDown
function from jQuery, which slides down an element. In this case, it will toggle form#search
.
After toggling the form, we add focus to the input, which will open the keyboard if we are accessing the page from a mobile phone.
To increment that, it would be nice if the search bar can hide when the user blurs the focus on the search input. To do this, add the following event handler to the JavaScript:
$('form#search input').on('blur', function(e) { if($('#search-icon').is(':visible')) { $('form#search').slideUp('fast'); } });
What we are doing here is using the blur
event, which is triggered whenever the element loses the focus. The trigger performs a check to find out whether the #search-icon
is visible, meaning that we are in the extra small viewport, and then hides the search bar using the slideUp
function, doing the opposite of what the slideDown
function does.
Click on the collapse toggle navigation (the hamburger button) and you will see how the #nav-menu
looks so messy, as shown in the next screenshot. We must fix it just like the way we did in the last web application example:

To do this, we will first need to remove the .pull-right
class from #nav-menu
. The .pull-*
classes add a float to the element by applying the !important
flag, which cannot be overridden. In this case, we must override this style rule to remove the .pull-right
class and add the float to the current element style rule:
#nav-menu { float: right; }
Create a media query for extra small devices for #nav-menu
and remove the float: right
:
@media(max-width:48em){ #nav-menu { float: none; } }
After that, we must hide #nav-profile
and move its button to the #nav-menu
list. First, add the .hidden-xs
class to the profile element:
<div id="nav-profile" class="btn-group pull-right hidden-xs"> … </div>
This will prevent the element from appearing for extra small devices using the Bootstrap viewport helper class. Then, in #nav-menu > ul
, append the options that were in the #nav-profile
drop-down button:
<div id="nav-menu" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li>…</li> <li class="visible-xs"> <a href="#">Profile</a> </li> <li class="visible-xs"> <a href="settings.html">Setting</a> </li> <li class="visible-xs"> <a href="#">Logout</a> </li> </ul> </div>
Note that we make this new item list visible only for extra small viewports with the .visible-xs
class.
These new item lists must now look just like the notification one, already present in this list. So, append the selector of the new item list to the current CSS style of #btn-notification
:
#btn-notifications .btn-link,
#nav-menu li a {
padding-top: 1.5rem;
color: #252830;
font-weight: 500;
}
The opened list should look like this:

Now, try to change the viewport and see how the elements on the header correctly change its visualization. The #nav-profile
will appear only for small-to-large viewports and will shrink into #nav-menu ul
in a small visualization for extra small viewports.
If you click on the notification list to open it, you will see three problems: firstly, the badge holding the number of new notifications jumps to the right portion; then the notification button is not filling the entire width; and finally, the notification list can appear a little nicer when opened.
To fix the jumping badge on the notification button, just add the following CSS:
@media(max-width:48em){ #nav-menu #btn-notifications > .badge { right: inherit; left: 10rem; } }
Note that we use a media query to change the position of the badge for extra small viewports only.
To modify the notification button's width, we have to create a media query as well. So, add this CSS style to it:
@media(max-width:48em){ #btn-notifications, #btn-notifications > button { width: 100%; text-align: left; } }
This style will change the width for both the notification button dropdown and the button itself.
Finally, the style for the notification list must be changed. We create the next CSS rule in our main.