Rails 6, Bootstrap 5 : a tutorial

Posted March 2, 2021 - tagged ruby-on-rails

Last update : December 21, 2021 6 min read

Bootstrap 5 is highly customisable and delightful when you need to deliver a consistent design as fast as possible. Let's see how to use it with the last Rails version.

December 2021 update : Rails 7 and Bootstrap 5

There is a new article about Rails 7 and Bootstrap 5 : https://www.bootrails.com/blog/rails-7-bootstrap-5-tutorial/

The article below is about Rails 6, Webpacker, and Bootstrap 5.


Here are the tools I used for this tutorial. Older versions may work, but I didn't try.

$> ruby --version  
=> 3.0.0  
$> rails --version  
=> 6.1.3  
$> node --version  
=> 14.15.1  
$> yarn --version  
=> 1.22.10  

1. Create new Rails app

$> rails new myapp && cd myapp  

Now wait for a minute... okay ! you have now a fresh new default Rails app.

2. Build a welcome page

Create a controller as follow in app/controllers/welcome_controller.rb

# inside app/controllers/welcome_controller.rb  
class WelcomeController < ApplicationController  

Configure a default route in config/routes.rb as follow

# inside config/routes.rb  
Rails.application.routes.draw do  
  get "welcome/index"  
  root to: "welcome#index"  

Now we have to make this simple example complex enough 😬 to ensure all CSS, JavaScript component works.

Don't worry, just copy/paste the code below into app/views/welcome/index.html.erb

<!-- inside app/views/welcome/index.html.erb -->  
<div class="collapse" id="navbarToggleExternalContent">
  <div class="bg-dark p-4">
    <h5 class="text-white h4">Collapsed content</h5>
    <span class="text-muted">Toggleable via the navbar brand.</span>
<nav class="navbar navbar-dark bg-dark">
  <div class="container-fluid">
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggleExternalContent" aria-controls="navbarToggleExternalContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>

  <section class="py-5 text-center container">
    <div class="row py-lg-5">
      <div class="col-lg-6 col-md-8 mx-auto">
        <h1 class="fw-light">Album example</h1>
        <p class="lead text-muted">Something short and leading about the collection below—its contents, the creator, etc. Make it short and sweet, but not too short so folks don’t simply skip over it entirely.</p>
          <a href="#" class="btn btn-primary my-2">Main call to action</a>
          <a href="#" class="btn btn-secondary my-2">Secondary action</a>

Ensure the application works by running

$/myapp> bin/rails server  

And open localhost:3000 to your browser

Raw image, Bootstrap v5 is not yet installed
Raw image, Bootstrap v5 is not yet installed

Ok, no style so far.

3. Choose a front-end manager

For historical reasons, Rails 6 has two different tools to manage frontend assets (CSS, JavaScript, images, etc). The old one is named "Sprockets", and is not much used outside the Rails scope. The new one is named "Webpacker", and relies on mature, widely used Webpack. Therefore, I don't recommend using Sprockets anymore for new projects, especially since version 5 of webpacker. It is a lot more stable, and can handle multiple packs.

Ensure your Gemfile include at least version 5 of webpacker :

gem 'webpacker', '~> 5.0'  

If not, include version 5 as above and run "bundle install"

Now we want webpacker to handle all our assets, not just JavaScript. Rename app/javascript to app/frontend, like this :

$/myapp> mv app/javascript app/frontend  

In webpacker.yml, warn webpack that we changed the name of the assets folder :

# Inside webpacker.yml, first lines  
default: &default  
source_path: app/frontend # Change here  

4. Install Bootstrap v5

Add latest Bootstrap version, and PopperJs (a mandatory dependency) as follow :

$/myapp> yarn add bootstrap@5.0.0-beta2  
$/myapp> yarn add @popperjs/core@2.0.0-alpha.1  

5. Inject Bootstrap into your application

5a) Inject Boostrap's JS files

Create JS file : app/frontend/js/bootstrap_js_files.js, and import Bootstrap-related JS files, as follow :

$/myapp> mkdir app/frontend/js && touch app/frontend/js/bootstrap_js_files.js  
// inside app/frontend/js/bootstrap_js_files.js  
// import 'bootstrap/js/src/alert'  
// import 'bootstrap/js/src/button'  
// import 'bootstrap/js/src/carousel'  
import 'bootstrap/js/src/collapse'  
import 'bootstrap/js/src/dropdown'  
// import 'bootstrap/js/src/modal'  
// import 'bootstrap/js/src/popover'  
import 'bootstrap/js/src/scrollspy'  
// import 'bootstrap/js/src/tab'  
// import 'bootstrap/js/src/toast'  
// import 'bootstrap/js/src/tooltip'  

Note we don't import all Bootstrap JS files, we only import the ones needed by the project (for the navbar).

Now import this file into the main JS file app/frontend/packs/application.js :

// inside app/frontend/packs/application.js  
// Add this line  
import '../js/bootstrap_js_files.js'  

5b) inject Bootstrap's styles

Create the main CSS file

$/myapp> touch app/frontend/packs/application.scss  

Inside, import Bootstrap

// inside app/frontend/packs/application.scss  
// Just a quick ugly style to see if our CSS works  
h1 {  
  text-decoration: underline;  
// Import Bootstrap v5  
@import "~bootstrap/scss/bootstrap";  

Now tell Rails where is your main CSS file, inside app/views/layouts/application.html.erb

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

    <!-- Warning !! ensure that "stylesheet_pack_tag" is used, line below -->
    <%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

    <%= yield %>

5c) Check everything works

Stop your Rails server. We've changed a lot of frontend assets, so we do a little cleanup/recompile before to restart our rails server.

$/myapp> bin/rails assets:clobber  
$/myapp> bin/rails webpacker:compile  
$/myapp> bin/rails server  

And open browser at localhost:3000.

  • If the style looks like Bootstrap, yay ! Our import of Bootstrap's CSS file has worked.
  • If clicking on the hamburger menu means toggling navbar, yay ! Our import of Bootstrap's JS file has worked.
it works!
it works!

6 More to come

Final code can be found here. That's all for today, given the number of steps involved to get this result. However, I'd like to add :

  • How to copy/paste SCSS file to get a deep Bootstrap customisation,
  • How to manage images
  • How to manage fonts
  • How to optimize assets
  • Probably other things I'm not thinking about right now. Stay tuned !
Take care ! Health first. 🙏