A great call-to-action will make all the difference in your portfolio site. Why not use a fancy button?
In the parent element of the jumbotron, add .text-center.
Now is a great time to talk about the grid system.
A portfolio is the place to showcase your most valuable work. So, you want to make it visible to a wide audience and on all devices.
For that, we need a responsive and flexible layout that can work across all devices, from large screens to smartphones.
The grid system is mobile first, fluid and responsive.
You can then complete the grid layout by adding columns.
It can be a number between 1 and 12.
The expected result is 3 paragraphs on 1 row.
We are only targeting the desktop and large screens for the moment.
Let ‘s do the same for the projects portfolio section, where we will add images.
We are only targeting the desktop and large screen for the moment. So, we add 4 divs and .col-md-3
We are getting closer to finalizing the projects gallery. We are just missing images.
Or, feel free to use your own assets. This is your portfolio, after all.
In total, we have 2 rows and 8 image thumbnails.
We will complete the design layout with the footer.
We have 2 paragraphs and we want the 2 on the opposite sides of the screen. This can be done with a 2-column layout.
6 and 6 add up to 12 columns, which will be the full width of the 12-column grid.
- Finally, we re-align each paragraph with .text-left and .text-right like so:

We are almost done with the footer. Next, we are adding a label and a glyphicon.
Labels
The page was designed with Bootstrap v.3.3.5 and we want to highlight it with a label. It works like the button with a common class .label and modifier class to add the styling and a color.
- Wrap Bootstrap v.3.3.5 within
<span>
tags
- Add the common class .label to the opening
<span>
tag
- Choose a modifier class to add color.
We will add .label-primary
<span class="label label-primary">Bootstrap (v3.3.5)</span>

Glyphicons
Glyphicons are free to use with the Bootstrap resources.
Every glyph has a common class .glyphicon, then another class specific to the glyphicon selected.
We are going to use glyphicon-heart to display Designed with 
- Inside the second
<p>
, add a <span>
- Inside the
<span>
, use the class .glyphicon and .glyphicon-heart like so:
<span class=" glyphicon glyphicon-heart" aria-hidden="true">

The role of glyphicons is purely decorative, so to hide them from assistive devices (screen readers) we add the attribute aria-hidden=”true”
Here you go:

Good job!
Next, we’re going to take another step further into the Bootstrap learning experience with the JavaScript plugins.
Javascript plugins made easy!
Knowing some JavaScript will be enough to get you up and running with making your site interactive, and with the help of Bootstrap. Here’s how:
- We will start with carousel.js to create a slideshow and display customers’ testimonials
- Next, we will add a modal. This is like a small window popping up on a click event
- Lastly, scrollspy.js: another plugin that comes with the power of updating the active state of a menu link based on the scroll position of a webpage. (See the example with scrollspy.)
Even if it seems like a challenge, you can be assured that it’s not.
Carousel.js
Below the projects gallery, we have included a testimonials section so visitors can read through reviews left by satisfied customers.
Given the great amount of content possible, displaying 4 or 5 testimonials could use up a lot of real estate. Therefore, we will include a carousel to allow visitors to slide through testimonials one after another instead of scrolling down the page. Real smooth!
So, let’s build a slideshow of testimonials.
To build the slideshow, we will use:
Testimonials Slideshow
- Copy the first markup example available on the documentation

- Inside
<div id=”testimonials”>
, add the carousel markup.
- You can get rid of the indicators.
- We only keep the wrapper for slides and the controls.

Try it now!
You will see the structure of the carousel with 2 controls (left and right arrows) on each side. There is no content for now.
Next, we will add the content: the testimonials.
Media Object
Inside each .item slide, we add a media object.
- Copy the code example available in the documentation and paste directly inside the .item.

- Get rid of the
<div>
and <img>
tags of the .item slide
- And, replace them with the media object code snippet.

To complete the markup of the media object, simply add:
- the image source: images/testimonials/…
- lorem ipsum within the .media-body
To adjust the layout, wrap each media object in a column with .col-md-8 and .col-md-offset-2
This is the final markup below:

