How to Use Custom Bootstrap in a Nuxt Project demo repo

Bootstrap is an open source toolkit for developing with HTML, CSS, and JS.

👣 Steps

  1. Create a Nuxt project and install Bootstrap, jQuery, and Popper.js. If your components do not need JavaScript, jQuery an Popper.js can be omitted.
npx create-nuxt-app nuxt-demo
cd nuxt-demo
npm i bootstrap jquery popper.js
  1. Customize Bootstrap, e.g. in assets/custom-bootstrap.scss. The path to the default variables is bootstrap/scss/_variables.scss.
$primary: #359499;
$secondary: #98ddde;
$success: #81894e;
$info: #185190;
$warning: #ffdb3b;
$danger: #f36e60;
$light: #f5fbfb;
$dark: #040b0c;

$link-hover-decoration: none;
$border-radius: 0;
$font-family-sans-serif: "Fira Sans", sans-serif;
$font-family-monospace: "Fira Mono", monospace;
$font-weight-bold: 600;

@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins";
@import "~bootstrap/scss/root";
@import "~bootstrap/scss/reboot";
@import "~bootstrap/scss/type";
@import "~bootstrap/scss/images";
// @import "~bootstrap/scss/code";
@import "~bootstrap/scss/grid";
@import "~bootstrap/scss/tables";
@import "~bootstrap/scss/forms";
@import "~bootstrap/scss/buttons";
@import "~bootstrap/scss/transitions";
@import "~bootstrap/scss/dropdown";
@import "~bootstrap/scss/button-group";
// @import "~bootstrap/scss/input-group";
// @import "~bootstrap/scss/custom-forms";
@import "~bootstrap/scss/nav";
@import "~bootstrap/scss/navbar";
@import "~bootstrap/scss/card";
@import "~bootstrap/scss/breadcrumb";
// @import "~bootstrap/scss/pagination";
// @import "~bootstrap/scss/badge";
@import "~bootstrap/scss/jumbotron";
// @import "~bootstrap/scss/alert";
// @import "~bootstrap/scss/progress";
// @import "~bootstrap/scss/media";
@import "~bootstrap/scss/list-group";
// @import "~bootstrap/scss/close";
// @import "~bootstrap/scss/toasts";
// @import "~bootstrap/scss/modal";
// @import "~bootstrap/scss/tooltip";
// @import "~bootstrap/scss/popover";
// @import "~bootstrap/scss/carousel";
// @import "~bootstrap/scss/spinners";
@import "~bootstrap/scss/utilities";
// @import "~bootstrap/scss/print";
  1. Create Bootstrap plugin in plugins/bootstrap.js.
if (process.browser) {
  require("bootstrap");
}
  1. Register the variables and plugin in nuxt.config.js.
const webpack = require("webpack");

export default {
  css: [{ src: "@/assets/custom-bootstrap", lang: "scss" }],
  plugins: ["@/plugins/bootstrap"],
  build: {
    plugins: [
      new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery",
        "window.jQuery": "jquery"
      })
    ]
  }
};
  1. Use Bootstrap, e.g. in pages/bootstrap.vue.
<template>
  <div>
    <h1>Bootstrap Demo</h1>

    <BootstrapNav />
    <BootstrapAbout />
    <BootstrapContact />
  </div>
</template>

<script>
import BootstrapAbout from "@/components/bootstrap-about";
import BootstrapContact from "@/components/bootstrap-contact";
import BootstrapNav from "@/components/bootstrap-nav";

export default {
  components: {
    BootstrapAbout,
    BootstrapContact,
    BootstrapNav
  }
};
</script>

In components/bootstrap-nav.vue:

<template>
  <nav class="bg-dark navbar navbar-expand-lg navbar-dark w-100">
    <nuxt-link class="navbar-brand" to="/">
      <img
        class="d-inline-block align-top"
        src="~assets/logo.svg"
        alt="Logo"
        width="30"
        height="30"
      />
      <span class="font-weight-bold">Unordinary</span>
    </nuxt-link>

    <button
      class="border-0 navbar-toggler"
      type="button"
      data-toggle="collapse"
      data-target="#navbarNav"
      aria-controls="navbarNav"
      aria-expanded="false"
      aria-label="Toggle navigation"
    >
      <span class="navbar-toggler-icon"></span>
    </button>

    <div id="navbarNav" class="collapse navbar-collapse">
      <ul class="navbar-nav ml-auto w-auto">
        <li v-for="(item, index) in menu" :key="index" class="nav-item">
          <a class="nav-link" :href="item.to">
            {{ item.label }}
          </a>
        </li>
      </ul>
    </div>
  </nav>
