Loading...

How to Add Bootstrap 5 to Nuxt 3 – A Beginner’s Guide

Last update: 8/7/2024
Nuxt 3 and Bootstrap 5 title image

Intro

Bootstrap is one of the most popular CSS framework in the area of web development. It provides you with many responsive components, and it can be used within various Frontend-Frameworks, such as Nuxt 3. Bootstrap 5 can be added to a Nuxt 3 project in various ways, ranging from loading compiled and bundled CSS and JavaScript files from external sources through plugins to adding only individual Sass and JavaScript source code files.

In this guide

In this beginner guide, a Nuxt 3 application is created which serves as a base to demonstrate three different ways to add Bootstrap 5 CSS and JavaScript to your project. In the first method, Bootstrap 5 is loaded as an external resource from a CDN. The second method shows how to host Bootstrap 5 by yourself and load it locally, while the third method shows how Bootstrap 5 is loaded when distributed through the npm package manager.

Setup

  • Nuxt 3.10.1
  • Vue 3.4.15
  • Bootstrap 5.3.2
  • node 18.12.1
  • npm 9.8.1

Prerequisites

  • Basic understanding of how to work with Nuxt 3
  • Basic understanding of how to work with Bootstrap 5 and what types of Bootstrap are available, e.g. compiled CSS and JavaScript bundles vs. source code (for more information check the documentation)
  • node.js and npm are installed on your machine

Base App

The base app created in this section will serve as a starting point for three methods described later on. Therefore, open your terminal at the desired working directory and create a new Nuxt 3 application by executing as described in the documentation:

npx nuxi@latest init nuxt3_bootstrap5_base

You will get prompt to choose a package manager. Select npm in this context of this tutorial and wait until the new Nuxt 3 project named nuxt3_bootstrap5_base is created. Note that at the time of writing this article latest initializes Nuxt version 3.10.1.

Navigate to the project root folder and start the Nuxt 3 app in development mode:

cd nuxt3_bootstrap5_base
npm run dev

Now open your browser and go to http://localhost:3000 to follow the upcoming changes.

In order to verify that Bootstrap 5 is loaded and working correctly later on, we need a Bootstrap component in our application which requires both, CSS and JavaScript to work correctly. In addition, we want to make sure that we can override Bootstrap’s CSS custom properties (CSS variables) and that we can interact with the Bootstrap components programmatically. Therefore, open app.vue and replace everything inside with the following snippet:

app.vue
<script setup lang="ts">
onMounted(() => {
  try {
    const collapse = new bootstrap.Collapse('#navbarSupportedContent');
    collapse.show();
  } catch (e) {
    console.log('Bootstrap error: ', e);
  }
});
</script>

<template>
  <nav class="navbar bg-body-tertiary">
    <div class="container-fluid">
      <a class="navbar-brand" href="#">Navbar</a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="#">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">Link</a>
          </li>
          <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
              Dropdown
            </a>
            <ul class="dropdown-menu">
              <li><a class="dropdown-item" href="#">Action</a></li>
              <li><a class="dropdown-item" href="#">Another action</a></li>
              <li><hr class="dropdown-divider"></li>
              <li><a class="dropdown-item" href="#">Something else here</a></li>
            </ul>
          </li>
          <li class="nav-item">
            <a class="nav-link disabled" aria-disabled="true">Disabled</a>
          </li>
        </ul>
        <form class="d-flex" role="search">
          <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
          <button class="btn btn-outline-success" type="submit">Search</button>
        </form>
      </div>
    </div>
  </nav>
</template>

The template contains boilerplate code for a Bootstrap 5 navbar component from the official documentation. We only remove navbar-expand-lg from the class attribute on the <nav> tag to make the demonstration work on mobile and desktop devices later on.