What about .col-md-offset? Well, we have not covered it yet.
Offsetting columns works in combination with the grid system classes. It allows you to move columns to the right by increasing the left margin.
It works much like the grid classes.
- The prefix is to target the viewport size. col-md-offset
- The suffix number, between 1 and 11, indicates by how much you want to move the columns further to the right.
See the difference for yourself with or without .col-md-offset-2.
Image shapes
We will finish with some images. Images can be styled easily with image shape.
Which one do you want?
- Img-rounded
- Img-circle
- Img-thumbnails
Add .img-circle to the <img>
tag like so:
<img class="media-object img-circle" src="images/testimonials/male-client2.png" alt="image">
We now repeat the process from the top to have 3 (or more) slides in total.
- Add an .item slide
- Add a .container
- Include a .row and 8 columns with .col-md-8
- And, offset by 2 columns with .col-md-offset-2
- Add the media object markup.
- Finally, change the image shape with .img-circle
That’s it! Now visitors can enjoy cycling and reading through your clients’ testimonials. What a treat!
Pop-up Modal
The Modal plugin is like a dialog box or a pop up window used to display information to visitors.
We will add a modal to the jumbotron section. You remember – with the call-to-action button, right?
Clicking the button will make a window pop up to display… well, we won’t tell you right now.

For now, we will show you how to create a modal via data-attributes.
2-step process
On the bootstrap documentation, let’s head over to the javascript section and select modal.js to see how the markup looks:
We first need a trigger button.
data-target and data- toggle are data-attributes that you embed inside your markup to bind the HTML elements with javascript.
Example:
<a class="btn btn-warning btn-lg" href="#" data-toggle="modal" data-target="#contactMe" href="#"Contact Me </a>
In the jumbotron:
- Inside the button element is where we add data-target=”#contactMe” and data-toggle=”modal”. This is the trigger button.
Change the text to “Contact Me!”.
<p>
<a class="btn btn-warning btn-lg" href="#" data-toggle="modal" data-target="#contactMe" href="#" role="button"> Contact Me </a>
</p>
Next, there is the modal element.
It has 3 primary sections:
- A modal-header
- A modal-body
- A modal-footer
We have already made the modal element available in the project with our own markup.
In the source code, this modal structure is invisible until triggered with a click event.
- The modal element has a unique identifier id=”contactMe”.

Very important: the data-target and the identifier must match. So, remember to update the data-target=”#contactMe” inside the trigger button, to match the id=”contactMe” in the modal.
Try it now!
When you click on “Contact Me”, the button will fire off the modal dialog and display… surprise! A contact form:

Inside the .modal-body, we have added a contact form. You can also include:
- A video
- An image
- Or, remote content
We will make a detour to the CSS section to explain how to set up a contact form.
Contact Form Modal
This is a great example of a pre-styled and enhanced HTML element. Form elements are ready to use with no extra styling required.
Here is how we did it:
The form documentation includes code examples and snippets that make the process straightforward.
- We have pasted the HTML form code snippet inside the .modal-body
- And, we have kept just what we need:
– fields for the name and an email address
– and, a textarea for the message.
- Each label and input is wrapped in a .form-group
The for and id attributes must always match to allow autofocus.
Forms add-ons and variations include:
- Static Control
- Focus, disabled and readonly State
- Help text
- And, control sizing
We will look at the 2 last ones: help text and control sizing.
A help text is extra information to the user.
- Below the textarea, we add the following code:
<span id="helpBlock" class="help-block">250 characters maximum</span>

(optional) Add the attribute aria-describedby=”helpBlock” inside the associated input or textarea for assistive technologies such as screen readers.
Control sizing is made possible with super helpful classes like .input-lg and .input-sm
Try .input-lg inside each input to see how it renders.
<div class="form-group">
<label for="sender-name" class="control-label input-lg">Name:</label>
<input type="text" class="form-control input-lg" id="sender-name">
</div>
List-inline
Below the submit button, we have added an additional modal-footer to include a list of social media links.
<li>
are, by default, block-level elements, meaning each will use one line.
In order to display the social media links on one single line, we use .list-inline like this:
<ul class="list-inline">

This will result in an inline list like below, when the modal dialog opens up:

Changing the modal size
The modal comes in 2 sizes: large and small.
- In your markup, add the modifier .modal-lg next to .modal-dialog. This will make the modal bigger.
<div class="modal-dialog modal-lg" role="document">

