bootstrap.native - Bootstrap without jQuery

kinopyo avatar


Bootstrap 5 will remove jQuery as a dependency. That's good news 👏 ! But if you want to drop the dependency right now, you can accomplish it with bootstrap.native.

bootstrap.native is a third-party plugin that perfectly mimics Bootstrap with vanilla JavaScript. It's lightweight, robust, and comes with some sweet enhancements too.

Get Started with bootstrap.native

Install via yarn:

yarn add bootstrap.native
yarn add -D bootstrap.native-loader

As you've guessed, bootstrap.native-loader is the Webpack loader.

Back to the code, let's configure the loader in Webpacker - specify components you want to use and the version. bootstrap.native supports both V3 and V4.

const { environment } = require("@rails/webpacker")
const webpack = require("webpack")

environment.loaders.append("bootstrap.native", {
  test: /bootstrap\.native/,
  use: {
    loader: "bootstrap.native-loader",
    options: {
      only: ["alert", "button", "dropdown", "modal", "tooltip"],
      bsVersion: 4

module.exports = environment

Then, import it in Webpack entry file.

import "bootstrap.native"

It's important to note that all components are initialized right away. Meaning that it'll scan through the data-* attributes and initialize dropdowns, tooltips, etc. If you've had the correct Bootstrap HTML markup, you don't have to do anything else.

But, if you're using Turbolinks...

You'll need this:

import "bootstrap.native"
document.addEventListener("turbolinks:load", () => {

As explained in its FAQ, dynamically added elements will not work.

Does it work with later added elements?
...the event listeners used by the components are not bound to the document and delegated to specific elements like jQuery plugins do, rather we took a more performance oriented approach and decided to bind events to elements themselves, for performance reasons.

Since Turbolinks is fetching a new page and replacing the body, the events will not work after clicking a link powered by Turbolink.

So we'll need to tell bootstrap.native (BSN global var) to re-initialize events after a turbolinks:load event. You can learn more about this part from the official wiki and this Stackoverflow.

The sweet data-persist

Compare to the official JavaScript, bootstrap.native comes with some sweet improvements.

My favorite is data-persist option that keeps the dropdown menu open, a perfect use case for having a form within a dropdown. (Previously I had to add a little hack to make Bootstrap work that way.)

The markup is straightforward - add data-persist="true" to the dropdown button.

<button class="dropdown-toggle" data-toggle="dropdown" data-persist="true">

Read more: Some features are even better.

Misc: ESLint, Cleanup

In case you're using ESLint, be sure to add that BSN to the globals:

 "globals": {
    "BSN": false,
    // ...

Lastly, happily say goodbye to these old pals 👋 (or even jQuery if Bootstrap is the last dependent of it!).

yarn remove bootstrap popper.js


Let's get down to the pros and cons.


  • works great as it advertised
  • lightweight, 5kb
  • well maintained
  • fast to catch up upstream (e.g. Toast feature)
  • almost a drop-in solution

The open-close ratio of Github issues is 1/205! 👏


Being a third-party craft, it unavoidably introduces..

  • some learning curves and gotchas
  • delays of catching up upstream

At last, I highly recommend you check out its Wiki first to understand the motivation of the project, acknowledgments, and FAQs.

I'm pretty happy after switching to bootstrap.native. Overall, less code, smaller bundle size, and one big step towards fully dropping jQuery dependency. 💪

p.s. If you're using React, there is a wonderful solution as well: React Bootstrap.

p.p.s. If you want to know how to use Toast component with bootstrap.native, check out the followup post.

kinopyo avatar
Written By


Indoor enthusiast, web developer, and former hardcore RTS gamer. #parenting
Published in Rails
Enjoyed the post?

Clap to support the author, help others find it, and make your opinion count.