Use Bootstrap with Astro

Dominik Rüttiger 5 min read

Use Bootstrap with Astro project screenshot

Modern web development is based on components, whether or not a front-end framework like Angular or React is used. Combined with wide browser support for CSS variables, I would argue that it has never been easier to style using plain CSS.

With that out of the way, Bootstrap is still one of the most popular CSS frameworks and here is how to use it with Astro.

TL;DR

You can find the final result in this GitHub repository.

It includes a Dev Container configuration with all requirements.

Create a new Astro project

We start with a fresh Astro project:

Terminal window
npm create astro@latest -- --template minimal

Add Bootstrap npm packages

Install the following packages:

Terminal window
npm install bootstrap sass
npm install --save-dev @types/bootstrap

Add Bootstrap CSS styles

The key to using Bootstrap efficiently is to include only the CSS you need. Create a new Sass file that imports the necessary packages:

src/styles/bootstrap.scss
// Required functions import
@import 'bootstrap/scss/functions';
// Optional variable overrides
$primary: #ffa500;
// Required imports
@import 'bootstrap/scss/variables';
@import 'bootstrap/scss/variables-dark';
@import 'bootstrap/scss/maps';
@import 'bootstrap/scss/mixins';
@import 'bootstrap/scss/root';
// Optional components
@import 'bootstrap/scss/utilities';
@import 'bootstrap/scss/reboot';
@import 'bootstrap/scss/type';
@import 'bootstrap/scss/containers';
@import 'bootstrap/scss/images';
@import 'bootstrap/scss/nav';
// @import 'bootstrap/scss/accordion';
// @import 'bootstrap/scss/alert';
// @import 'bootstrap/scss/badge';
// @import 'bootstrap/scss/breadcrumb';
// @import 'bootstrap/scss/button-group';
// @import 'bootstrap/scss/buttons';
// @import 'bootstrap/scss/card';
// @import 'bootstrap/scss/carousel';
// @import 'bootstrap/scss/close';
// @import 'bootstrap/scss/dropdown';
// @import 'bootstrap/scss/forms';
// @import 'bootstrap/scss/grid';
// @import 'bootstrap/scss/list-group';
// @import 'bootstrap/scss/modal';
// @import 'bootstrap/scss/navbar';
// @import 'bootstrap/scss/offcanvas';
// @import 'bootstrap/scss/pagination';
// @import 'bootstrap/scss/placeholders';
// @import 'bootstrap/scss/popover';
// @import 'bootstrap/scss/progress';
// @import 'bootstrap/scss/spinners';
// @import 'bootstrap/scss/tables';
// @import 'bootstrap/scss/toasts';
// @import 'bootstrap/scss/tooltip';
// @import 'bootstrap/scss/transitions';
// Optional helpers
// @import 'bootstrap/scss/helpers';
// Optional utilities
@import 'bootstrap/scss/utilities/api';

During development or debugging, you could also temporarily import everything with:

src/styles/bootstrap.scss
// Optional variable overrides
$primary: #ffa500;
// Import everything
@import 'bootstrap/scss/bootstrap';

For more details, see the Sass page in the official Bootstrap documentation.

Add Layout and pages

Create a new Astro file that will serve as the main page layout. Same as with CSS, make sure you import only the JavaScript modules that you need:

src/layouts/Layout.astro
---
import '../styles/bootstrap.scss';
---
<!doctype html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="utf-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="generator" content={Astro.generator} />
<title>Bootstrap with Astro</title>
<meta name="description" content="Use Bootstrap with Astro" />
</head>
<body>
<slot />
<script>
// Import only what you need
// import 'bootstrap/js/dist/alert';
// import 'bootstrap/js/dist/button';
// import 'bootstrap/js/dist/carousel';
// import 'bootstrap/js/dist/collapse';
// import 'bootstrap/js/dist/dropdown';
// import 'bootstrap/js/dist/modal';
// import 'bootstrap/js/dist/offcanvas';
// import 'bootstrap/js/dist/popover';
// import 'bootstrap/js/dist/scrollspy';
// import 'bootstrap/js/dist/tab';
// import 'bootstrap/js/dist/toast';
// import 'bootstrap/js/dist/tooltip';
</script>
</body>
</html>

During development or debugging, you could also temporarily import everything with:

// Import everything
import 'bootstrap/dist/js/bootstrap';

To use the layout replace the contents of the index page with the following Bootstrap example content:

src/pages/index.astro
---
import Layout from '../layouts/Layout.astro';
---
<Layout>
<div class="container">
<header class="d-flex justify-content-center py-3">
<ul class="nav nav-pills">
{
['Home', 'Features', 'Pricing', 'FAQs', 'About'].map((n, i) => (
<li class="nav-item">
<a href="#" class:list={['nav-link', { active: i === 0 }, {'text-black': i === 0}]}>{n}</a>
</li>
))
}
</ul>
</header>
<main class="text-center">
<h1 class="display-1">Hi Bootstrap!</h1>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-rocket-takeoff mt-5 img-fluid" style="width: 20rem; height: 20rem;" viewBox="0 0 16 16">
<path d="M9.752 6.193c.599.6 1.73.437 2.528-.362s.96-1.932.362-2.531c-.599-.6-1.73-.438-2.528.361-.798.8-.96 1.933-.362 2.532"/>
<path d="M15.811 3.312c-.363 1.534-1.334 3.626-3.64 6.218l-.24 2.408a2.56 2.56 0 0 1-.732 1.526L8.817 15.85a.51.51 0 0 1-.867-.434l.27-1.899c.04-.28-.013-.593-.131-.956a9 9 0 0 0-.249-.657l-.082-.202c-.815-.197-1.578-.662-2.191-1.277-.614-.615-1.079-1.379-1.275-2.195l-.203-.083a10 10 0 0 0-.655-.248c-.363-.119-.675-.172-.955-.132l-1.896.27A.51.51 0 0 1 .15 7.17l2.382-2.386c.41-.41.947-.67 1.524-.734h.006l2.4-.238C9.005 1.55 11.087.582 12.623.208c.89-.217 1.59-.232 2.08-.188.244.023.435.06.57.093q.1.026.16.045c.184.06.279.13.351.295l.029.073a3.5 3.5 0 0 1 .157.721c.055.485.051 1.178-.159 2.065m-4.828 7.475.04-.04-.107 1.081a1.54 1.54 0 0 1-.44.913l-1.298 1.3.054-.38c.072-.506-.034-.993-.172-1.418a9 9 0 0 0-.164-.45c.738-.065 1.462-.38 2.087-1.006M5.205 5c-.625.626-.94 1.351-1.004 2.09a9 9 0 0 0-.45-.164c-.424-.138-.91-.244-1.416-.172l-.38.054 1.3-1.3c.245-.246.566-.401.91-.44l1.08-.107zm9.406-3.961c-.38-.034-.967-.027-1.746.163-1.558.38-3.917 1.496-6.937 4.521-.62.62-.799 1.34-.687 2.051.107.676.483 1.362 1.048 1.928.564.565 1.25.941 1.924 1.049.71.112 1.429-.067 2.048-.688 3.079-3.083 4.192-5.444 4.556-6.987.183-.771.18-1.345.138-1.713a3 3 0 0 0-.045-.283 3 3 0 0 0-.3-.041Z"/>
<path d="M7.009 12.139a7.6 7.6 0 0 1-1.804-1.352A7.6 7.6 0 0 1 3.794 8.86c-1.102.992-1.965 5.054-1.839 5.18.125.126 3.936-.896 5.054-1.902Z"/>
</svg>
</main>
</div>
</Layout>

Add more pages using the same <Layout> if you like.

Bootstrap icons

There are many options to include icons. I recommend to use the official Bootstrap Icons and add the SVG directly to the Astro/HTML files.

Just head over to their docs, select an icon that you like, copy the SVG and paste it into your page. No need to overcomplicate things.

Run the development server

To check the final result run:

Terminal window
npm run dev

Running in production

Only including the CSS and JavaScript that we need, and without any further optimization, the Lighthouse score rocks!

Lighthouse Score of website using Bootstrap with Astro

This setup can be optimized even more. But don’t overdo it. Simplicity is king.

Set caching header

All files in the dist/_astro folder are compiled by Astro and an hash is included in the file name. If the content changes the filename will change, too.

Therefore we can tell the browser that it is safe to cache these files forever. The browser will not even check if there is a new version, making subsequent page visits blazingly fast.

For the classic Apache webserver that many hosters still use, this can easily be configured by creating the following file:

public/_astro/.htaccess
<FilesMatch "\.(css|js|webp|jpg|jpeg|png|svg)$">
Header set Cache-Control "max-age=31536000"
</FilesMatch>

Minimize CSS

If you had been exposed to Tailwind for a long time, you will feel the urge to minify Bootstrap’s CSS. This is totally possible to do, and can easily be automated with the astro-purgecss integration .

But in my opinion, it is not worth bringing in a new dependency to your project. The compiled Bootstrap CSS file is usually really small:

This is nothing compared the megabytes of web bloat these days.

Tags

#astro #bootstrap #css #webperformance

Share

Hacker News LinkedIn Reddit Twitter/X