Conversely, .modal-sm gives you a small modal.
<div class="modal-dialog modal-sm" role="document">
Try it!
Scrollspy navigation
The scrollspy plugin watches for position change on a webpage to automatically update the active state of the navigation links.
It means literally what it’s called.
- Spy = it spies on the element to which it is attached
- Scroll = it updates based on the scroll position
We will add the scrollspy behavior to the navigation bar. Just like the modal.js, it requires 2 steps:
- We add the data-attribute data-spy=”scroll” to the element we want to spy. We will add this one to the
<body>
element:
<body data-spy="scroll">
- Inside the body, add data-target:
<body data-spy="scroll" data-target="#menu">

The data-target refers to the element we want to update with the active state. In this case, this is the menu navigation (home, services and projects). This one will have a unique identifier.
Important: both the data-target and the id must match.

Try it now!
When you click a menu link, the page skips to the targeted section and the link automatically updates to active. This is a much better user experience.
Bootstrap can help achieve great results with little to no effort. Look at the portfolio that you just built. Impressive!
Next, we will take your Bootstrap experience to the next level by teaching you how to combine default and custom styling.
Leveraging Bootstrap
Looking at the source code of some websites, it is very common to find properties from Bootstrap. However, you could not guess by just looking at the interface. These sites look nothing like Bootstrap.
Many developers and designers use Bootstrap to get a quick start in their project. Their expertise allows them to fully take advantage of the framework while staying in control of their design.
You can do it too!
We will show you how to do that in a manner that is quick, effective and non-obstructive.
Applying custom styles
In your code editor, open css/style.css. Inside, we have added some global styling.
Below is where you will write your custom style to override the default Bootstrap CSS.

Very important: you never ever want to change the bootstrap files: bootstrap.css or bootstrap.js.
This is recommended practice to keep your custom style and the Bootstrap files separate.
- Your custom style must be in style.css or else.
- And, the bootstrap files remain untouched.
Naturally, you must add your style.css stylesheet in the head section of the index.html, like we did for you.

The goal here is to override the default Bootstrap CSS. To do so, your custom style always comes last. This follows the rule of Cascading Stylesheets, so CSS rules positioned last take precedent.
And, this is how we can start customizing Bootstrap.
Customizing the navbar
The default navbar is easily recognizable. Anyone could guess that your site is a product of Bootstrap. However, you want it to be your portfolio, not just a copy of a Bootstrap template. Time to be original!
We will start by targeting the text links. They look a bit tiny.
And, we will also change the font size.
In style.css, we have already added the corresponding selectors.
- First, we target the .navbar with font-size:20px;
- Second, we make the width of the
<li>
larger.
(style.css)

We also target .navbar-brand in case you should decide to keep a text link in lieu of the bootstrap logo.
Finally, we align the text links with .text-center in the HTML markup

Looks different already.
Styling the banner
For the banner we want to get rid of the jumbotron’s default grey color and display the content on a plain background color. Finally, we increase the font size of the headings.
In order to figure out which CSS rule needs overriding, we must look into the default Bootstrap CSS. We don’t mean for you to open and inspect the bootstrap.css. No! Instead, we will use the inspector tool.
The inspector tool
If you are using Chrome, the inspector tool comes with the web developer tool.
- Click right on the element you want to inspect
- Select inspect element to open the console

- In the console, the left side allows to inspect the DOM (Document Object Model)
- The right side provides you with styling details about the HTML element inspected (highlighted)
Try it yourself! Highlight the jumbotron, click right and select inspect element to open the console.

