Bootstrap is a UI Framework initially created by Mark Otto and Jacob Thornton at Twitter. It is an amazing source of styles, icons, and behaviors, abstracted to define and enrich components. Bootstrap offers an easy, rational, and unified set of patterns for defining styles. It had no equivalent before. If you have never used it, you will be excited to get so much visual feedback from a quick definition of the DOM.
In June 2014 it was the number 1 project on GitHub with over 73,000 stars and more than 27,000 forks. Their documentation is very fluid and easy to go through.
In this recipe, we will use Bootstrap to set up the web-design basics for our CloudStreet Market project from an existing Bootstrap theme. We will remake the index.jsp
page to render a better looking welcome page that can be previewed with the following screenshot.
There are three major steps in this recipe:
From the Git Perspective in Eclipse, checkout the latest version of the branch v2.x.x
:
chapter_2
directory, you can find a freeme.zip
archive. It is a responsive Bootstrap template downloadable for free. This zip comes from the bootstrapmaster.com website.css
directory, a js
directory, an img
directory, and finally an index.html
file. Opening the index.html
file with a web browser should render the following home page:We are using this template as a base for the webapp module.
freeme/js
directory have been copied over to the /cloudstreetmarket-webapp/src/main/webapp/js
directory.freeme/css
directory have been copied over to the /cloudstreetmarket-webapp/src/main/webapp/css
directory.freeme/img
have been copied over to the /cloudstreetmarket-webapp/src/main/webapp/img
directory.freeme/index.html
file has been copied and pasted into the /cloudstreetmarket-webapp/src/main/webapp/WEB-INF/jsp/index.jsp
file, as UTF-8.freeme/licence.txt
has been copied and pasted to the /cloudstreetmarket-webapp/src/main/webapp/WEB-INF/jsp
directory.http://localhost:8080/portal/index
with a web browser displayed exactly the same visual you saw earlier, but served by our application.We will detail in this section what has been done in order to adapt the downloaded template to our use case.
cloudstreetmarket-webappsrcmainwebappimglogos
have been removed and replaced with six new images representing brands of technical products that we have been using through out this application and this book.index.jsp
file located in the cloudstreetmarket-webapp
module has been implemented the following changes:<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page isELIgnored="false" %>
<!-- start: Meta -->
section has been replaced with the following:<!-- start: Meta --> <meta charset="utf-8"> <title>Spring MVC: CloudST Market</title> <meta name="description" content="Spring MVC CookBook: Cloud Street Market"/> <meta name="keywords" content="spring mvc, cookbook, packt publishing, microservices, angular.js" /> <meta name="author" content="Your name"/> <!-- end: Meta -->
<!--start: Logo -->
section has been replaced with the following:<!--start: Logo --> <div class="logo span4"> CLOUD<span class="sub">ST</span><span>Market</span> </div> <!--end: Logo -->
<ul class="nav"> <li class="active"><a href="index">Home</a></li> <li><a href="markets">Prices and markets</a></li> <li><a href="community">Community</a></li> <li><a href="sources">Sources</a></li> <li><a href="about">About</a></li> <li><a href="contact">Contact</a></li> </ul>
<!-- start: Hero Unit -->
and <!-- start: Flexslider -->
sections have been removed and <div class="row">
coming after the navigation menu (<!--end: Navigation-->
) has been emptied:<!-- start: Row --> <div class="row"></div> <!-- end: Row -->
<!-- start: Row -->
section to the <!-- end: Row -->
section, which is located after the <!-- end Clients List -->
, has been removed along with the <hr>
just after it.<!-- start: Footer Menu -->
to <!-- end: Footer Menu -->
has been replaced with the following content:<!-- start: Footer Menu --> <div id="footer-menu" class="hidden-tablet hidden-phone"> <!-- start: Container --> <div class="container"> <!-- start: Row --> <div class="row"> <!-- start: Footer Menu Logo --> <div class="span1"> <div class="logoSmall">CLOUD<span class="sub">ST</span><span>M!</span> </div> </div> <!-- end: Footer Menu Logo --> <!-- start: Footer Menu Links--> <div class="span10" > <div id="footer-menu-links"> <ul id="footer-nav" style="margin-left:35pt;"> <li><a href="index">Home</a></li> <li><a href="markets">Prices and markets</a></li> <li><a href="community">Community</a></li> <li><a href="sources">Sources</a></li> <li><a href="about">About</a></li> <li><a href="contact">Contact</a></li> </ul> </div> </div> <!-- end: Footer Menu Links--> <!-- start: Footer Menu Back To Top --> <div class="span1"> <div id="footer-menu-back-to-top"> <a href="#"></a> </div> </div> <!-- end: Footer Menu Back To Top --> </div> <!-- end: Row --> </div> <!-- end: Container --> </div> <!-- end: Footer Menu -->
<!-- start: Photo Stream -->
to <!-- end: Photo Stream -->
has been replaced with:<!-- start: Leaderboard --> <div class="span3"> <h3>Leaderboard</h3> <div class="flickr-widget"> <script type="text/javascript" src=""></script> <div class="clear"></div> </div> </div> <!-- end: Leaderboard -->
index.jsp
file, the copyright section has been adapted.cloudstreetmarket-webapp/src/main/webapp/css/style.css
file, the following classes have been added:.logo{ font-family: 'Droid Sans'; font-size: 24pt; color: #666; width:157pt; font-weight:bold; margin-top:18pt; margin-left:10pt; height:30pt; } .logo span{ position:relative;float:right; margin-top: 3pt; font-weight:normal; font-family: 'Boogaloo'; font- style:italic; color: #89C236; padding-right: 3pt; } .logo .sub { vertical-align: super; font-style:normal;font-size: 16pt; font-family: 'Droid Sans'; font-weight:bold; position: absolute; color: #888; margin:-4pt 0 -4pt 0; } .logoSmall{ font-family: 'Droid Sans'; font-size: 16pt; color: #888;width:80pt; font-weight:bold; margin-top:10pt;height:20pt; margin-right:30pt; } .logoSmall span{ position:relative; float:right; margin-top: 3pt; font-weight:normal;font-family: 'Boogaloo'; font-style:italic;color: #89C236; } .logoSmall .sub { vertical-align: super; font-style:normal; font-size: 10pt;font-family: 'Droid Sans';font-weight:bold;position: absolute; color: #666;margin:-2pt 0 -4pt 0; }
http://localhost:8080/portal/index
resulted in the following state:We will focus in this section on the changes that have been made to fill the welcome page with responsive content. By responsive, understand that the content will be rendered under a style appropriate for the device size and orientation.
index.jsp
file:<div class="row">
has been added the following content:<div class='span12'> <div class="hero-unit hidden-phone"><p>Welcome to CloudStreet Market, the educational platform.</p></div> </div> <div class='span5'> <div id='landingGraphContainer'></div> <div id='tableMarketPrices'> <table class="table table-hover table-condensed table-bordered table-striped"> <thead> <tr> <th>Index</th> <th>Value</th> <th>Change</th> </tr> </thead> <tbody> <tr> <td>Dow Jones-IA</td><td>17,634.74</td> <td class='text-success'><b>-18.05</b></td> </tr> ... <tr> <td>FTSE MIB</td><td>18,965.41</td> <td class='text-error'><b>-182.86</b></td> </tr> ... </tbody> </table> </div> </div> <div id="containerCommunity" class='span7'> <div id="divRss3"></div> </div>
In the previously added landingGraphContainer, we have inserted a generated graph that renders the evolution of specific markets during the last opened day. The graph uses the morris.js
library (http://morrisjs.github.io/morris.js), which also relies on the raphael.js
library (https://cdnjs.com/libraries/raphael).
<!-- start: Java Script -->
section to the <!-- end: Java Script -->
section has been added the following content:<script src="js/jquery-1.8.2.js"></script> <script src="js/bootstrap.js"></script> <script src="js/flexslider.js"></script> <script src="js/carousel.js"></script> <script def src="js/custom.js"></script> <script src="js/FeedEk.js"></script> <script src="js/raphael.js"></script> <script src="js/morris.min.js"></script> <script> $(function () { var financial_data = [ {"period": "08:00", "index": 66},{"period": "09:00", "index": 62}, {"period": "10:00", "index": 61},{"period": "11:00", "index": 66}, {"period": "12:00", "index": 67},{"period": "13:00", "index": 68}, {"period": "14:00", "index": 62},{"period": "15:00", "index": 61}, {"period": "16:00", "index": 61},{"period": "17:00", "index": 54} ]; Morris.Line({ element: 'landingGraphContainer', hideHover: 'auto', data: financial_data, ymax: 70, ymin: 50, pointSize: 3, hideHover:'always', xkey: 'period', xLabels: 'month', ykeys: ['index'], postUnits: '', parseTime: false, labels: ['Index'], resize: true, smooth: false, lineColors: ['#A52A2A'] }); }); </script>
cloudstreetmarket-webappsrcmainwebappjs
directory, the morris.min.js
and raphael.js
libraries have been copied and pasted from their respective websites.index.jsp
file:<div id='containerCommunity'>
has been filled with the following content:<div id="divRss3"> <ul class="feedEkList"> <li> <div class="itemTitle"> <div class="listUserIco"> <img src='img/young- lad.jpg'> </div> <span class="ico-white ico-up-arrow listActionIco actionBuy"></span> <a href="#">happyFace8</a> buys 6 <a href="#">NXT.L</a> at $3.00 <p class="itemDate">15/11/2014 11:12 AM</p> </div> </li> <li> <div class="itemTitle"> <div class="ico-user listUserIco"></div> <span class="ico-white ico-down-arrow listActionIco actionSell"></span> <a href="#">actionMan9</a> sells 6 <a href="#">CCH.L</a> at $12.00 <p class="itemDate">15/11/2014 10:46 AM</p> </div> </li> ... </ul> </div>
cloudstreetmarket-webappsrcmainwebappjs
directory includes the FeedEk.js
file related to the feedEk jQuery plugin. This plugin can be found online (http://jquery-plugins.net/FeedEk/FeedEk.html).cloudstreetmarket-webappsrcmainwebappcss
directory also has the related FeedEk.css
file.index.jsp
, under the <!-- start: CSS -->
comment, the FeedEk css
document has been added: <link href="css/FeedEk.css" rel="stylesheet">
style.css
file, before the first media query definition (@media only screen and (min-width: 960px)
), the following style definitions have been added:.listUserIco { background-color:#bbb; float:left; margin:0 7px 0 0; } .listActionIco { float:right; margin-top:-3px; } .actionSell { background-color:#FC9090; } .actionBuy { background-color:#8CDBA0; } #landingGraphContainer{ height:160px; padding: 0px 13px 0 10px; } .tableMarketPrices{ padding: 13px 13px 0 15px; }
cloudstreetmarket-webappsrcmainwebappimg
.http://localhost:8080/portal/index
. You should observe a responsive and adaptive style as in the following picture:To understand our Bootstrap deployment, we are going to review now how it has been installed as a predesigned theme. We will then discover some key features of the Bootstrap Framework—not only the implemented features because, logically enough, only a few features of the Framework can visually be used on one single page example.
The theme we have obtained is no more than a classical static theme, as you can find thousands of them over the Internet. They are made by web designers and distributed for free or commercially. This one is made with the basic structure of HTML files, a JS directory, a CSS directory, and an IMG directory.
The theme installation is quite straightforward to understand, since we have just placed the JavaScript files, CSS files, and images in their expected locations for our application.
The implemented theme (FreeME) uses Bootstrap 2. We are going to review a couple of features that have been implemented in the template and for the needs of our project.
The Bootstrap scaffolding helps with designing the HTML structure usually built from a grid model. The Bootstrap strategy on this topic is described in the following sections.
Bootstrap offers a styleframe to handle a page-specific grid system. The key point is in the default grid-system made up of 12 columns and designed for a 940px wide nonresponsive container.
The Bootstrap responsive features are activated with the use of <meta name="viewport"…>
tag and with the import of the boostrap-responsive.css
file. The container width can extend from 724px to 1170px in that case.
These Bootstrap specifications define quite a drastic set of constraints but Bootstrap somehow creates an easy-to-understand design uniformity for its implementations.
In the case of our template, the viewport metatag is the following:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
If you are not familiar with this tag, its main purpose is to define device-specific sizes in the document. From these sizes, rules are defined for orientation-specific and device-specific rendering. These rules that are bound to style definitions are called mediaqueries. You can find an example of a mediaquery in the style.css file:
/* Higher than 960 (desktop devices) ================================================================ */ @media only screen and (min-width: 960px) { ... #footer-menu { padding-left: 30px; padding-right: 30px; margin-left: -30px; margin-right: -30px; } ... }
This media query overrides the style that is specific to the id footer menu only where the device presents a width greater than 960px.
To define columns within the grid system, Bootstrap drives us towards the use of a row
div tagged as a row
class element. Then, the idea is to define subdivs marked with custom span*
class elements where the *
characters represents subdivisions of the 12-column grid we have to deal with.
For example, consider the following two possible designs:
The two columns on the left example can be rendered from the DOM definition:
<div class="row"> <div class="span4">...</div> <div class="span8">...</div> </div>
The two columns on the right example can be rendered from the DOM definition:
<div class="row"> <div class="span6">...</div> <div class="span6">...</div> </div>
With this in mind, the grid of our welcome page is actually the following:
Offsetting a column allows you to create a fixed-sized decay corresponding to one or more invisible columns. For example, consider the following snippet:
<div class="row"> <div class="span6">...</div> <div class="span4 offset2">...</div> </div>
This DOM definition will correspond to the following columns:
A column can also be nested inside another column redefining a new row. The sum of the newly created columns must correspond to the parent's size:
<div class="row"> <div class="span6"> <div class="row"> <div class="span2">...</div> <div class="span4">...</div> </div> </div> </div>
Bootstrap also provides a few pre-designed elements such as buttons, icons, tables, forms and also utilities to support typography or images.
Default styled buttons can be created from the <a>
and <button>
tags with only addition of the .btn
class element. The created default gray button with a gradient can then be declined in different colour variations. For example, by default, the following classes combination:
.btn .btn-primary
: This produces an intense ultramarine blue button to identify the primary action among other buttons.btn .btn-info
: This produces a moderate turquoise blue button.btn .btn-success
: This produces a positive green button.btn .btn-warning
: This produces a warning orange button.btn .btn-danger
: This produces a dangerous red button.btn .btn-inverse
: This produces a black button with white text.btn .btn-link
: This produces a link while maintaining a button behaviorThese buttons are also resizable declaratively by adding a .btn-large
class, adding a .btn-small
class, or adding a .btn-mini
class:
A button can be disabled by adding it as a disabled attribute. Similarly, a <a>
tagged button can be disabled with the addition of a .disabled
class. We didn't make use of buttons yet, but it is a great feature to be presented at this point.
Bootstrap 2 comes with an impressive set of 140 dark gray icons available as sprites and provided by Glyphicons:
These icons are normally available commercially but they are also usable for free as part of the Bootstrap product. However Bootstrap asks us to provide an optional backlink to http://glyphicons.com.
All these icons can be pulled from the DOM with a simple class within a <i>
tag such as <i class="icon-search"></i>
.
The amazing thing is that you can actually embed these icons in every suitable Bootstrap component. For example, the button definition: <a class="btn btn-mini" href="#"><i class="icon-star"></i> Star</a>
, produces the following:
We have implemented a Bootstrap table for the market activity overview. We have basically shaped the following table:
<table class="table table-hover table-condensed table-bordered table-striped"> <thead> <tr><th>Index</th> <th>Value</th> <th>Change</th></tr> </thead> <tbody> <tr><td>...</td> <td>...</td> <td>...</td> </tr> </tbody> </table>
In the same way as we can define a button class overridden with customization classes, we have defined a generic Bootstrap table with the class .table
, and then we have made use of the following customization classes:
The framework has other pre-designed elements identified as Components. Among them, dropdowns, button groups, breadcrumbs, pagination, Navbars, labels and badges, thumbnails, alerts, progress bars, and so on. Here we only present some of them:
The Bootstrap navigation bars provide support for a basic navigation menu. They are not by default fixed to the top of the page; they must be included in a .container
. The code is as follows:
<div class="navbar navbar-inverse"> <div class="navbar-inner"> ... <ul class="nav"> <li class="active"><a href="index">Home</a></li> <li><a href="markets">Prices and markets</a></li> <li><a href="community">Community</a></li> <li><a href="sources">Sources</a></li> <li><a href="about">About</a></li> <li><a href="contact">Contact</a></li> </ul> ...
The most basic feature in the navbar is the activable link:
The example above can be designed from the following DOM definition:
<ul class="nav"> <li class="active"><a href="#">Home</a></li> <li><a href="#">Link</a></li> </ul>
We strongly recommend reading the Bootstrap documentation. More details can be found on how to implement other features. For example, Bootstrap provides tools for:
.navbar-fixed-top
), fixed-to-bottom (with .navbar-fixed-bottom
), at the opposite of the full-width navbar that scrolls away with the page (with .navbar-static-top
)..nav-collapse.collapse
) that allow significant space savings. With the use of the data-toggle HTML5 attribute, dynamic handling is performed with no extra JavaScript configuration.There was a hero unit defined in the provided template. We've just moved it a bit to suit our responsive needs.
It is a lightweight, flexible component to showcase key content on your site.
The example above can be designed from the following DOM definition:
<div class="hero-unit"><p>Welcome to CloudStreet Market, the educational platform.</p></div>
Bootstrap alerts are great to quickly generate a predefined style for a warning message or another contextual message. A Bootstrap alert comes with an optional dismiss button (which will hide the alert with no extraJavaScript configuration). The code is as follows:
<div class="alert"> <button type="button" class="close" data-dismiss="alert">×</button> <strong>Warning!</strong> Best check yo self, you're not looking too good. </div>
This definition produces the output presented here:
An Alert is defined with the class .alert
on a <div>
tag , from which contextual color variations can be set up, providing extra overriding classes such as .alert-success
, .alert-info
, or .alert-error
.
Bootstrap labels are very nice for enriching content. They render particularly well in list or in tables. Find here an overview of the possible contextual variations:
The labels here would be defined with:
<span class="label">Default</span> <span class="label label-success">Success</span> <span class="label label-important">Important</span> …
The badges would be defined with:
<span class="badge">1</span> <span class="badge badge-warning">4</span> <span class="badge badge-important">6</span> …
There is much more to Bootstrap than this tiny overview for enriching official documentation. Again, the official documentation is very well done and very comprehensible.
Visit http://getbootstrap.com for the documentation related to the latest supported version of the framework. Go to http://getbootstrap.com/2.3.2 for the documentation related to the version we use in our project.
We will implement more features in the coming chapters and care will be taken to highlight them wherever possible.
If you like Bootstrap and feel you want to use it in your projects, you must consider Version 3.
bootstrap.js
and bootstrap.css
files (there is no more bootstrap-responsive.js
or bootstrap-responsive.css
). It is now possible to drive media-query duties directly from the DOM using a set of new device-specific classes.