The 60 Bootstrap questions interviewers actually ask, with direct answers, runnable markup, and what the interviewer is listening for. Grouped for freshers, intermediate, and experienced rounds.
60 questions with answersKey Takeaways
Bootstrap is a free, open-source front-end framework first released by Twitter engineers in 2011, built to help developers ship responsive, mobile-first web pages fast. It bundles a CSS layer (a 12-column grid, spacing and typography utilities, and styled components like buttons, cards, modals, and navbars) with a small JavaScript layer that drives interactive widgets. You drop in a few classes and get a layout that reflows across phones, tablets, and desktops without writing custom media queries. In interviews, Bootstrap questions probe how the responsive grid and breakpoints work, when to reach for a utility versus a component, and how you customize the defaults with Sass rather than overriding everything by hand. This page collects the 60 questions that come up most, each with a direct answer and runnable markup. The official Bootstrap documentation is the canonical reference for every class and component; increasingly the first front-end round is a live AI coding interview, so pair this bank with our AI interview preparation guides for the format side.
Watch: Bootstrap 5 Crash Course | Website Build & Deploy
Video: Bootstrap 5 Crash Course | Website Build & Deploy (Traversy Media, YouTube)
Test yourself and earn a certificate
10 quick questions. Score 70%+ to download your Bootstrap certificate.
The fundamentals every entry-level round checks. If any answer here surprises you, that's your study list.
Bootstrap is a free, open-source CSS and JavaScript framework for building responsive, mobile-first websites. It ships a 12-column grid, utility classes, and prebuilt components like navbars, buttons, cards, and modals so you don't style everything from scratch.
Developers use it to ship consistent, responsive layouts fast. Instead of writing custom media queries and component CSS, you add a few classes and get a page that reflows across phones, tablets, and desktops.
Key point: A one-line definition plus two concrete examples (grid, prebuilt components) beats a memorized feature list. Interviewers open with this to hear how you organize an answer.
Watch a deeper explanation
Video: Bootstrap 5 Crash Course Tutorial #1 - Intro & Setup (Net Ninja, YouTube)
Two common ways: link the CSS and JS from a CDN, or install the npm package and import it into your build. The CDN is fastest for a quick page; npm gives you version pinning and Sass customization.
You need the stylesheet in the head and the JavaScript bundle before the closing body tag. The bundle includes Popper, which dropdowns, tooltips, and popovers depend on.
<!-- CDN in <head> -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Before </body> -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>Key point: Mention that the bundle version includes Popper. Candidates who forget the JS entirely can't explain why their dropdown doesn't open.
The grid divides each row into 12 columns. You wrap columns in a .row, wrap the row in a container, and give each column a width class whose numbers add up to 12 per row. Columns are flexbox children, so they sit side by side and wrap when they run out of space.
Breakpoint infixes (col-sm, col-md, col-lg) make widths responsive: a column can be full width on mobile and half width on desktop with two classes.
<div class="container">
<div class="row">
<div class="col-md-8">Main content</div>
<div class="col-md-4">Sidebar</div>
</div>
</div>
<!-- 8 + 4 = 12; both stack full width below md -->Key point: The container-row-column trio is the contract. Skipping the .row is the most common beginner mistake, so name it explicitly.
Watch a deeper explanation
Video: Learn Bootstrap 5 and SASS by Building a Portfolio Website - Full Course (freeCodeCamp.org, YouTube)
.container has a max-width that jumps at each breakpoint, so content sits in a centered column with margins on wide screens. .container-fluid spans 100% of the viewport width at every size.
Bootstrap 5 also adds responsive containers like .container-md, which stay fluid up to a breakpoint and then become fixed-width from that breakpoint up.
| Class | Width behavior | Typical use |
|---|---|---|
| .container | Fixed max-width per breakpoint, centered | Standard page content |
| .container-fluid | Full viewport width always | Full-bleed sections, dashboards |
| .container-lg | Fluid until lg, then fixed | Edge-to-edge on small screens only |
Key point: The follow-up is usually 'when would you use fluid?'. Have the dashboard or full-bleed hero example ready.
Bootstrap 5 has six tiers: the default (no infix) applies to everything, then sm at 576px, md at 768px, lg at 992px, xl at 1200px, and xxl at 1400px. Each tier is a min-width, so a class applies from that width upward.
This is why the grid is mobile-first: you set the smallest layout with the plain class, then override upward for larger screens.
| Breakpoint | Infix | Min width |
|---|---|---|
| Extra small | (none) | < 576px |
| Small | sm | 576px |
| Medium | md | 768px |
| Large | lg | 992px |
| Extra large | xl | 1200px |
| Extra extra large | xxl | 1400px |
Key point: Interviewers use this to set up the mobile-first question. You don't need exact pixels, but knowing md is roughly a tablet and lg a laptop shows real usage.
Mobile-first means styles target the smallest screen by default, and larger breakpoints add or override styles as the viewport grows. Bootstrap's breakpoint classes use min-width media queries, so col-md-6 kicks in at medium and up while the base applies below.
The practical rule: set your mobile layout with plain classes first, then layer in sm, md, and lg overrides. You rarely need a max-width query.
<div class="col-12 col-md-6 col-lg-4">
<!-- full width on phones, half on tablets, a third on desktops -->
</div>Key point: Show the class order small to large in one element. That single line proves you understand min-width layering.
If you only give a column a class at a larger breakpoint, like col-md-6, there's no width set below md, so the column falls back to full width and stacks. That's the mobile-first default doing its job.
To keep columns side by side on the smallest screens too, add a plain col or col-6 class alongside the breakpoint class.
<!-- stacks below md -->
<div class="col-md-6">A</div>
<!-- stays half width even on phones -->
<div class="col-6 col-md-6">B</div>Key point: This question checks whether you truly get min-width behavior. Explaining the fallback, not just the fix, is the signal.
Spacing classes follow a pattern: a property letter (m for margin, p for padding), an optional side (t, b, s, e, x, y), an optional breakpoint, and a size from 0 to 5 (or auto). So mt-3 is margin-top size 3, and px-lg-4 is horizontal padding size 4 from large up.
The sizes map to a spacer scale, so spacing stays consistent across the app without you picking pixel values.
<div class="mt-3 mb-4 px-2">Card body</div>
<div class="p-0 m-auto">Reset and center</div>
<div class="mx-auto" style="width: 200px;">Horizontally centered</div>Key point: The s and e sides (start and end) replace l and r in Bootstrap 5 for RTL support. Mentioning that indicates current knowledge.
Bootstrap covers alignment (text-start, text-center, text-end), transformation (text-uppercase, text-lowercase, text-capitalize), weight and style (fw-bold, fst-italic), and wrapping (text-truncate, text-nowrap). Font-size helpers fs-1 through fs-6 match heading sizes without using heading tags.
These utilities keep markup semantic: you can style a paragraph like a heading without misusing an h1.
<p class="text-center fw-bold text-uppercase">Section title</p>
<p class="text-truncate" style="max-width: 150px;">A very long line that gets cut off</p>A card is a flexible content container with optional header, body, image, and footer sections. You wrap content in .card, then use .card-body, .card-title, .card-text, and .card-img-top to structure it.
Cards are a common layout building block: put them in grid columns and they line up into a responsive gallery.
<div class="card" style="width: 18rem;">
<img src="cover.jpg" class="card-img-top" alt="Cover">
<div class="card-body">
<h5 class="card-title">Role: Frontend</h5>
<p class="card-text">Remote, full time.</p>
<a href="#" class="btn btn-primary">Apply</a>
</div>
</div>Text color uses text-* (text-primary, text-danger, text-muted), and background uses bg-* (bg-success, bg-dark, bg-light). The names map to Bootstrap's theme colors: primary, secondary, success, danger, warning, info, light, dark.
Because background and text color are separate utilities, pair them for contrast, like bg-dark text-white on a footer.
<div class="bg-primary text-white p-3">Primary banner</div>
<span class="text-danger">Required field</span>
<footer class="bg-dark text-light p-4">Footer</footer>Add .img-fluid to an image and it gets max-width 100% and height auto, so it scales down inside its parent and never overflows. For shape helpers, .rounded, .rounded-circle, and .img-thumbnail adjust the corners and border.
img-fluid handles the common case: an image that shrinks on small screens without a fixed width breaking the layout.
<img src="team.jpg" class="img-fluid rounded" alt="Team">
<img src="avatar.jpg" class="rounded-circle" width="64" alt="Avatar">Alerts are colored message boxes built with .alert plus a variant like .alert-success or .alert-warning. To make one dismissible, add .alert-dismissible, a close button with data-bs-dismiss, and the .fade .show classes for the transition.
The dismiss behavior is JavaScript-driven, so the Bootstrap bundle has to be loaded.
<div class="alert alert-success alert-dismissible fade show" role="alert">
Application submitted.
<button type="button" class="btn-close"
data-bs-dismiss="alert" aria-label="Close"></button>
</div>The d-* classes set the CSS display property: d-none hides an element, d-block, d-inline, and d-flex set the box type. Adding a breakpoint makes it responsive, so d-none d-md-block hides on phones and shows from medium up.
This is the modern replacement for the old hidden-* classes: you compose a hide-by-default plus a show-at-breakpoint pair.
<!-- hidden on mobile, visible from md up -->
<div class="d-none d-md-block">Desktop sidebar</div>
<!-- visible on mobile only -->
<div class="d-block d-md-none">Mobile menu</div>Key point: Interviewers ask this to see if you know Bootstrap 4 dropped the hidden-* and visible-* classes in favor of d-*. Naming that shows you're current.
Add .form-control to inputs and selects, .form-label to labels, and .form-check to checkboxes and radios. These give consistent sizing, focus states, and spacing. Wrap fields in .mb-3 for vertical rhythm between them.
For layout, put form groups in grid columns or use the row-based form grid to place fields side by side on wide screens.
<form>
<div class="mb-3">
<label class="form-label" for="email">Email</label>
<input type="email" class="form-control" id="email">
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="remember">
<label class="form-check-label" for="remember">Remember me</label>
</div>
</form>Watch a deeper explanation
Video: Bootstrap 5 Crash Course Tutorial #14 - Working with Forms (Net Ninja, YouTube)
Add .table to a table element for the base styling, then layer modifiers: .table-striped for zebra rows, .table-hover for hover highlight, .table-bordered for full borders, and .table-dark for a dark theme. .table-responsive on a wrapper adds horizontal scroll on small screens.
The responsive wrapper matters: wide tables overflow on phones, and the scroll container keeps the page layout intact.
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead><tr><th>Name</th><th>Role</th></tr></thead>
<tbody><tr><td>Asha</td><td>Engineer</td></tr></tbody>
</table>
</div>A list group is a flexible way to display a series of content: a .list-group wrapper with .list-group-item children. Items can be plain, active, disabled, or turned into links and buttons with .list-group-item-action for hover and focus states.
List groups handle common patterns like menus, settings lists, and feeds. You can add badges, contextual colors, and flush borders with modifier classes.
<div class="list-group">
<a href="#" class="list-group-item list-group-item-action active">Dashboard</a>
<a href="#" class="list-group-item list-group-item-action">Applications</a>
<a href="#" class="list-group-item list-group-item-action disabled">Reports</a>
</div>Watch a deeper explanation
Video: Bootstrap 5 Crash Course Tutorial #12 - List Groups (Net Ninja, YouTube)
Icons are a separate package called Bootstrap Icons, not part of the core CSS. You include the icon font or SVG stylesheet, then use an i or span with a class like bi bi-search.
Bootstrap 3 used to bundle Glyphicons; that was removed in version 4, so modern projects add Bootstrap Icons or another set explicitly.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
<button class="btn btn-primary">
<i class="bi bi-search"></i> Search
</button>Key point: Knowing icons are a separate download (and that Glyphicons were dropped after Bootstrap 3) is a small detail that signals real experience.
Bootstrap exposes flexbox through utilities: d-flex turns on flex, justify-content-* controls the main axis (start, center, between, around), align-items-* controls the cross axis, and flex-column or flex-row sets direction. They mirror the CSS flexbox properties one to one.
These let you center and distribute elements without writing custom CSS, and they take breakpoint infixes for responsive layouts.
<div class="d-flex justify-content-between align-items-center">
<span>Logo</span>
<button class="btn btn-primary">Menu</button>
</div>Key point: This question checks that you know Bootstrap sits on top of flexbox. If you can The CSS property behind justify-content-center, you're ahead.
CSS is the styling language browsers understand. Bootstrap is a framework written in CSS (plus some JavaScript) that gives you a system of predefined classes, a grid, and components on top of that language. Bootstrap doesn't replace CSS; it packages common patterns as reusable classes.
You still write custom CSS for anything Bootstrap doesn't cover, and you fall back to CSS knowledge whenever a layout breaks or a utility is missing.
Key point: Interviewers ask this to catch candidates who think Bootstrap is an alternative to learning CSS. Framing it as CSS with conventions on top is the right answer.
Advantages: fast development with prebuilt components, a responsive grid that handles most layouts, cross-browser consistency, and a large community with documentation. You ship a working responsive page quickly.
Disadvantages: the default look is recognizable, so sites can feel similar; heavy customization means overriding Sass or fighting specificity; and unused classes add page weight unless you purge them.
Key point: A balanced answer with real cons works better than pure praise. the question needs to see you evaluate tools, not sell them.
Gutters are the horizontal padding between grid columns that create the gap without pushing content to the edges. In Bootstrap 5 they're controlled by the .g-*, .gx-*, and .gy-* classes on the row, where gx sets horizontal and gy vertical spacing.
Set .g-0 on a row to remove gutters entirely, which is common for edge-to-edge image grids.
<div class="row g-3">
<div class="col-6">A</div>
<div class="col-6">B</div>
</div>
<!-- g-0 removes the gap between columns -->For candidates with working experience: grid mechanics, component internals, and the questions that separate users from understanders.
Bootstrap 5 dropped jQuery and rewrote its JavaScript in plain ES, added the xxl breakpoint at 1400px, switched utility naming to start/end for RTL support, and moved to CSS custom properties. It also renamed data attributes with a bs prefix, so data-toggle became data-bs-toggle.
Other shifts: Internet Explorer support was removed, the form controls were reworked, and Bootstrap Icons replaced the need for a third-party icon set.
| Area | Bootstrap 4 | Bootstrap 5 |
|---|---|---|
| jQuery | Required | Removed (plain JS) |
| Data attributes | data-toggle | data-bs-toggle |
| Breakpoints | 5 tiers | 6 tiers (adds xxl) |
| Directional utils | ml / mr (left/right) | ms / me (start/end) |
| IE support | Yes | Dropped |
Key point: The jQuery removal and the bs prefix are the two changes interviewers most want to hear. They trip up people who learned on version 4.
Watch a deeper explanation
Video: Bootstrap 5 Crash Course Tutorial #2 - Bootstrap 5 New Features (Net Ninja, YouTube)
Offset classes (offset-md-2) push a column to the right by that many columns, useful for centering or indenting content within a row. Order classes (order-1, order-md-last) change the visual order of flex columns without touching the HTML order.
Order is handy for responsive rearranging: show a sidebar first on mobile but second on desktop by swapping order at a breakpoint.
<div class="row">
<div class="col-md-6 offset-md-3">Centered half-width block</div>
</div>
<div class="row">
<div class="col order-2 order-md-1">Content</div>
<div class="col order-1 order-md-2">Sidebar first on mobile</div>
</div>Key point: The order trick (visual order differs from source order) is a favorite follow-up. Mentioning that source order still matters for accessibility is a bonus.
If you use plain .col with no number, columns split the available width equally. Add .col-auto and a column shrinks to fit its content. You can mix them: two .col columns share the leftover space around a .col-auto.
This removes the need to do the math to 12 when you just want even columns or a content-sized column beside flexible ones.
<div class="row">
<div class="col">Equal</div>
<div class="col-auto">Fits content</div>
<div class="col">Equal</div>
</div>Put a new .row inside a column, and that row starts its own 12-column context scoped to the parent column's width. So a col-md-8 can hold a nested row split into col-6 and col-6, each spanning half of the 8-wide parent, not the full page.
Nesting is how you build complex layouts: a two-column page where one column itself splits into cards.
<div class="row">
<div class="col-md-8">
<div class="row">
<div class="col-6">Nested left</div>
<div class="col-6">Nested right</div>
</div>
</div>
<div class="col-md-4">Sidebar</div>
</div>Key point: The point that a nested row re-divides its parent into 12, not the whole page, is what this question tests. State it directly.
A modal is an overlay dialog. You define the modal markup (.modal wrapping .modal-dialog and .modal-content) once, then open it with a trigger using data-bs-toggle='modal' and data-bs-target pointing at the modal's id. Bootstrap handles the backdrop, focus trap, and closing.
You can also control it in JavaScript by creating a bootstrap.Modal instance and calling show() and hide(), which is what you do when opening a modal after an async event.
<button data-bs-toggle="modal" data-bs-target="#confirm" class="btn btn-primary">Open</button>
<div class="modal fade" id="confirm" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">Are you sure?</div>
</div>
</div>
</div>Key point: Knowing both the data-attribute trigger and the JS API (new bootstrap.Modal) separates people who copy examples from people who build features.
Interactive components need the JS bundle: modals, dropdowns, tooltips, popovers, collapse, offcanvas, carousels, toasts, and tabs. Most work through data attributes automatically once the bundle loads. Tooltips and popovers are the exception: they must be initialized in JavaScript for performance reasons.
In Bootstrap 5 you initialize by constructing the component class, since there's no jQuery plugin syntax anymore.
// Tooltips need explicit init
const triggers = document.querySelectorAll('[data-bs-toggle="tooltip"]');
[...triggers].forEach(el => new bootstrap.Tooltip(el));Key point: The tooltip and popover 'opt-in' detail is a common gotcha. Candidates who know these don't auto-init have clearly shipped them.
Import Bootstrap's Sass source and override its variables before the import so your values feed into the compiled output. You change things like $primary, $font-family-base, or the grid gutter, then compile. This produces a themed build instead of a pile of overrides.
The order matters: your variable overrides go above the Bootstrap functions and variables import, or the defaults win.
// custom.scss
$primary: #9CE56D;
$border-radius: 0.5rem;
@import "bootstrap/scss/bootstrap";
// now .btn-primary uses your greenKey point: Overriding variables before the import is the recommended path. Candidates who reach for !important overrides instead reveal they haven't done real theming.
Bootstrap 5 exposes many values as CSS custom properties (variables) like --bs-primary and --bs-gutter-x at the :root and component level. You can override these at runtime with plain CSS, which is useful for theme switching without recompiling Sass.
So there are two customization layers: Sass variables at build time for structural changes, and CSS variables at runtime for theming like light and dark modes.
:root {
--bs-primary: #9CE56D;
}
.card {
--bs-card-bg: #102713;
--bs-card-color: #fff;
}Key point: Distinguishing build-time Sass from runtime CSS variables is a Bootstrap 5 nuance. Naming both, and when each fits, indicates senior.
Bootstrap 5.3 added built-in color modes. You set data-bs-theme='dark' on the html element (or any container) and components read the CSS variables for that mode. You can scope it, so one section can be dark while the rest stays light.
This replaced the older approach of hand-rolling a dark theme with custom Sass, and it works because components now reference CSS variables instead of hard-coded colors.
<html data-bs-theme="dark">
<!-- whole page in dark mode -->
</html>
<div data-bs-theme="dark">
<!-- just this section is dark -->
</div>Most utilities take a breakpoint infix, so you stack classes to change behavior per screen. A single element can be d-flex flex-column on mobile and flex-md-row on tablets, or text-center text-lg-start. The base class applies from the smallest screen; each infix overrides upward.
The discipline is to set the mobile state with the plain class first, then add only the overrides you need, rather than repeating a class at every breakpoint.
<div class="d-flex flex-column flex-md-row justify-content-md-between text-center text-md-start">
<div>Left</div>
<div>Right</div>
</div>The spacer sizes 0 through 5 are multiples of a base $spacer variable, which defaults to 1rem. So size 0 is 0, size 1 is 0.25rem, size 2 is 0.5rem, size 3 is 1rem, size 4 is 1.5rem, and size 5 is 3rem. Because it's driven by a Sass variable, changing $spacer rescales all spacing.
Knowing the scale is tied to one variable is why teams get consistent rhythm: nobody hand-picks pixel gaps.
| Class suffix | Multiplier | Default rem |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 0.25 x $spacer | 0.25rem |
| 2 | 0.5 x $spacer | 0.5rem |
| 3 | 1 x $spacer | 1rem |
| 4 | 1.5 x $spacer | 1.5rem |
| 5 | 3 x $spacer | 3rem |
A carousel is a slideshow built with .carousel, .carousel-inner, and .carousel-item elements, with the first item marked .active. Controls and indicators are optional. It runs on the JS bundle and can auto-cycle via data-bs-ride='carousel'.
The gotchas: exactly one item needs .active or it renders blank, images should be sized consistently to avoid jumpiness, and auto-cycling can hurt accessibility, so provide controls and consider pausing on hover or focus.
<div id="hero" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active"><img src="1.jpg" class="d-block w-100"></div>
<div class="carousel-item"><img src="2.jpg" class="d-block w-100"></div>
</div>
</div>Key point: The 'exactly one .active' rule is the bug interviewers plant. Calling it out before they ask shows hands-on time.
An accordion is a set of collapsible panels. Each item has a header button with data-bs-toggle='collapse' pointing at a collapsible body. Grouping them under a parent with data-bs-parent makes only one panel open at a time.
Drop the data-bs-parent and each panel opens independently, which is the difference between an exclusive accordion and a set of standalone collapses.
<div class="accordion" id="faq">
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button" data-bs-toggle="collapse" data-bs-target="#q1">Question 1</button>
</h2>
<div id="q1" class="accordion-collapse collapse" data-bs-parent="#faq">
<div class="accordion-body">Answer 1</div>
</div>
</div>
</div>Bootstrap provides validation styles through .is-valid and .is-invalid classes on inputs, plus .valid-feedback and .invalid-feedback for messages. You can use the browser's native constraint validation and Bootstrap's .was-validated class on the form to trigger the styles, or apply the classes yourself from JavaScript.
Bootstrap only styles validation; it doesn't do the checking. You still validate with HTML attributes, JavaScript, or server-side, then reflect the result with these classes.
<input type="email" class="form-control is-invalid" required>
<div class="invalid-feedback">Enter a valid email.</div>Key point: The distinction that Bootstrap styles but doesn't validate is the point. Candidates who think it validates for them get caught fast.
The utility API is a Sass map system that generates utility classes. You can add, modify, or remove utilities by editing the $utilities map, so you can create a custom utility (like a new opacity scale or a cursor helper) that outputs responsive and state variants automatically.
It replaces the older approach of hand-writing utility CSS: you describe the utility once in Sass and Bootstrap generates the class family.
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "bootstrap/scss/utilities";
$utilities: map-merge($utilities, (
"cursor": (property: cursor, class: cursor, values: pointer grab)
));
@import "bootstrap/scss/utilities/api";Key point: Awareness of the utility API signals you've customized Bootstrap beyond overriding colors. Few candidates mention it.
Position utilities set the CSS position property: position-static, position-relative, position-absolute, position-fixed, and position-sticky. Combine them with edge helpers like top-0, start-0, end-0, and bottom-0, and translate-middle to center an element on a point.
A common pattern is a badge pinned to the corner of a button using position-absolute with top-0 start-100 and translate-middle.
<button class="btn btn-primary position-relative">
Inbox
<span class="position-absolute top-0 start-100 translate-middle badge bg-danger">9</span>
</button>Bootstrap 5 has no jQuery dependency; its JavaScript is written in plain ES. The only third-party dependency is Popper, used to position dropdowns, tooltips, and popovers. The bundle.min.js file includes Popper, while the plain bootstrap.min.js does not.
Bootstrap 4 and earlier required jQuery, so if you're maintaining an older codebase, removing jQuery is part of a version 5 migration.
Key point: Knowing bundle.js includes Popper but the plain file doesn't explains a whole class of 'my dropdown won't position' bugs. That detail lands well.
Import only the Sass partials you use instead of the whole framework, and run a CSS purge step (like PurgeCSS) that removes classes your markup never references. On the JS side, import individual component modules rather than the full bundle if you only use a few.
The savings are real because the default build ships every component and utility. Tree-shaking the CSS is usually the biggest win.
Key point: Interviewers ask this to see if you treat page weight as a real concern. Naming PurgeCSS and partial imports shows production thinking.
Bootstrap ships with sensible defaults: focus states, ARIA roles on components, and keyboard support for modals and dropdowns. But it doesn't make your page accessible on its own. You still add alt text, label form controls, keep color contrast sufficient, and preserve a logical source order.
The order utilities are a trap here: rearranging columns visually while leaving the DOM order confusing hurts screen reader and keyboard users, so source order should still make sense.
Key point: The point that Bootstrap helps but doesn't guarantee accessibility, plus the order-utility caveat, is what a thoughtful answer includes.
Overrides fail when your custom CSS has equal or lower specificity than Bootstrap's rules, so Bootstrap wins the cascade. Adding a class after Bootstrap's stylesheet doesn't help if the selector is weaker. The clean fix is customizing Sass variables or matching Bootstrap's specificity, not sprinkling !important.
Load order also matters: your override stylesheet must come after Bootstrap's, or your rules never get a chance even at equal specificity.
Key point: Reaching for Sass variables and correct load order instead of !important is the mature answer. Overuse of !important is a red flag the key signal is.
advanced rounds probe internals, design judgment, and production scars. Expect every answer here to draw a follow-up.
The row is a flex container with negative horizontal margins that offset the columns' padding, and columns are flex items with padding (the gutter) and a flex-basis or width set by their col class. Fixed-width columns set flex: 0 0 auto with a percentage width; plain .col uses flex: 1 0 0 to share space.
Bootstrap 5 moved gutters to CSS custom properties and padding rather than margins, which is why .g-* classes now control spacing. Understanding this explains why negative margins on rows and why a stray column outside a row breaks alignment.
Key point: Explaining the negative-margin-plus-padding gutter mechanism is the production signal. It's why columns must live in a row.
Three options: import the plain CSS and write Bootstrap classes on JSX (simple, but you manage the JS components yourself), use React-Bootstrap which reimplements components as React components (no Bootstrap JS, real props and state), or use a wrapper like Reactstrap. React-Bootstrap is the common choice because it avoids direct DOM manipulation that fights React's model.
The trade-off with plain Bootstrap JS in React is that its imperative DOM control (toggling classes, managing modals) collides with React's declarative rendering, so you either wrap it carefully or use a React-native component library.
| Approach | JS handling | Best when |
|---|---|---|
| Plain CSS + classes | You manage manually | Static UI, minimal interactivity |
| React-Bootstrap | React components, no BS JS | Standard React apps |
| Reactstrap | React components | Teams preferring its API |
Key point: Naming the imperative-versus-declarative clash is what this question is really after. It shows you understand why a wrapper exists.
Create a single Sass entry file: import Bootstrap's functions, override variables and maps, import Bootstrap's variables and the rest of the framework (or just the partials you need), then add your own components below. Compile with your bundler. This keeps overrides in one place and survives Bootstrap upgrades because you're not editing vendor files.
The maintainability win is that a version bump means updating the dependency and recompiling, since your customizations sit in variables and your own partials, not scattered overrides.
// app.scss
@import "bootstrap/scss/functions";
// your overrides
$primary: #9CE56D;
$grid-gutter-width: 2rem;
@import "bootstrap/scss/variables";
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/root";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/utilities/api";
// your components last
@import "components/hero";Key point: The 'never edit vendor files, override through variables' principle is the whole answer. It's what makes upgrades painless.
Bootstrap's Sass is split into partials (grid, buttons, forms, utilities) so you can import only what you use. The catch is dependency order: functions, variables, maps, and mixins must come first, because component partials reference them. Import a component without its prerequisites and Sass throws undefined-variable errors.
The safe pattern is to always import the foundation (functions through mixins), then cherry-pick components. Skipping utilities is fine; skipping variables is not.
Key point: The dependency-order gotcha (functions and variables before components) is the trap. Knowing it means you've actually done a slim build.
Bootstrap fits when you want finished components and a consistent look with minimal design work: internal tools, admin panels, prototypes, or teams without a dedicated designer. You get navbars, modals, and forms that look done immediately. Tailwind fits when you have a custom design system and want full control over every visual detail without fighting component defaults.
The honest framing is about who owns the design. Bootstrap gives you decisions; Tailwind gives you primitives. For a distinctive brand you'll customize heavily, Tailwind's utility model wins; for speed to a working, conventional UI, Bootstrap wins.
| Factor | Lean Bootstrap | Lean Tailwind |
|---|---|---|
| Design freedom | Conventional UI is fine | Distinctive custom design |
| Speed to working UI | Prebuilt components | Build from primitives |
| Team | No dedicated designer | Design system owner exists |
| Markup style | Fewer classes, components | Utility classes everywhere |
Key point: Framing it as 'who owns the design decisions' scores far better than 'Bootstrap is older, Tailwind is newer'.
Audit the breaking changes first: remove jQuery and rewrite any jQuery plugin calls as the new JS API, update data-* attributes to data-bs-*, swap directional utilities (ml/mr to ms/me), and rename the dropped or renamed classes. Do it behind a branch with visual regression checks, page by page.
The riskiest parts are custom JavaScript that relied on jQuery and Bootstrap's plugin events, and any Sass that overrode variables that were renamed. Grep for jQuery usage and old data attributes to scope the work before estimating.
Key point: A migration plan that leads with an audit and visual regression testing, not a big-bang rewrite, is The production-ready answer.
The default CSS bundle is large because it includes every component and utility, so unused styles inflate the download and the browser's style computation. Ship a purged, partial build. On the JS side, the bundle loads Popper even if you only use a modal, so import individual components when you use few.
Also watch render cost: deeply nested grids and many utility classes are cheap, but heavy use of components like tooltips that init on load can add JavaScript work. Measure with a real page rather than guessing.
Key point: The escalation (purge CSS, partial JS imports, then measure) mirrors real optimization. the question needs the discipline, not a single trick.
Prefer the supported levers in order: override the component's Sass variables (or its CSS custom properties for runtime theming), then use the utility API for new utilities, and only then add scoped custom CSS that matches Bootstrap's specificity. Never edit the vendor Sass. This keeps your changes in your files so a Bootstrap upgrade doesn't wipe them.
For genuinely new components, build them as your own Sass partials that reuse Bootstrap's mixins and variables, so they inherit your theme and stay consistent.
Key point: The ordered ladder (variables, then CSS vars, then utility API, then scoped CSS) is exactly what a maintainer wants to hear.
Bootstrap 5 ships a separate RTL stylesheet and uses logical property naming (start and end instead of left and right) so layouts mirror correctly. You set dir='rtl' and lang on the html element and load bootstrap.rtl.css. Because the directional utilities are ms/me rather than ml/mr, they flip automatically for RTL.
The reason version 5 renamed the utilities to start/end was exactly this: logical directions mirror without you writing separate rules, which is why the migration renamed ml/mr.
<html lang="ar" dir="rtl">
<head>
<link href="bootstrap.rtl.min.css" rel="stylesheet">
</head>
</html>Key point: Connecting the start/end utility rename to RTL support ties two topics together and indicates deep familiarity.
Reproduce it at the reported breakpoint first using dev tools' responsive mode, then check the usual suspects: a column outside a .row (breaks the negative-margin gutter math), widths not adding to 12, a missing container, or a conflicting custom CSS rule winning on specificity. Inspect the computed styles to see which rule actually applies.
Then fix at the right layer and confirm across breakpoints, not just the one that broke. The structure matters more than any single check: reproduce, inspect computed styles, form a hypothesis, fix, verify responsively.
Debugging a broken Bootstrap layout
The methodology is the technical core more than the specific fix. The steps out loud in the interview.
Key point: The methodology is; the specific fix is supporting evidence.
Bootstrap includes print display utilities: d-print-none hides an element when printing, and d-print-block shows one only in print. Combine them with screen display utilities to build a layout that drops navigation and buttons on paper while keeping content.
For anything beyond show and hide, you add your own @media print CSS, since Bootstrap only ships the display helpers for print, not a full print theme.
<nav class="navbar d-print-none">Hidden on paper</nav>
<div class="d-none d-print-block">Only visible when printing</div>Offcanvas is a sidebar panel that slides in from an edge, added in Bootstrap 5. It's built with .offcanvas and toggled with data-bs-toggle='offcanvas'. It's the modern pattern for mobile navigation drawers and filter panels that shouldn't take a full modal.
You choose placement (start, end, top, bottom) and whether the backdrop and body scroll are enabled. It replaced the common hack of building a custom slide-in menu by hand.
<button data-bs-toggle="offcanvas" data-bs-target="#menu" class="btn btn-primary">Menu</button>
<div class="offcanvas offcanvas-start" id="menu">
<div class="offcanvas-body">Navigation links</div>
</div>Bootstrap's grid is flexbox-based and one-dimensional per row: great for the common 12-column responsive layouts with prebuilt breakpoint classes. Native CSS Grid is two-dimensional, controlling rows and columns together, which fits complex layouts like dashboards with areas that span both axes.
Reach for Bootstrap's grid when the layout is column-based and you want breakpoint classes for free; reach for CSS Grid when you need true two-dimensional control or template areas. Bootstrap 5 even adds a small CSS Grid opt-in for this reason.
| Aspect | Bootstrap grid | CSS Grid |
|---|---|---|
| Model | Flexbox, one axis per row | Two-dimensional |
| Breakpoints | Built-in classes | You write media queries |
| Best at | Column layouts, fast start | Complex 2D layouts, areas |
Key point: Knowing Bootstrap's grid is flexbox (one-dimensional) versus CSS Grid (two-dimensional) is the distinction. Mentioning Bootstrap 5's CSS Grid opt-in is a bonus.
Two layers. For structural differences, compile separate Sass builds per brand by swapping the variable overrides, producing brand-a.css and brand-b.css. For runtime switching without a rebuild, lean on Bootstrap 5's CSS custom properties: scope --bs-primary and friends under a theme class or data attribute and toggle it on a container.
The runtime approach is what makes live theme switching (per tenant, per user) practical, because you're changing CSS variable values rather than swapping whole stylesheets.
[data-brand="growth"] {
--bs-primary: #9CE56D;
--bs-body-bg: #102713;
}
[data-brand="lite"] {
--bs-primary: #0d6efd;
}Key point: Splitting build-time Sass (structural) from runtime CSS variables (live switching) is the architecture answer interviewers hope for.
Two approaches. Classic grid: pick a col width that divides 12, so col-6 gives two per row, col-4 gives three, col-3 gives four; combine breakpoint infixes to change the count per screen. Row columns: put .row-cols-* on the row itself, like row-cols-1 row-cols-md-2 row-cols-lg-4, and Bootstrap sizes the children so you get one per row on mobile and four on large.
Row columns are the cleaner tool for a uniform card gallery because you set the count once on the row instead of on every column. The classic width classes are better when columns have different widths.
<!-- 1 per row on phones, 2 on tablets, 4 on desktops -->
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-4 g-3">
<div class="col"><div class="card">Card</div></div>
<div class="col"><div class="card">Card</div></div>
<div class="col"><div class="card">Card</div></div>
<div class="col"><div class="card">Card</div></div>
</div>| Goal | Width class | Row-cols class |
|---|---|---|
| 2 per row | col-6 | row-cols-2 |
| 3 per row | col-4 | row-cols-3 |
| 4 per row | col-3 | row-cols-4 |
Key point: Knowing row-cols-* exists (not just dividing 12 by hand) shows current Bootstrap 5 fluency. It's the right tool for equal-count galleries.
Add subresource integrity (the integrity attribute with a hash) and crossorigin so the browser refuses a tampered file, pin an exact version rather than a floating one, and weigh the reliability of relying on a third-party host versus self-hosting. A CDN gives caching and speed but adds an external dependency and a supply-chain surface.
For most production apps, self-hosting a purged, version-pinned build alongside your other assets is safer and often faster after the first load, since you control caching and remove the extra DNS and connection to a third party.
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-..."
crossorigin="anonymous">Key point: Naming subresource integrity and version pinning shows you think about supply-chain risk, which is exactly what this question screens for.
Bootstrap wins when you want a consistent, prebuilt component library and a fast start without designing a system from scratch, which fits internal tools, prototypes, and teams that value convention over custom design. It ships opinionated components (navbars, modals, cards) that look finished out of the box. The trade-off: those defaults have a recognizable look, and heavy customization means overriding Sass or fighting specificity. Tailwind takes the opposite stance with low-level utilities and no components, so you build any design but write more markup. Knowing these trade-offs out loud is itself an interview signal: it shows you pick tools on merits, not habit.
| Tool | Approach | Best at | Watch out for |
|---|---|---|---|
| Bootstrap | Components + utilities | Fast starts, prebuilt UI, internal tools | Recognizable default look, override friction |
| Tailwind CSS | Utility-first, no components | Custom designs, design systems | Verbose markup, build step, no ready components |
| Foundation | Components + grid | Enterprise, email templates | Smaller community, fewer resources now |
| Plain CSS | Write everything yourself | Full control, zero framework weight | Slow to build, you own responsiveness |
Prepare in layers, and practice out loud. Most Bootstrap rounds move from concept questions about the grid and breakpoints to live layout building to a customization or debugging discussion, so rehearse each stage rather than only reading answers.
The typical Bootstrap interview flow
Earlier rounds increasingly run as AI coding interviews. The concepts on this page are what gets probed at every stage.
10 questions, about 6 minutes. Score 70% or higher to earn a shareable certificate.
Hyring builds the AI Coding Interviewer that runs live technical rounds in 20+ languages for 5,000+ hiring teams. These Bootstrap questions and scoring notes reflect what actually gets asked and evaluated inside the interviews we host.
See how the AI Coding Interviewer works