As seen on the console, the .jumbotron class has the following CSS rules.
We want to override: .jumbotron {background-color: #eee}

(console – right panel)
In style.css, complete the code like so:
.jumbotron { background-color: transparent; }
Once your custom change is applied, you notice that the information on the console has changed.
- Your custom style.css is available first, meaning that it takes precedence over other styles.
- If you scroll down the console a little, you will see that the same selector originating from the bootstrap.min.css is stricken through, meaning that it has been overridden by your custom style.

- If you use Firefox,firebug will help you through the same process.
- Web developer tools for other browsers are listed here.
Font size
As part of the customization, we make the headings bigger with .font70 and .font80.
These rules are available at the top of style.css.
Complete the code like below:
<h1 class='font80' >John Doe</h1>
<h2 class='font70'>Developer & Designer</h2>
Same for the headings of the sections services, projects and testimonials:
<h1 class="font60">Services</h1>
<h1 class="font60">Projects</h1>
<h1 class="font60">Testimonials</h1>
Finally, let’s change the color to something lighter.
.jumbotron {
Background: transparent;
color: #ecf0f1;
}
For the color swatches, we are using flatuicolors.
And, the page customization is now complete.

We told you that it would be effective, non-obstructive and quick!
- Effective: the inspector tool helps find exactly which selector to target.
- Non-obstructive: we allow the bootstrap and custom files to co-exist in a project without interfering with each other. The last file will override the first without altering the original files.Because your site is powered by the framework, you must always have the Bootstrap files in your project. However, removing the custom style will not break your site. You would only lose the custom style.
- And quick: because of the first two!
Mobile First
There are over 3.1 billion mobile web users worldwide. In the U.S. alone, 25% of mobile web users use mobile only. And, the numbers keep growing.
Mobile first is an important concept to consider. As the web landscape becomes increasingly complex, it is becoming even more challenging for developers and designers to create the best universal web experience.
Thankfully, the Bootstrap framework is responsive, flexible and mobile first. It provides great tools and solutions to help build layouts that can gracefully adapt to any device.
Let’s see it in action with a quick demo.
- Try to reduce the size of your browser and watch what happens.
First, the navigation bar is replaced with a square-shaped icon with 3 lines across it.
Clicking the icon will toggle the menu up and down to alternately reveal and hide the menu content.
On a large screen, we see a horizontal menu that turns into a collapsed menu when switching to a small screen. Genius!

This is a great example of adaptive design that Bootstrap can help us achieve with little effort.
However, not everything looks as nice on a small device as on a desktop view.
When you scroll down the page, you may notice a few areas that need improvement.
The pre-defined grid options classes and the responsive utilities will come to the rescue.
In this part, we are about to take it up a notch with more control over how your design renders on multiple devices.
Topics include:
- Mobile first: How it works
- The advanced grid system with multiple-column layouts
- The responsive utilities
- The viewport meta tag
- And, the media queries
Mobile first: How it works
The services section is made of 3 columns. For that, we are using .col-md-4.
You remember the third section’s introduction to the grid system, where we explained that md is short for medium.
- col-md is used to target medium-sized and large screens only.
- Any smaller size will not be targeted, bringing the column size to its default: full-width.
Confused? Let’s clarify with a demo:
- Reduce the size of the screen to see what happens with the services layout.
With the grid system, the default styling is always full-width until overridden with a pre-defined class like .col-md-4.

Full-width looks best on a smaller screen – hence the concept of mobile first. So, we won’t change anything here.
However, if you decide to override mobile first on a tablet, you would use the class .col-sm-4 to target 768px-wide devices and larger.
Let’s try that next.
Advanced grid system: Multi-column layout
The projects gallery displays on 4 columns. That looks nice on desktops and large screens.
What about on a tablet? It looks a bit squished. It would be nice to see 2 images on a row.
With an advanced grid system, it is possible to combine multiple pre-defined grid classes to create a multi-column layout like the example below:
<div class="col-sm-6 col-md-3">
…
</div>
The markup should look like this:

On tablet view, the class .col-sm-6 will limit the number of images to 2 per row, while the number will remain at 4 on a desktop view with .col-md-3.
See below if it makes more sense:
Desktop view

Tablet view – 2 images per row!

Now, going even smaller, like on a smartphone, things start to get a bit cluttered. There is a lot going on. And, we have a lot to scroll down through before reaching the bottom.
To improve the mobile user experience, it is best to keep the content to a minimum and limit the number of images to 4 in total.
How so? By making one row invisible. This is when the responsive utilities come into play.
Responsive utilities
Just like the grid options, responsive utilities allow more flexibility in the responsive layout. Their purpose is to make elements visible or invisible based on breakpoints.
In Responsive Web Design, breakpoints are used to target different devices with specific styling.
Hidden row
To make the second row disappear when we reach the small (<768px) breakpoint, we use .hidden-xs.

And that’s all there is to it!
Testimonials: Adaptive content
Moving on with the responsive utilities, we will adapt the testimonials section to the mobile screen.
On a tablet view, the testimonials carousel looks fine.
On a small device, it’s harder to read.
Inside the section testimonials:
- We add another .container right before the closing tag.
</section><!—testimonial -->
- Inside the .container, we add:
A <h1>
And, a media object (the same that we have inside the carousel) like so:

Now, the goal is to make the content interchangeable and adaptive based on the viewport size.
- .visible-xs makes the content visible on small devices only
- Conversely, .hidden-xs hides the content on small devices
To do so:
We add .hidden-xs to the container with the carousel
<div class="container visible-xs">
And, we add .visible-xs to the second container without the carousel
<div class="container hidden-xs">
Then, the web content adapts as the viewport changes size.
Now try it in your browser
On medium to large screens, we can slide through testimonials. Then, the slideshow gets replaced by static content when we reach the smaller breakpoint.
Interchangeable Headings
We are purposely making the heading bigger. However, this may not suit the mobile display. Too big!

The idea is to duplicate headings in the markup and to alternately display them as the screen size decreases.
- In the banner, update the code like this:
<h1 class='font80 hidden-xs'>John Doe</h1>
<h2 class='font70 hidden-xs'>Developer & Designer</h2>
(Duplicate: will show on small screens only):
<h1 class='visible-xs'>John Doe</h1>
<h2 class='visible-xs'>Developer & Designer</h2>
- The first headings will display on screens of 768px and larger
- The second set of headings (duplicate) will show on smaller screens with a regular font size: 36px.
Repeat the process for each section:
- Services
- Projects
- Testimonials
Example:
<h1 class='font60 hidden-xs'>Services</h1>
<h1 class='visible-xs'>Services</h1>
Now, you are probably wondering how the browser can figure out which class to apply. This is when the meta viewport tag comes into play.
The Viewport Meta Tag
The meta viewport is set in the head section of the index.html
<meta name="viewport" content="width=device-width, initial-scale=1">

The viewport represents the visible area of a page, which varies as the device size gets smaller or larger.
With the viewport meta tag, the width of the screen is detected and the information is sent to the browser, which knows the CSS to apply for a specific breakpoint. It lets you control how you want your site to display on different screen sizes.
For better control over cross-platform responsive design, you can write styling that will take effect for specific breakpoints. CSS lets you define it with the media queries.
Media Queries
The @media rule is used to define different styling for key breakpoints.
Some global styling was not really to our liking.
So, in style.css, we use the @media rule to write custom styling for the navigation links and the footer to better fit the small screen view.
@media screen and (max-width: 468px) {
}
Navigation links <li>
Because full-width always works best on small screens, we set the width of the <li> at 100%
- In the media queries, update with the code below:
@media screen and (max-width: 468px) {
.navbar li {
width: 100%;
}
}
Footer
For the footer, the columns become full-width automatically with mobile first.
However, we use text alignment classes in the markup and it looks funny on a small screen.
So, we adjust like so:
- text-align:left
- Plus, we are adding a little bit of margin on the top and bottom.
In the media queries, update with the code below:
footer p {
text-align: left;
margin: 3px 0;
}
Before After – Better!


Bootstrap provides a table of media queries that you can use in FEWER files. Replace the @variables with numerical values to define your breakpoints and you are good to go.
Congrats for making it this far! Still can’t get enough of Bootstrap?
There is more to come, and we have saved the best for last. Here come the bonuses!
BONUSES
Topics include:
- Tootip.js
- Carousel.js
- Font Awesome
- Adding a background image to the banner
Tooltip.js
Tooltip.js is a quick way to display extended information on mouseover, like the example below when hovering over an image.

It works via data-attributes, and the configuration is minimal.
Inside <div id=”project”>
, each image thumbnail will include a tooltip:
- First, the attributes: data-toggle and data-placement are added to the
<img>
element.
- Another attribute is title with the text you want to display as a value.
<img data-toggle="tooltip" data-placement="bottom" title="Add text" src="images/projects/web-template6.png" alt='image'>
You will not be able to see the tooltip yet.
Tooltip.js needs to be initialized with a little script at the bottom of the index.html like so:
$(function () {
$('[data-toggle="tooltip"]').tooltip()
});
We call tooltip() on [data-toggle=”tooltip“]
Try it! You must refresh your browser first.
- Update data-placement to position the tooltip: left, right or top
- Update title to add your text
More Carousel.js options
We want to show you how to have more control over the carousel behavior, such as:
- Interval
- And, pause on hover
The interval is the amount of time between each slide. The default is 5000ms, which is in milliseconds.
To give your visitors all the time they need to read through testimonials, we should increase this value a bit.
Options can be easily implemented via data-attributes, inside the carousel parent element, along with other data-attributes like this:
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel" >
To change the default value of interval, we write data-interval
The value is in milliseconds. So, we write 10000 for a 10-second interval.
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel" data-interval="10000" >
That’s more time to read all the great feedback left by customers!
You also can allow a pause between each slide.
On mouseover, the cycling pauses automatically, and then it resumes on mouseout.
This is another option available with data-pause=”hover”
Add it to the carousel parent element like so:
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel" data-interval="10000" data-pause="hover">
Now, try it!
The slideshow cycles through the slides every 10 seconds, stops on hover and resumes on mouseleave.
It is definite advantage to be able to control the behavior of a site this way. You can read more about options here.
Font Awesome
Font Awesome is a collection of 519 scalable vector icons, also designed by the Bootstrap team. They are delivered in font format, so they can be customized with CSS.
We will update the following sections with the Font Awesome icons.
- Services
- Modal Contact Form
We will start with a quick setup with CDN.
Quick setup with CDN
Font Awesome offers a quick and handy way to get started with the CDN.
In the head section, we have added the Font Awesome CDN.

A CDN is a Content Delivery Network, or a system of distributed servers that delivers content based on the user’s geographical location.
This is like using a regular stylesheet, except that the file is hosted on an external server. Therefore, the page is lighter and loads much faster.
Now, we are going to see examples of icons and see how to add them to our designs.
- To add a Font Awesome icon, use
<i>
tags
- The common class is .fa
- Then, add a modifier for the icon selected. Example: .fa-camera-retro
Here is the result:

<i class="fa fa-camera"></i>
In the services sections, we add a few icons to make it more appealing.
- In the markup, add a
<p>
above the <h3>
- The
<p>
will host the icons wrapped in <i>

Complete the markup like so:
<p><i class="fa fa-mobile"></i></p>
You can also customize the size with .fa-4x
<p><i class="fa fa-mobile fa-4x"></i></p>
Update all 3 columns with Font Awesome icons like this:
<p><i class="fa fa-desktop fa-4x"></i></p>
<p><i class="fa fa-mobile fa-4x"></i></p
<p><i class="fa fa-pencil fa-4x"></i></p>
Font Awesome is in font format, so we can customize with the CSS color property in style.css:
#services i {
color: #3498db;
}
We do the same for the contact form in the modal dialog. In the modal footer, we have included text links that we will replace with font icons.
From this:

To this:

In the modal element, we replace the text links with social media font icons.
The markup looks like this:
<ul class="list-inline">
<li><a href="#"><i class="fa fa-facebook-square fa-3x"></i></a></li>
<li><a href="#"><i class="fa fa-twitter fa-3x"></i></a></li>
<li><a href="#"><i class="fa fa-linkedin fa-3x"></i></a></li>
<li><a href="#"><i class="fa fa-github fa-3x"></i></a></li>
</ul>
Background Image
This is the final touch to wrap it all up.
In the project files, we have added background images images/background.
In style.css, we can update like so:
#banner {
background: url("../images/background/bg-1.jpg");
background-size: cover;
}
Try it!
We hope you enjoyed this tutorial.
You are now well on your way to creating some awesome pages.
To further your learning with Bootstrap, watch Start Now With Bootstrap and create a portfolio website with HTML, CSS & Bootstrap. These 5 hours of video content will get you up to speed with the front-end framework. Practice makes perfect.
Photo courtesy of Unsplash and Freepik