The code inside <script setup> expands the navbar programmatically. We therefore need to create a new instance of the Bootstrap Collapse plugin with on the element which contains the collapsible part of the navbar with new bootstrap.Collapse('#navbarSupportedContent‘). The show() method expands the corresponding part of the navbar subsequently. We wrap this with try {…} catch {…} to control for potential errors. Since bootstrap.Collapse() uses querySelector() to find the corresponding element in the DOM, we need to wait until the component’s DOM is created with Vue’s onMounted() lifecycle hook.

To ensure that we are able to override Bootstrap CSS variables, create a new folder in your project root assets/ with main.css inside and add the following snippet:

main.css
:root {
  --bs-tertiary-bg-rgb: 101, 127, 220;
}

This overrides the CSS variable --bs-tertiary-bg-rgb which is used by Bootstrap to color the background of the navbar with a blue color. Note that instead of the entire rgb() functional notation, the variable only contains the rgb values, separated by commas. These values are then wrapped inside the Bootstrap CSS with the rgba() function, which will be loaded later on.

To process the main.css file, it must be referenced in nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  css: ['@/assets/main.css']
})

If you switch to your browser now and visit http://localhost:3000 you will see the unstyled navbar and an error in your browser console indicating a reference error, since Bootstrap is not yet available.

Illustration: Nuxt 3 base app

This application serves as our base for each of the following methods.

GitHub: Source Code Base App

Method 1: Load Bootstrap 5 CSS and JavaScript From a CDN

The easiest way to use Bootstrap 5 in Nuxt is to load the CSS and JavaScript files via <link> and <script> tags in the documents <head> from a content delivery network (CDN) for which Bootstrap provides links in their documentation.

Starting from our base app: To add the tags to the document <head>, we need to change the nuxt.config.ts as follows:

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      link: [
        {
          rel: 'stylesheet',
          href: 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css'
        }
      ],
      script: [
        {
          src: 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js',
          tagPosition: 'bodyClose'
        }
      ]
    }
  },
  css: ['@/assets/main.css']
})

The configuration for the <head> is placed in app.head and is applied to every page of the application. Both, link and script take a list of objects whereby each object is converted to a <link> or <script> tag respectively with the corresponding attributes as defined within the object:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>

Note: Following the Bootstrap 5 documentation we insert the <script> tag before the colising </body> tag with the attribute tagPosition: 'bodyClose' in nuxt.config.ts.

Now switch to your browser and wait for the Nuxt 3 application to be updated by the development server.

Illustration: Bootstrap 5 loaded in Nuxt 3 via CDN

As you can see, the Bootstrap navbar is now styled as defined in the loaded CSS file, whereas the background is colored blue according to the CSS variable override. In addition, the navbar expands after the component is mounted and no reference errors appear in the browser console. This verifies that both CSS and JavaScript are loaded correctly.

GitHub: Source Code Nuxt 3 + Bootstrap 5 (CDN)

Method 2: Self-Host Bootstrap 5 CSS and JavaScript

If you want to use Bootstrap’s pre-compiled and bundled CSS and JavaScript files similar to as with Method 1 but without loading them from a CDN, there are different possibilities to add the files to your Nuxt project. The easiest way is to download and add them to the public/ directory in your project root folder. Since files in the public/ folder are copied to the server root as-is, you only have to modify the paths in your nuxt.config.ts.

Donwload the files under the Compiled CSS and JS section from the Bootstrap 5 download page and unzip them after the download completes. Create new folders css/ and js/ inside public/, copy the CSS and JavaScript files you need and paste them in the the corresponding folder inside public/. In the context of this tutorial, we copy bootstrap.min.css and bootstrap.bundle.min.js and place them in public/css/ and public/js/ respectively. As in Method 1 we add the paths to the CSS and JavaScript file in config.nuxt.ts.

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      link: [
        {
          rel: 'stylesheet',
          href: '/css/bootstrap.min.css'
        }
      ],
      script: [
        {
          src: '/js/bootstrap.bundle.min.js',
          tagPosition: 'bodyClose'
        }
      ]
    }
  },
  css: ['@/assets/main.css']
})

