Bootstrap have released version 5 which I would like to use in a Rails 6 project as it no longer requires JQuery. There aren’t many guides to installing Bootstrap 5 in a Rails 6 project and the one I followed didn’t work for tooltips and Popovers. Here’s the workflow I used to get these features working nicely.

This is my workflow for getting Bootstrap5 working with Rails6.

  • yarn add bootstrap@next
  • yarn add @popperjs/core
  • create file app/javascript/stylesheets/application.scss which is where I will add custom css
  • add the following to the top of the new file:
# app/javascript/stylesheets/application.scss

@import "bootstrap"
  • In order for the application to import your custom css from the javascripts folder, add the following to your application layout file add <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>. The pack_tag indicates that this will be handled by webpacker. The layout file will then look like:
# app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>Hello World</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
    <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>
  • finally to get everything working add the following to the bottom of app/javascript/packs/application.js
# app/javascript/packs/application.js

import * as bootstrap from 'bootstrap'
import "../stylesheets/application"

document.addEventListener("DOMContentLoaded", function(event) {
  var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
  var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
    return new bootstrap.Popover(popoverTriggerEl)
  })

  var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
  var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
    return new bootstrap.Tooltip(tooltipTriggerEl)
  })
});

Just as a test I then added the following Bootstrap components to my home page (or any page to test):

# index.html.erb

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
  Launch demo modal
</button>

<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

<button type="button" class="btn btn-secondary" data-bs-toggle="tooltip" data-bs-placement="top" title="Tooltip on top">
  Tooltip on top
</button>