Performance
Some of Bootstrap 4's performance cost is fixable with better build habits. One piece of it isn't — it's baked into choosing Bootstrap 4 at all. Let's separate the two, and then apply the fixable ones to TrailMap.
The Unavoidable Cost: jQuery + Popper.js
Every interactive Bootstrap 4 component — modal, dropdown, collapse, carousel, tooltip, popover, scrollspy — is implemented as a jQuery plugin, and the positioning-heavy ones (tooltips, popovers, dropdowns) additionally depend on Popper.js. That means a real download-and-parse cost on every single page that loads Bootstrap 4's JS, whether or not that particular page actually uses a dropdown or a modal:
| Dependency | Why Bootstrap 4 needs it |
|---|---|
| jQuery | Every component's JavaScript is written as a jQuery plugin ($.fn.modal, $.fn.collapse, etc.) — there's no jQuery-free code path |
| Popper.js | Powers the positioning math for dropdowns, tooltips, and popovers so they don't render off-screen |
Fixable: Build Only the Sass Modules You Use
The CDN's bootstrap.min.css bundles every component's styles, whether or not the
page uses them — carousel styles ship even to a page with no carousel. With the Sass workflow
from Sass Customization, you control which component
partials get imported at all:
// custom.scss — only pull in what TrailMap actually uses
@import "../node_modules/bootstrap/scss/functions";
@import "../node_modules/bootstrap/scss/variables";
@import "../node_modules/bootstrap/scss/mixins";
@import "../node_modules/bootstrap/scss/grid";
@import "../node_modules/bootstrap/scss/card";
@import "../node_modules/bootstrap/scss/navbar";
// no carousel, no toasts, no jumbotron partial — TrailMap doesn't use them
Skip the components TrailMap never uses (say, the carousel or toasts) and the compiled CSS is meaningfully smaller than the full CDN bundle, with zero visual difference on the pages that were never using those styles anyway.
Fixable: Minimize Custom CSS Overrides
Every additional stylesheet — especially one full of !important overrides fighting
the compiled CSS, as covered in Sass Customization — is
more bytes the browser has to download and more specificity conflicts it has to resolve. A
project that overrides Sass $variables before compiling needs little to no
override stylesheet at all; a project papering over the CDN build with !important
rules accumulates more of them every time a new component needs the same treatment.
Worked Example: Lazy-Loading Images in TrailMap's Card Grid
TrailMap's trail card grid (from the Advanced Grid
lesson) can easily have dozens of trail photos on one page. The native loading="lazy"
attribute defers loading any image until it's about to scroll into view — no Bootstrap 4 class
involved, just a plain HTML attribute on the <img>:
<div class="card">
<img src="ridgeline-loop.jpg" class="card-img-top"
loading="lazy" alt="Ridgeline Loop trail winding through pine forest">
<div class="card-body">
<h5 class="card-title">Ridgeline Loop</h5>
</div>
</div>
Only the trail photos near the top of the page load immediately; the rest load as the visitor scrolls, which matters a lot on a page that might list fifty or more trail cards at once.