The corresponding <link> will now be added to the <head> tag while <script> will be added before the closing </body> tag as defined with the attribute tagPosition: 'bodyClose'`` during build, both with relative paths which corresponds to the structure inside public/```:

<link rel="stylesheet" href="/css/bootstrap.min.css">
<script src="/js/bootstrap.bundle.min.js"></script>

If you switch to your browser now and visit http://localhost:3000, the development server should update your application. You will see that Bootstrap is loaded correctly by the styled navbar with the blue background from our CSS variable override. In addition, the navbar automatically expands after the component’s DOM is created without errors in the browser console.

Illustration: Bootstrap 5 self-hosted in Nuxt 3

GitHub: Source Code Nuxt 3 + Bootstrap 5 (Self-Hosted)

Method 3: Add Bootstrap 5 CSS and JavaScript with NPM

You can use the npm package manager to make Bootstrap 5 available in your Nuxt 3 project. This method takes a little more effort upfront, since you need to write a plugin to import the JavaScript. However, the advantage is that you can update Bootstrap with npm more conveniently.

In order to install Bootstrap 5, switch to your terminal and execute the following command in your project root folder:

npm install bootstrap@5.3.2

npm now installs Bootstrap version 5.3.2 to the node_modules folder and adds it as a dependency in the package.json file. The pre-compiled CSS and JavaScript files reside in node_modules/bootstrap/dist/. To reference the CSS, add the paths to your nuxt.config.ts as follows:

nuxt.config.ts
export default defineNuxtConfig({
  css: ['bootstrap/dist/css/bootstrap.min.css']
})

Note that Nuxt 3 resolves the path without including node_modules/ in the path.

The JavaScript bundle must be loaded as a plugin. In Nuxt 3, Vue plugins reside in the plugins/ folder in the project root, which are automatically registered by Nuxt and therefore do not need to be defined in nuxt.config.ts. Create a new folder plugins/ in your project root. Inside plugins/ create a new file bootstrap.client.ts for the Bootstrap plugin. The file name consists of three parts: an arbitrary name (in this case bootstrap), the suffix client which tells Nuxt, that the plugin is only required in the browser (for more information on the plugin suffix see the documentation) and the file extension ts.

bootstrap.client.ts
import bootstrap from 'bootstrap/dist/js/bootstrap.bundle.min';

export default defineNuxtPlugin(nuxtApp => {
    nuxtApp.provide('bs', bootstrap);
})

At the top, we import the bundled JavaScript from the node_modules/ folder. A plugin in Nuxt 3 is then defined with defineNuxtPlugin which is passed the Nuxt runtime context nuxtApp as an argument. Next, we provide the Bootstrap JavaScript object as a helper named bs to the app context, with nuxtApp.provide(…). The Bootstrap JavaScript can then be used in components, composables and plugins. To do that, the <script setup> of app.vue from our base app must be modified as follows:

app.vue
<script setup>
const { $bs } = useNuxtApp();

onMounted(() => {
  try {
    const collapse = new $bs.Collapse('#navbarSupportedContent');
    collapse.show();
  } catch (e) {
    console.log('Bootstrap error: ', e);
  }
});
</script>

First, the previously defined Bootstrap helper bs (prefixed with $) must be loaded from the useNuxtApp() composable which provides access to the app context during runtime. Then, instead of creating a new instance of the Collapse instance over the bootstrap object, we create it from the helper $bs ( $bs.Collapse('#navbarSupportedContent').

Switch to your browser and wait for Nuxt to be updated.

Illustration: Bootstrap 5 loaded in Nuxt 3 via NPM

As you can see, the navbar is styled according to the Bootstrap 5 stylesheets and the background color is overridden as defined in the main.css CSS file. The navbar also programmatically expanded when the components DOM has been created without any errors in the browser console.

GitHub: Source Code Nuxt 3 + Bootstrap 5 (NPM)

Alternatives Methods and Restrictions

Note: Since Bootstrap 5 is a large framework which is available in different forms (Downloads and Content from the documentation) there are alternative methods which might fit your needs better, such as loading the Sass source files instead of CSS which allows you to take advantage of many mixins, functions and more. It is also possible to use Bootstrap only on single pages of a Nuxt 3 application with useHead().

The methods described are tested with npm generate and npm build with ssr set to both true and false to ensure high compatibility. However, when it comes to Bootstrap’s JavaScript, you should keep in mind that you might face limited compatibility when using Bootstrap 5 JavaScript in your Nuxt 3 framework, since Bootstrap needs access to the entire DOM, as well as both frameworks might manipulate the same object which can lead to bugs (documentation).

Summary

Bootstrap 5’s stylesheets and JavaScript are available in different forms and can be used in Nuxt 3 in different ways. Loading the pre-compiled and bundled CSS and JavaScript files from a CDN, self-hosting them and installing Bootstrap via npm are only three ways out of many. When it comes to the JavaScript part, one should keep in mind, that compatibility might be restricted, since Bootstrap assumes full knowledge of the DOM.

Report a problem (E-Mail)