Bootstrap 5 Essentials
10 classes and components that handle layout, spacing, and interactivity — so your custom CSS can focus on visual identity.
Bootstrap is a CSS framework: it provides pre-written CSS (and some JavaScript) that you activate by adding class names to HTML elements. Every class in this guide appears in one of the Conversation Quests pages.
The vibe coder’s mental model: Bootstrap handles the structure — grid layout, spacing, navbar, interactive components. Your custom CSS handles the identity — the colors, fonts, and visual character that make a page distinctly yours. When AI generates Bootstrap code, it’s assembling pre-built pieces. Understanding what those pieces do is what lets you verify, adjust, and fix the output.
The 10 Concepts
Examples span the full series: the poster, the interactive app, and the chatlog.
.container
.container-fluid
The Container
Bootstrap’s layout starts with a container. .container
has a max-width that increases at each breakpoint (540 / 720 / 960 / 1140 /
1320px) with auto left/right margins that center it horizontally.
.container-fluid is always 100% wide. Use
.container for readable text and card layouts;
use .container-fluid when you want content
to bleed to the screen edges.
<!-- Constrained width, centered -->
<div class="container">
<div class="row g-3">...</div>
</div>
<!-- Full-width with controlled side padding -->
<div class="container-fluid px-3 px-md-4">
<div class="poster-card">...</div>
</div>
You understand:
px-3 px-md-4 on the fluid container adds 1rem
padding on phones and 1.5rem on medium+ screens. This prevents the poster
card from touching the screen edges on small devices.
AI handles: Choosing the container type. If your content feels too wide or too narrow, the container class is usually the first thing to adjust.
.row
.col-md-6
g-*
The Grid System
Bootstrap’s grid is 12 columns wide. .col-md-6
means “6 columns wide (half the row) on medium screens and above; full
width below medium.” The breakpoints: sm (≥576px), md (≥768px),
lg (≥992px), xl (≥1200px), xxl (≥1400px). g-3
sets the gutter (gap between columns). The .row
must be the direct parent of .col-* elements.
<!-- 2-column grid on md+; stacked on phones -->
<div class="row g-3">
<div class="col-md-6">
<div class="poster-tier poster-tier--curiosity">...</div>
</div>
<div class="col-md-6">
<div class="poster-tier poster-tier--connection">...</div>
</div>
</div>
You understand: The grid is 12 columns.
col-md-6 = 6/12 = half. Two
col-md-6 divs sit side by side on desktop;
each stacks to full-width on phones. No media queries required.
AI handles: Column math. Tell AI "two
columns on desktop, one on mobile" and it produces the correct
col-md-* value.
p-*
m-*
me-*
gap-*
Spacing Utilities
Bootstrap’s spacing scale runs 0–5:
0=0, 1=0.25rem, 2=0.5rem, 3=1rem, 4=1.5rem, 5=3rem.
Direction codes: t=top,
b=bottom,
s=start (left in LTR),
e=end (right in LTR),
x=horizontal,
y=vertical, no suffix=all sides.
So me-1 = margin-end 0.25rem;
px-3 = padding-left and padding-right 1rem.
<!-- me-1 = margin-end (right) 0.25rem --> <i class="fas fa-comments me-1"></i>S.P.A.R.K. Chat Log <!-- gap-1 in a flex row = 0.25rem gap between items --> <ul class="navbar-nav ms-auto gap-1">...</ul> <!-- pt-4 = padding-top 1.5rem --> <div class="log-container pt-4">...</div> <!-- g-3 on .row = gutters between columns --> <div class="row g-3">...</div>
You understand: The scale. 1=tiny nudge (0.25rem), 3=standard spacing (1rem), 5=large (3rem). When AI’s spacing feels off, you can ask it to increase or decrease the number.
AI handles: Choosing appropriate utility
values for context. Tell AI "add a small gap between the icon and the label"
and it applies me-1 or
me-2 correctly.
d-flex
align-items-*
justify-content-*
Flexbox Utilities
Bootstrap wraps CSS flexbox into single-class utilities.
d-flex = display: flex.
align-items-center = align-items: center.
They produce identical CSS to hand-written flexbox — the difference is
speed: you apply them directly in HTML without writing a CSS rule. Use utilities
for one-off layouts; write a CSS class when the same pattern repeats or needs
multiple properties.
<!-- Flex row, items centered, with gap -->
<div class="d-flex gap-3 align-items-center">
<a href="convQuestChatlog.html">Chat Log</a>
<a href="convQuestPoster.html">Poster</a>
</div>
<!-- Bootstrap's .text-center is equivalent to: -->
<!-- justify-content: center on a flex container -->
<!-- or text-align: center on a block element -->
<div class="text-center mt-4">
<button class="draw-btn">Draw a Question</button>
</div>
You understand: Bootstrap utilities and custom CSS are interchangeable — one writes a class in HTML, the other writes it in CSS. When you see five utility classes on one element in AI output, consider asking AI to consolidate them into a named CSS class.
AI handles: Both approaches correctly. Tell AI your preference: "use Bootstrap utilities" or "write a CSS class."
visually-hidden
d-none
d-md-block
Visibility & Display Utilities
d-none hides an element completely —
removed from the visual layout and from screen readers.
visually-hidden (Bootstrap’s name for
the WCAG pattern) hides visually but keeps the element audible to screen
readers. The Conversation Quests pages use visually-hidden
for footer elements that JavaScript later reveals by calling
classList.remove('visually-hidden').
d-md-block shows an element only on medium
screens and above.
<!-- Hidden visually; screen readers still announce it -->
<p id="footerPara" class="footer-text visually-hidden">
Stage: <span id="stageSpan"></span>
</p>
<!-- JavaScript reveals it: -->
document.getElementById("footerPara")
.classList.remove("visually-hidden");
<!-- Hidden from screen readers AND visual layout -->
<span class="navbar-toggler-icon"
aria-hidden="true"></span>
You understand: Never use
d-none to "hide" something for accessibility
purposes — it also hides it from screen readers. Use
visually-hidden when screen readers should
still announce the content.
AI handles: Using
visually-hidden when you say "accessible hidden
label" or "screen-reader-only text." Review AI’s use of
d-none — ensure it’s appropriate.
.navbar
navbar-expand-xl
sticky-top
Navbar Component
navbar-expand-xl means “collapse to a
hamburger menu below XL breakpoint; show the full nav at XL and above.”
The hamburger button’s data-bs-target="#navMenu"
must match the collapse div’s id exactly
— a mismatch is the most common “hamburger doesn’t work” bug.
ms-auto on the nav list pushes links to the
right by adding automatic left margin.
<nav class="navbar navbar-expand-xl sticky-top">
<div class="container">
<a class="navbar-brand" href="../index.html">TNT</a>
<!-- hamburger: data-bs-target must match #navMenu -->
<button class="navbar-toggler"
data-bs-toggle="collapse"
data-bs-target="#navMenu">
</button>
<div class="collapse navbar-collapse" id="navMenu">
<ul class="navbar-nav ms-auto gap-1">
<li class="nav-item">
<a class="nav-link active" href="...">JS Apps</a>
</li>
</ul>
</div>
</div>
</nav>
You understand:
data-bs-target="#navMenu" and the collapse
div’s id="navMenu" are a matched pair.
If the hamburger doesn’t open the menu, check these two values first.
AI handles: The complete navbar structure. Bootstrap JS must be loaded (at the bottom of the body) for the collapse to work — AI always includes it, but verify it wasn’t removed.
.btn
.btn-warning
.fw-bold
Buttons
.btn provides the base shape: padding,
border-radius, cursor, and transition. A color modifier like
.btn-warning fills in the color scheme.
The Conversation Quests series often overrides the fill color with a custom
CSS variable while keeping .btn for the
shape — this pattern (custom color + Bootstrap shape) is correct and
common. Always add type="button" to buttons
inside forms to prevent accidental form submission.
<!-- Custom color + Bootstrap shape -->
<a href="convQuest1.html"
class="btn fw-bold me-2"
style="background-color: var(--cq-vision); color: #0d0818;">
<i class="fas fa-comments me-1"></i>Interactive App
</a>
<!-- Bootstrap color scheme -->
<button type="button"
class="btn btn-warning"
data-bs-dismiss="modal">Submit</button>
You understand:
type="button" is required on
<button> elements inside a
<form>. Without it, the button
defaults to type="submit" and submits
the form on click — even if you didn’t intend it to.
AI handles: Button color variants.
When you override the color with a custom value, keep the
.btn base class — it provides the
shape, cursor, and hover transition.
.modal
data-bs-toggle
data-bs-dismiss
Modal Component
Bootstrap modals are triggered by data-bs-toggle="modal"
+ data-bs-target="#myModal" on any trigger
element. Bootstrap JavaScript reads these attributes and handles show/hide.
data-bs-dismiss="modal" on any button inside
the modal closes it. The trigger’s data-bs-target
value and the modal’s id must match
exactly — a mismatch means the modal never opens.
<!-- Trigger element -->
<button data-bs-toggle="modal"
data-bs-target="#myModal">Open</button>
<!-- Modal — id must match data-bs-target above -->
<div id="myModal" class="modal fade" role="dialog"
tabindex="-1" aria-labelledby="myModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="myModalLabel">
Whoa There, Sparky!
</h2>
<button class="btn-close"
data-bs-dismiss="modal"></button>
</div>
</div>
</div>
</div>
You understand: Three ARIA attributes are
required: role="dialog",
tabindex="-1", and
aria-labelledby pointing to the modal
title’s id. Without these, the modal
fails HTML validation and screen readers can’t announce it correctly.
AI handles: The full modal structure. Review
the id / data-bs-target
match. Also verify aria-labelledby points to
the actual title element.
.border
.rounded
.border-0
.shadow
Border & Shadow Utilities
.border adds a 1px solid border in the
default color. .border-0 removes all borders.
.rounded adds a standard border-radius (0.375rem);
.rounded-pill creates a pill shape (50rem).
These utilities shine for rapid prototyping. When you need a custom border
color, width, or radius, write a CSS rule — utilities are starting points,
not limits.
<!-- Border + rounded corners + padding, all utilities -->
<div id="msgDiv"
class="text-center border border-secondary rounded p-2 mb-4">
<p id="msgPara" class="display-1 p-3 mb-0">
that that is is...
</p>
</div>
<!-- Remove the default border from the toggle button -->
<button class="navbar-toggler border-0" type="button">
...
</button>
You understand:
border-secondary,
border-danger, etc. change the border
color using Bootstrap’s semantic color palette. When you need
a specific hex color, write CSS and skip the utility.
AI handles: Stacking border and shadow utilities correctly. These are building blocks for rapid UI — let AI use them, then refine in CSS when the design calls for something precise.
Bootstrap CDN CSS
Bootstrap bundle.min.js
Font Awesome CDN
CDN Links — The Setup
Bootstrap is loaded via CDN links, not a local file. The CSS link
goes in the <head> before your
custom CSS (so your rules override Bootstrap’s). The JS link goes
at the end of the <body> for performance.
Use bootstrap.bundle.min.js — it includes
Popper.js (required for dropdowns, tooltips, and modals). Pin to a specific
version number, not @latest, so your site
doesn’t break when Bootstrap releases a new major version.
<!-- In <head>: Bootstrap CSS first, then your CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
rel="stylesheet">
<link rel="stylesheet" href="../styles/tnt-base-styles.css">
<link rel="stylesheet" href="styles/convQuestPosterStyles.css">
<!-- Before </body>: JS bundle last -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js">
</script>
You understand: Order matters for CSS:
Bootstrap first, your overrides last. Without this order, Bootstrap’s
rules overwrite your custom styles. The .min.
in filenames means minified (whitespace removed for faster download).
AI handles: Always includes the correct CDN links. Review the Bootstrap version number — AI may generate a slightly outdated version. The version in this series is 5.3.3.