Tables
Tables are the right tool for data with rows and columns: marks sheets, price lists, order histories, train timetables. Plain HTML tables look cramped and hard to read. Bootstrap turns them into clean, readable tables with one class, and adds options for stripes, borders, colours and phone-friendly scrolling.
In this lesson you will style a table, choose between the different table looks, highlight rows, and make wide tables work on small screens.
The basic table
Write a normal, well-structured HTML table (see HTML Tables) and add the table class to the <table> element. Bootstrap adds padding to the cells, horizontal lines between rows, and a bold header.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Marks table</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-3">
<table class="table table-striped table-hover caption-top">
<caption>Class 10-B, half-yearly exam marks (out of 100)</caption>
<thead>
<tr>
<th scope="col">Roll no.</th>
<th scope="col">Name</th>
<th scope="col" class="text-end">Maths</th>
<th scope="col" class="text-end">Science</th>
<th scope="col" class="text-end">English</th>
</tr>
</thead>
<tbody class="table-group-divider">
<tr><th scope="row">1</th><td>Aarav Sharma</td><td class="text-end">88</td><td class="text-end">91</td><td class="text-end">79</td></tr>
<tr><th scope="row">2</th><td>Isha Verma</td><td class="text-end">95</td><td class="text-end">89</td><td class="text-end">92</td></tr>
<tr class="table-danger"><th scope="row">3</th><td>Kabir Khan</td><td class="text-end">31</td><td class="text-end">44</td><td class="text-end">58</td></tr>
<tr><th scope="row">4</th><td>Meera Pillai</td><td class="text-end">76</td><td class="text-end">82</td><td class="text-end">90</td></tr>
</tbody>
<tfoot>
<tr class="fw-semibold"><td colspan="2">Class average</td><td class="text-end">72.5</td><td class="text-end">76.5</td><td class="text-end">79.8</td></tr>
</tfoot>
</table>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>What the classes add:
table-stripedshades every other row, which helps the eye follow a long row across.table-hoverhighlights the row under the mouse pointer.table-group-divideron the<tbody>draws a thicker line between the header and the body.caption-topmoves the<caption>above the table. A caption tells everyone, including screen-reader users, what the table is about.table-dangeron one row colours it, here to flag a student who needs help. Also add text such as "Needs support" if the colour carries meaning.text-endright-aligns the numbers so the digits line up.
Keep scope="col" on header cells and scope="row" on the first cell of each row. They let screen readers announce "Maths, 88" instead of just "88".
Table styles at a glance
| Class | Effect |
|---|---|
table-striped | Zebra stripes on rows |
table-striped-columns | Zebra stripes on columns |
table-hover | Highlights the hovered row |
table-bordered | Borders on every side of every cell |
table-borderless | No borders at all |
table-sm | Halves the cell padding for a compact table |
table-active | Highlights one row or cell |
table-primary, table-success, table-danger... | Colours a whole table, a row or a single cell |
table-dark, table-light | Dark or light background, often used on <thead> |
You can combine them, for example table table-sm table-bordered table-hover for a dense admin table.
Responsive tables
A table with eight columns does not fit on a 360px phone. Squeezing it makes every cell unreadable, and the page starts scrolling sideways. The solution is to let only the table scroll horizontally: wrap it in a div with table-responsive.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Responsive table</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-3" style="max-width: 420px">
<h1 class="h5">Trains from Jaipur to Pune</h1>
<div class="table-responsive">
<table class="table table-sm table-bordered align-middle text-nowrap">
<thead class="table-light">
<tr>
<th scope="col">Train no.</th>
<th scope="col">Name</th>
<th scope="col">Departs</th>
<th scope="col">Arrives</th>
<th scope="col">Days</th>
<th scope="col">Classes</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>11000</td><td>Sample Express</td><td>06:10</td><td>08:45 (+1)</td><td>Mon, Thu</td><td>SL, 3A, 2A</td>
<td><span class="badge text-bg-success">Available</span></td>
</tr>
<tr>
<td>22000</td><td>Practice Superfast</td><td>18:30</td><td>17:05 (+1)</td><td>Daily</td><td>3A, 2A, 1A</td>
<td><span class="badge text-bg-warning">Waitlist 12</span></td>
</tr>
</tbody>
</table>
</div>
<p class="small text-body-secondary">Swipe or scroll the table sideways to see all columns.</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>The page stays put, and only the table area scrolls. Two more helpers are used here: align-middle vertically centres the cell contents (useful when cells hold badges or buttons), and text-nowrap keeps times like "08:45 (+1)" on one line.
You can also make a table responsive only below a breakpoint: table-responsive-md scrolls on screens narrower than 768px and behaves like a normal table above that.
Tables in cards and dark mode
In admin panels, tables usually sit inside a card. Put the table directly in the card (not in card-body) and add mb-0 so there is no gap at the bottom:
<div class="card">
<div class="card-header fw-semibold">Recent orders</div>
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead><tr><th scope="col">Order</th><th scope="col">Customer</th><th scope="col" class="text-end">Amount</th></tr></thead>
<tbody>
<tr><td>#4521</td><td>Priya, Jaipur</td><td class="text-end">₹1,299</td></tr>
<tr><td>#4522</td><td>Farhan, Lucknow</td><td class="text-end">₹640</td></tr>
</tbody>
</table>
</div>
</div>Tables follow the colour mode automatically. Inside an element with data-bs-theme="dark", a normal table already becomes dark, so you rarely need table-dark in Bootstrap 5.3.
Advanced: sorting and filtering
Bootstrap only styles tables. It does not sort columns or filter rows. For small tables you can filter with a few lines of JavaScript:
const search = document.getElementById("search");
search.addEventListener("input", () => {
const term = search.value.toLowerCase();
document.querySelectorAll("#orders tbody tr").forEach((row) => {
row.hidden = !row.textContent.toLowerCase().includes(term);
});
});For large data (thousands of rows), filter and page the data on the server with SQL instead of sending it all to the browser.
Common mistakes
- Forgetting the base
tableclass.table-stripedalone does nothing. - Putting
table-responsiveon the<table>itself. It belongs on a wrapping<div>. - Using tables for layout. Screen readers announce rows and columns, which confuses users. Use the grid.
- Leaving out
<thead>,<th>andscope. The table looks fine but is hard to understand with a screen reader, and the header styling is lost.
Key points
- Add
tableto any<table>for clean default styling; add modifiers such astable-striped,table-hover,table-borderedandtable-sm. - Colour rows or cells with
table-success,table-dangerand the other variants, or highlight withtable-active. - Wrap wide tables in
<div class="table-responsive">so only the table scrolls on phones. - Use
<caption>,<thead>,<th scope>andtext-endfor numbers to make tables accessible and readable. - Bootstrap styles tables but does not sort or filter them; that needs JavaScript or the server.
Exercise
Make a compact, bordered price list for a mobile repair shop in Rohtak with columns for Service, Time taken and Price. Add five services, right-align the prices, colour the cheapest service's row with table-success, add a caption on top, and wrap the table so it scrolls sideways on small screens.
Show solution
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Repair prices</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container py-3">
<div class="table-responsive">
<table class="table table-sm table-bordered caption-top">
<caption>Mobile repair price list, Rohtak</caption>
<thead class="table-light">
<tr><th scope="col">Service</th><th scope="col">Time taken</th><th scope="col" class="text-end">Price</th></tr>
</thead>
<tbody>
<tr><td>Screen guard fitting</td><td>10 minutes</td><td class="text-end">₹150</td></tr>
<tr><td>Charging port repair</td><td>1 hour</td><td class="text-end">₹450</td></tr>
<tr><td>Battery replacement</td><td>45 minutes</td><td class="text-end">₹1,200</td></tr>
<tr><td>Screen replacement</td><td>2 hours</td><td class="text-end">₹3,500</td></tr>
<tr class="table-success"><td>Software update (cheapest)</td><td>30 minutes</td><td class="text-end">₹100</td></tr>
</tbody>
</table>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>table-sm and table-bordered give a compact grid of borders, caption-top places the caption above, and the table-responsive wrapper scrolls the table instead of the page. The word "cheapest" repeats the colour's meaning in text.
Quick Quiz
1. Where does the table-responsive class go?
The wrapper scrolls horizontally, so the table can keep its natural width.
2. Which class halves the padding of the cells for a compact table?
table-sm is the Bootstrap 4 and 5 name; table-condensed was Bootstrap 3.
3. What does scope="col" on a <th> do?
The scope attribute links header cells to their data cells for assistive technology.
4. Which classes would you combine for a striped table that highlights the row under the mouse?
Each modifier adds one feature and they can be combined with the base table class.
Learn Bootstrap with a mentor
Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