</template>

<script>
export default {
  data() {
    return {
      menu: [
        { to: "#about", label: "About" },
        { to: "#contact", label: "Contact" }
      ]
    };
  },
  methods: {
    to(input) {
      if (input.label) {
        return input.to;
      } else {
        return `/${input.toLowerCase()}`;
      }
    }
  }
};
</script>

In components/bootstrap-about.vue:

<template>
  <div id="about" class="bg-white rounded-0 jumbotron mb-0 row">
    <div
      class="col-md-4 order-md-2 d-flex align-items-center justify-content-center"
    >
      <img src="~assets/john-doe.jpeg" alt="John Doe" class="img-fluid" />
    </div>

    <div class="col-md-8 order-md-1 container">
      <h2 class="display-4">John Doe</h2>

      <p class="lead">
        I am also known as joker, shadow king, and
        &#647;n&#477;sp&#592;&#654;.<br />I hate the hierarchy, so I am going to
        break it.
      </p>
    </div>
  </div>
</template>

<style lang="scss" scoped>
img {
  max-height: 300px;
}
</style>

In components/bootstrap-contact.vue:

<template>
  <div id="contact" class="bg-primary container-fluid mh-100 px-0 text-white">
    <div class="container-fluid content py-3 mh-100">
      <div class="container">
        <h3 class="mb-4">Contact Me</h3>

        <p>
          You know I am busy beating up high-tiers while keeping Sera in the
          dark. So reach me out through my sidekick Cecile.
        </p>

        <hr class="bg-white" />

        <div class="row">
          <div class="col-md-7 mb-5 mb-md-0 py-3">
            <form
              action="https://formspree.io/yasmin@yasminzy.com"
              method="POST"
            >
              <div class="form-group">
                <input
                  id="name"
                  class="form-control"
                  type="text"
                  name="name"
                  placeholder="Name"
                  required
                />
              </div>

              <div class="form-group">
                <input
                  id="email"
                  class="form-control"
                  type="email"
                  name="_replyto"
                  aria-describedby="emailHelp"
                  placeholder="Email"
                  required
                />
              </div>

              <div class="form-group">
                <textarea
                  id="message"
                  class="form-control"
                  rows="3"
                  name="message"
                  placeholder="Message"
                  required
                />
              </div>

              <input type="hidden" name="_subject" value="Bootstrap Demo" />
              <input
                type="hidden"
                name="_next"
                value="https://www.yasminzy.com"
              />

              <button
                type="submit"
                class="bg-white btn d-flex align-items-center text-dark"
              >
                SEND
                <ion-icon name="send" class="pl-1 text-primary" />
              </button>
            </form>
          </div>

          <div class="col-md-3 offset-md-1">
            <ul class="list-group mb-5 wrapper">
              <li
                v-for="(item, index) in contact"
                :key="index"
                class="bg-transparent border-left-0 border-right-0 border-top-0 list-group-item px-0"
              >
                <div>
                  <p class="font-weight-bold mb-2 text-uppercase">
                    {{ item.label }}
                  </p>

                  <small>{{ item.content }}</small>
                </div>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      contact: [
        {
          label: "Telephone",
          content: "(12) 345-6789"
        },
        {
          label: "Email",
          content: "cecile[at]welston.com"
        },
        {
          label: "Address",
          content: "2019 Black Speech Bubble, ID"
        }
      ]
    };
  }
};
</script>

<style lang="scss" scoped>
h2 {
  text-align: center;

  @media (min-width: 768px) {
    text-align: initial;
  }
}

li {
  text-align: center;

  @media (min-width: 768px) {
    text-align: initial;
  }
}

li:last-child {
  border-bottom: 0;
}
</style>
Last updated: 7/3/2019, 11:43:37 PM