All Bootstrap Exercises
Create a responsive three column layout with Bootstrap
Description: Create three columns. On small screens they must be stacked (full width), and from the medium breakpoint they must be side by side.
Hint:
- Use
container,rowandcol-12 col-md-4.
Solution
<div class="container text-center">
<div class="row g-2">
<div class="col-12 col-md-4"><div class="p-3 border bg-light">Column 1</div></div>
<div class="col-12 col-md-4"><div class="p-3 border bg-light">Column 2</div></div>
<div class="col-12 col-md-4"><div class="p-3 border bg-light">Column 3</div></div>
</div>
</div>
How it works
col-12gives the full width on small screens, andcol-md-4gives 4 of 12 columns from 768px.g-2adds a small gutter between the columns.
Read Grid System.
Create a centered page heading and text with Bootstrap
Description: Make a centered heading “Welcome” with a lead paragraph under it, inside a container, with some space above and below.
Hint:
- Use
container,text-center,display-*,leadandmy-5.
Solution
<div class="container text-center my-5">
<h1 class="display-4">Welcome</h1>
<p class="lead">This is a short introduction text under the heading.</p>
</div>
How it works
my-5adds margin on top and bottom.text-centercenters the text.
Read Typography and Spacing.
Create a responsive navbar with a brand and three links
Description: Build a navbar with the brand “MySite” and three links. It must collapse into a toggle button on small screens.
Hint:
- Use
navbar navbar-expand-md,navbar-togglerandcollapse navbar-collapse.
Solution
<nav class="navbar navbar-expand-md bg-body-tertiary">
<div class="container-fluid">
<a class="navbar-brand" href="#">MySite</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#menu" aria-controls="menu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="menu">
<ul class="navbar-nav">
<li class="nav-item"><a class="nav-link active" href="#">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#">About</a></li>
<li class="nav-item"><a class="nav-link" href="#">Contact</a></li>
</ul>
</div>
</div>
</nav>
document.querySelector('.navbar-toggler').click();
await new Promise(r => setTimeout(r, 600));
console.log('menu opens on a small screen: ' + document.getElementById('menu').classList.contains('show'));
console.log('links in the menu: ' + document.querySelectorAll('#menu .nav-link').length);
menu opens on a small screen: true
links in the menu: 3
How it works
- The links are hidden in the
collapsepart, and the toggler button opens them. - From the md breakpoint (768px) the menu is shown in a row.
Read Navbar.
Create a card with an image, a title, a text and a button
Description: Create a card 18rem wide with an image on top, a title, a text and a button.
Hint:
- Use
card,card-img-top,card-body,card-titleandcard-text.
Solution
<div class="card" style="width: 18rem;">
<img src="images/photo.jpg" class="card-img-top" alt="A sample image">
<div class="card-body">
<h5 class="card-title">Learn Bootstrap</h5>
<p class="card-text">A short text about the course, with some words.</p>
<a href="#" class="btn btn-primary">Start now</a>
</div>
</div>
How it works
- The image uses
card-img-top, so it fits the top of the card with rounded corners. - The text and the button are inside
card-body, which gives the padding.
Read Cards.
Create a responsive grid of six cards
Description: Show six cards: 1 per row on small screens, 2 per row from sm and 3 per row from lg.
Hint:
- Use
row row-cols-1 row-cols-sm-2 row-cols-lg-3 g-3andcard h-100.
Solution
<div class="container">
<div class="row row-cols-1 row-cols-sm-2 row-cols-lg-3 g-3">
<div class="col"><div class="card h-100"><div class="card-body"><h5 class="card-title">Card 1</h5><p class="card-text">Text</p></div></div></div>
<div class="col"><div class="card h-100"><div class="card-body"><h5 class="card-title">Card 2</h5><p class="card-text">Text</p></div></div></div>
<div class="col"><div class="card h-100"><div class="card-body"><h5 class="card-title">Card 3</h5><p class="card-text">Text</p></div></div></div>
<div class="col"><div class="card h-100"><div class="card-body"><h5 class="card-title">Card 4</h5><p class="card-text">Text</p></div></div></div>
<div class="col"><div class="card h-100"><div class="card-body"><h5 class="card-title">Card 5</h5><p class="card-text">Text</p></div></div></div>
<div class="col"><div class="card h-100"><div class="card-body"><h5 class="card-title">Card 6</h5><p class="card-text">Text</p></div></div></div>
</div>
</div>
How it works
row-cols-*sets the number of columns per row, so each column needs only the classcol.h-100makes the cards in a row the same height.
Read Grid: Gutters, Offset and Order and Cards.
Create a login form with Bootstrap
Description: Create a login form with an email, a password, a “Remember me” checkbox and a full width Login button, centered in a card.
Hint:
- Use
form-label,form-control,form-checkandd-grid.
Solution
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-sm-10 col-md-8">
<div class="card shadow-sm">
<div class="card-body p-4">
<h2 class="h4 mb-3 text-center">Login</h2>
<form>
<div class="mb-3">
<label for="lemail" class="form-label">Email address</label>
<input type="email" class="form-control" id="lemail" placeholder="name@example.com">
</div>
<div class="mb-3">
<label for="lpass" class="form-label">Password</label>
<input type="password" class="form-control" id="lpass">
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="lremember">
<label class="form-check-label" for="lremember">Remember me</label>
</div>
<div class="d-grid"><button type="submit" class="btn btn-primary">Login</button></div>
</form>
</div>
</div>
</div>
</div>
</div>
How it works
justify-content-centeron the row centers the column.d-gridmakes the button full width.
Read Forms.
Create a registration form with two columns
Description: Make a registration form. First name and last name must be in one row, email and city in another row, and the address field must be full width.
Hint:
- Use the grid inside the form:
row g-3andcol-md-6.
Solution
<form class="row g-3">
<div class="col-md-6">
<label for="rfn" class="form-label">First name</label>
<input type="text" class="form-control" id="rfn">
</div>
<div class="col-md-6">
<label for="rln" class="form-label">Last name</label>
<input type="text" class="form-control" id="rln">
</div>
<div class="col-md-8">
<label for="rem" class="form-label">Email</label>
<input type="email" class="form-control" id="rem">
</div>
<div class="col-md-4">
<label for="rcity" class="form-label">City</label>
<select id="rcity" class="form-select"><option selected>Choose...</option><option>Delhi</option><option>Pune</option></select>
</div>
<div class="col-12">
<label for="radd" class="form-label">Address</label>
<input type="text" class="form-control" id="radd" placeholder="Street and number">
</div>
<div class="col-12"><button type="submit" class="btn btn-primary">Register</button></div>
</form>
How it works
row g-3on the form creates the grid with a gutter. Each field is a column.col-md-6puts two fields side by side from 768px, and they are stacked on a phone.
Read Forms.
Validate a required field with Bootstrap
Description: Create a form with a required name field. When the user submits it empty, the field must be red with the message “Please write your name”.
Hint:
- Use
novalidate,.needs-validation,.invalid-feedback,checkValidity()and the classwas-validated.
Solution
<form class="needs-validation" novalidate id="f">
<label for="vn" class="form-label">Name</label>
<input type="text" class="form-control" id="vn" required>
<div class="invalid-feedback">Please write your name.</div>
<button class="btn btn-primary mt-3" type="submit">Submit</button>
</form>
<script>
document.getElementById('f').addEventListener('submit', function (e) {
if (!this.checkValidity()) { e.preventDefault(); e.stopPropagation(); }
this.classList.add('was-validated');
});
</script>
const f = document.getElementById('f');
f.requestSubmit();
await new Promise(r => setTimeout(r, 200));
console.log('was-validated class: ' + f.classList.contains('was-validated'));
console.log('field is invalid: ' + !document.getElementById('vn').checkValidity());
console.log('message color: ' + getComputedStyle(document.querySelector('.invalid-feedback')).color + ', display: ' + getComputedStyle(document.querySelector('.invalid-feedback')).display);
was-validated class: true
field is invalid: true
message color: rgb(220, 53, 69), display: block
How it works
- The browser checks the
requiredattribute withcheckValidity(). - After
was-validatedis added, Bootstrap shows the red border and the.invalid-feedbacktext.
Read Form Validation.
Create a striped, hover and responsive table
Description: Make a table of three students with striped rows and a hover effect, which scrolls sideways on small screens.
Hint:
- Use
table table-striped table-hoverand wrap it intable-responsive.
Solution
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="table-dark"><tr><th>#</th><th>Name</th><th>City</th><th>Marks</th></tr></thead>
<tbody>
<tr><td>1</td><td>Anita</td><td>Delhi</td><td>88</td></tr>
<tr><td>2</td><td>Ravi</td><td>Pune</td><td>92</td></tr>
<tr><td>3</td><td>Maya</td><td>Kolkata</td><td>79</td></tr>
</tbody>
</table>
</div>
How it works
table-stripedcolors every second row,table-hoverhighlights the row under the mouse.table-responsiveadds a horizontal scroll when the table is wider than the screen.
Read Tables.
Create an alert which the user can close
Description: Show a warning alert with a close button. When the user clicks the button, the alert must disappear.
Hint:
- Use
alert-dismissible fade show,btn-closeanddata-bs-dismiss="alert".
Solution
<div class="alert alert-warning alert-dismissible fade show" role="alert" id="al">
<strong>Careful!</strong> Your session will end in 5 minutes.
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
console.log('alert before: ' + document.querySelectorAll('#al').length);
document.querySelector('#al .btn-close').click();
await new Promise(r => setTimeout(r, 600));
console.log('alert after the click: ' + document.querySelectorAll('#al').length);
alert before: 1
alert after the click: 0
How it works
data-bs-dismiss="alert"tells Bootstrap to close the alert, andfade showgives the smooth effect.
Read Alerts.
Open a modal with a button
Description: Add a button “Open”. The click must open a modal with a title, a text and a Close button.
Hint:
- Use
data-bs-toggle="modal",data-bs-targetanddata-bs-dismiss="modal".
Solution
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#ex1">Open</button>
<div class="modal fade" id="ex1" tabindex="-1" aria-labelledby="ex1Label" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="ex1Label">Hello</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">This is a modal.</div>
<div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button></div>
</div>
</div>
</div>
const m = document.getElementById('ex1');
document.querySelector('[data-bs-toggle="modal"]').click();
await new Promise(r => setTimeout(r, 700));
console.log('open: ' + m.classList.contains('show'));
m.querySelector('.modal-footer .btn').click();
await new Promise(r => setTimeout(r, 700));
console.log('open after Close: ' + m.classList.contains('show'));
open: true
open after Close: false
How it works
- The button opens the element with the id from
data-bs-target. modal-dialog-centeredputs the box in the vertical center.
Read Modal.
Create an accordion with three items
Description: Make an accordion with three items. The first is open at the start, and opening another one must close the first.
Hint:
- Use
accordion,accordion-item,accordion-buttonanddata-bs-parent.
Solution
<div class="accordion" id="acc">
<div class="accordion-item">
<h2 class="accordion-header"><button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#a1" aria-expanded="true" aria-controls="a1">Item 1</button></h2>
<div id="a1" class="accordion-collapse collapse show" data-bs-parent="#acc"><div class="accordion-body">Text of item 1</div></div>
</div>
<div class="accordion-item">
<h2 class="accordion-header"><button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#a2" aria-expanded="false" aria-controls="a2">Item 2</button></h2>
<div id="a2" class="accordion-collapse collapse" data-bs-parent="#acc"><div class="accordion-body">Text of item 2</div></div>
</div>
<div class="accordion-item">
<h2 class="accordion-header"><button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#a3" aria-expanded="false" aria-controls="a3">Item 3</button></h2>
<div id="a3" class="accordion-collapse collapse" data-bs-parent="#acc"><div class="accordion-body">Text of item 3</div></div>
</div>
</div>
document.querySelector('[data-bs-target="#a3"]').click();
await new Promise(r => setTimeout(r, 800));
['a1', 'a2', 'a3'].forEach(id => console.log(id + ' open = ' + document.getElementById(id).classList.contains('show')));
a1 open = false
a2 open = false
a3 open = true
How it works
data-bs-parent="#acc"connects the items, so Bootstrap closes the others.- After the click on item 3, only item 3 is open.
Read Collapse and Accordion.
Create tabs with three panels
Description: Create three tabs. Clicking a tab must show only its own panel.
Hint:
- Use
nav nav-tabs,data-bs-toggle="tab"andtab-contentwithtab-pane.
Solution
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item" role="presentation"><button class="nav-link active" id="t1" data-bs-toggle="tab" data-bs-target="#p1" type="button" role="tab" aria-controls="p1" aria-selected="true">Home</button></li>
<li class="nav-item" role="presentation"><button class="nav-link" id="t2" data-bs-toggle="tab" data-bs-target="#p2" type="button" role="tab" aria-controls="p2" aria-selected="false">Profile</button></li>
<li class="nav-item" role="presentation"><button class="nav-link" id="t3" data-bs-toggle="tab" data-bs-target="#p3" type="button" role="tab" aria-controls="p3" aria-selected="false">Contact</button></li>
</ul>
<div class="tab-content border border-top-0 p-3">
<div class="tab-pane fade show active" id="p1" role="tabpanel" tabindex="0">Home panel</div>
<div class="tab-pane fade" id="p2" role="tabpanel" tabindex="0">Profile panel</div>
<div class="tab-pane fade" id="p3" role="tabpanel" tabindex="0">Contact panel</div>
</div>
document.getElementById('t3').click();
await new Promise(r => setTimeout(r, 500));
console.log('active panel: ' + document.querySelector('.tab-pane.active').textContent);
console.log('active tab: ' + document.querySelector('.nav-link.active').textContent);
active panel: Contact panel
active tab: Contact
How it works
- Each tab button points to a panel with
data-bs-target. Bootstrap switches the classesactiveandshow.
Read Navs and Tabs.
Create a carousel with three slides
Description: Make a carousel with three slides, previous and next buttons and three indicators.
Hint:
- Use
carousel slide,carousel-inner,carousel-item activeand the control buttons withdata-bs-slide.
Solution
<div id="cx" class="carousel slide" style="max-width: 420px">
<div class="carousel-indicators">
<button type="button" data-bs-target="#cx" data-bs-slide-to="0" class="active" aria-label="Slide 1"></button>
<button type="button" data-bs-target="#cx" data-bs-slide-to="1" aria-label="Slide 2"></button>
<button type="button" data-bs-target="#cx" data-bs-slide-to="2" aria-label="Slide 3"></button>
</div>
<div class="carousel-inner">
<div class="carousel-item active"><img src="images/photo.jpg" class="d-block w-100" alt="Slide 1"></div>
<div class="carousel-item"><img src="images/photo.jpg" class="d-block w-100" alt="Slide 2"></div>
<div class="carousel-item"><img src="images/photo.jpg" class="d-block w-100" alt="Slide 3"></div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#cx" data-bs-slide="prev"><span class="carousel-control-prev-icon" aria-hidden="true"></span><span class="visually-hidden">Previous</span></button>
<button class="carousel-control-next" type="button" data-bs-target="#cx" data-bs-slide="next"><span class="carousel-control-next-icon" aria-hidden="true"></span><span class="visually-hidden">Next</span></button>
</div>
const cx = document.getElementById('cx');
const idx = () => [...cx.querySelectorAll('.carousel-item')].findIndex(i => i.classList.contains('active')) + 1;
cx.querySelector('.carousel-control-next').click();
await new Promise(r => setTimeout(r, 900));
console.log('after Next: slide ' + idx());
cx.querySelector('.carousel-control-next').click();
await new Promise(r => setTimeout(r, 900));
console.log('after Next again: slide ' + idx());
cx.querySelector('.carousel-control-next').click();
await new Promise(r => setTimeout(r, 900));
console.log('after Next at the end: slide ' + idx() + ' (it goes round)');
after Next: slide 2
after Next again: slide 3
after Next at the end: slide 1 (it goes round)
How it works
- Exactly one
carousel-itemmust have the classactiveat the start. - After the last slide, the carousel goes back to the first one.
Read Carousel.
Add a tooltip to a button
Description: Add a tooltip “Save the file” to a button, which opens when the user hovers on it.
Hint:
- Use
data-bs-toggle="tooltip",data-bs-titleand start it withnew bootstrap.Tooltip().
Solution
<button type="button" class="btn btn-success" id="savebtn" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Save the file">Save</button>
<script>
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(function (el) { new bootstrap.Tooltip(el); });
</script>
const b = document.getElementById('savebtn');
b.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
await new Promise(r => setTimeout(r, 400));
const t = document.querySelector('.tooltip');
console.log('tooltip shown: ' + (t !== null) + ', text: ' + (t ? t.textContent.trim() : ''));
tooltip shown: true, text: Save the file
How it works
- Tooltips are not started automatically. The small script finds all elements with
data-bs-toggle="tooltip"and starts them.
Read Tooltips and Popovers.
Create a progress bar at 60 percent
Description: Show a progress bar which is filled to 60% with the text “60%”.
Hint:
- Use
progress,progress-barand the width style. Add the aria attributes.
Solution
<div class="progress" role="progressbar" aria-label="Course progress" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar bg-success" style="width: 60%">60%</div>
</div>
How it works
- The width of
.progress-baris the percent. The role and aria values are on the wrapper for screen readers.
Create a pricing section with three cards
Description: Build three pricing cards in one row (stacked on phones). Each has a title, a price, a list of features and a button. The middle card must be highlighted.
Hint:
- Use
row row-cols-1 row-cols-md-3,card,list-unstyledandborder-primary.
Solution
<div class="container">
<div class="row row-cols-1 row-cols-md-3 g-3 text-center">
<div class="col">
<div class="card h-100">
<div class="card-header"><h3 class="h5 my-1">Free</h3></div>
<div class="card-body">
<p class="card-title display-6">$0<small class="fs-6 text-body-secondary"> / month</small></p>
<ul class="list-unstyled mt-3 mb-4"><li>1 project</li><li>Basic support</li></ul>
<button type="button" class="btn btn-outline-primary w-100">Sign up</button>
</div>
</div>
</div>
<div class="col">
<div class="card h-100 border-primary">
<div class="card-header text-bg-primary"><h3 class="h5 my-1">Pro</h3></div>
<div class="card-body">
<p class="card-title display-6">$15<small class="fs-6 text-body-secondary"> / month</small></p>
<ul class="list-unstyled mt-3 mb-4"><li>10 projects</li><li>Email support</li></ul>
<button type="button" class="btn btn-primary w-100">Get started</button>
</div>
</div>
</div>
<div class="col">
<div class="card h-100">
<div class="card-header"><h3 class="h5 my-1">Business</h3></div>
<div class="card-body">
<p class="card-title display-6">$49<small class="fs-6 text-body-secondary"> / month</small></p>
<ul class="list-unstyled mt-3 mb-4"><li>Unlimited projects</li><li>Phone support</li></ul>
<button type="button" class="btn btn-outline-primary w-100">Contact us</button>
</div>
</div>
</div>
</div>
</div>
How it works
row-cols-md-3makes three equal columns from the md breakpoint, andh-100makes the cards the same height.- The Pro card is highlighted with
border-primaryand a colored header.
Read Cards and Grid: Gutters, Offset and Order.
Create a button group
Description: Make one group of three outline buttons (Left, Middle, Right), and a vertical group of two buttons.
Hint:
- Use
btn-groupandbtn-group-vertical.
Solution
<div class="btn-group mb-3" role="group" aria-label="Alignment">
<button type="button" class="btn btn-outline-primary">Left</button>
<button type="button" class="btn btn-outline-primary">Middle</button>
<button type="button" class="btn btn-outline-primary">Right</button>
</div>
<br>
<div class="btn-group-vertical" role="group" aria-label="Vertical group">
<button type="button" class="btn btn-secondary">Top</button>
<button type="button" class="btn btn-secondary">Bottom</button>
</div>
How it works
btn-groupjoins the buttons and removes the space and the inner radius.
Read Buttons.
Center a box horizontally and vertically with flex utilities
Description: A parent has a height of 200px. Put a blue box in the exact center, horizontally and vertically.
Hint:
- Use
d-flex,justify-content-centerandalign-items-centeron the parent.
Solution
<div class="d-flex justify-content-center align-items-center bg-body-secondary" style="height: 200px">
<div class="p-3 bg-primary text-white rounded">I am in the center</div>
</div>
How it works
justify-content-centercenters on the main axis (horizontal).align-items-centercenters on the other axis (vertical).- The parent needs a height, or there is no free space to center in.
Read Flex Utilities.
Add a notification count badge to a button
Description: Add a red round badge with the number 5 on the top right corner of an “Inbox” button.
Hint:
- Use
position-relativeon the button andposition-absolute top-0 start-100 translate-middleon the badge.
Solution
<button type="button" class="btn btn-primary position-relative">
Inbox
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
5
<span class="visually-hidden">unread messages</span>
</span>
</button>
How it works
top-0 start-100puts the badge on the corner, andtranslate-middlemoves it half of its size back, so it sits on the corner.- The hidden text tells screen reader users what “5” means.