· Ruby · 5 min read
Rails 8 Bootstrap 5 tutorial
A very simple tutorial about Rails 8 and Bootstrap 5, since starting with Boostrap is given by the framework.
Motivation
Bootstrap used to be the de-facto CSS Frameworks for a long time. Now it’s more Tailwind, but Rails 8 still gives the option to use Bootstrap by default.
1. Prerequisites
I tested on Linux with the tools below :
$> ruby -v
ruby 3.3.0
$> bundle -v
Bundler version 2.5.5
$> npm -v
10.2.4
$> yarn -v
1.22.22
Any upper versions should work.
2. Create an isolated, new Rails 8 app
mkdir myapp && cd myapp
echo "source 'https://rubygems.org'" > Gemfile
echo "gem 'rails', '8.0.0'" >> Gemfile
bundle install
bundle exec rails new . --force --css=bootstrap -j=esbuild
Continue inside bash :
bin/rails db:create
bin/rails db:migrate
3. Is Bootstrap v5 already installed ? a check
In this paragraph, we will not write any code, instead, we will read what is already installed for us.
Some good news : maybe you noticed the --css=bootstrap
option above. This means the last Bootstrap version is already installed.
Let’s check where this happens :
package.json
// inside package.json
{
"name": "app",
"private": "true",
// ... other props, the
"dependencies": {
"@hotwired/stimulus": "^3.2.2",
"@hotwired/turbo-rails": "^8.0.12",
"@popperjs/core": "^2.11.8",
"autoprefixer": "^10.4.20",
"bootstrap": "^5.3.3",
"bootstrap-icons": "^1.11.3",
"nodemon": "^3.1.7",
"postcss": "^8.4.49",
"postcss-cli": "^11.0.0",
"sass": "^1.81.0"
},
}
Ok ! Bootstrap 5 and its dependencies is properly installed inside package.json
// inside app/assets/stylesheets/application.bootstrap.scss
@import 'bootstrap/scss/bootstrap';
@import 'bootstrap-icons/font/bootstrap-icons';
Great ! Standard import of bootstrap scss source, this will allow us fine tuning later.
// inside app/javascript/application.js
// Entry point for the build script in your package.json
import '@hotwired/turbo-rails';
import './controllers';
import * as bootstrap from 'bootstrap';
Ok ! JavaScript for Bootstrap is now loaded - even if no initialisation happens so far.
Open app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title><%= content_for(:title) || "Myapp" %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= yield :head %>
<%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
<%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
<link rel="icon" href="/icon.png" type="image/png">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/icon.png">
<%# Includes all stylesheet files in app/assets/stylesheets %>
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
</head>
<body>
<%= yield %>
</body>
</html>
The interesting lines are javascript_include_tag
and stylesheet_link_tag
. They allow us to profit from initial SCSS and JS files in each template that inherits from the default layout.
Create bare minimal Bootstrap 5 HTML
Create a controller :
# inside app/controllers/home_controller.rb
class HomeController < ApplicationController
end
Configure a default route :
# inside config/routes.rb
Rails.application.routes.draw do
get "home/index"
root to: "home#index"
end
Now create a view tailored for Bootstrap 5 : just copy/paste the code below into app/views/home/index.html.erb
<!-- inside app/views/home/index.html.erb -->
<h1>Welcome, this is the home page</h1>
<button
type="button"
class="btn btn-lg btn-danger"
data-bs-toggle="popover"
title="Popover title"
data-bs-content="Amazing content, right ?"
>
Click to toggle popover
</button>
This HTML should show a popover when clicking the red button, only if
- Bootstrap CSS is properly configured,
- Bootstrap JS is loaded and initialized.
Great ! This bare minimalistic example will ensure everything works properly.
Bootstrap 5, Rails 8, locally : let’s start !
$/myapp> ./bin/dev
17:24:24 web.1 | started with pid 26889
17:24:24 js.1 | started with pid 26890
17:24:24 css.1 | started with pid 26891
17:24:24 css.1 | yarn run v1.22.10
17:24:24 js.1 | yarn run v1.22.10
17:24:24 css.1 | $ sass ./app/assets/stylesheets/application.bootstrap.scss ./app/assets/builds/application.css --no-source-map --load-path=node_modules --watch
17:24:24 js.1 | $ esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --watch
17:24:25 js.1 | [watch] build finished, watching for changes...
17:24:25 css.1 | Sass is watching for changes. Press Ctrl-C to stop.
17:24:25 css.1 |
17:24:26 web.1 | => Booting Puma
17:24:26 web.1 | => Rails 7.0.0 application starting in development
17:24:26 web.1 | => Run `bin/rails server --help` for more startup options
17:24:26 web.1 | Puma starting in single mode...
17:24:26 web.1 | * Puma version: 5.5.2 (ruby 3.0.0-p0) ("Zawgyi")
17:24:26 web.1 | * Min threads: 5
17:24:26 web.1 | * Max threads: 5
17:24:26 web.1 | * Environment: development
17:24:26 web.1 | * PID: 26889
17:24:26 web.1 | * Listening on http://127.0.0.1:3000
17:24:26 web.1 | * Listening on http://[::1]:3000
17:24:26 web.1 | Use Ctrl-C to stop
Great ! the console indicates that we should go to localhost:3000 to see what is happening. Let’s go :
Try to click the button. Nothing happens.
Adding custom Bootstrap-based JavaScript into Rails
Let’s follow the Bootstrap docs about popovers here :
And inject it into Rails
// Inside app/javascript/application.js
import "@hotwired/turbo-rails"
import "./controllers"
import * as bootstrap from "bootstrap"
let popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
let popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
return new bootstrap.Popover(popoverTriggerEl)
})
Now reload your browser, and click the big red button
Great ! it works
Add custom SCSS
// inside app/assets/stylesheets/application.bootstrap.scss
$h1-font-size: 1rem; // this line was added
@import 'bootstrap/scss/bootstrap';
Reload your browser
Summary
I tried to write the most possible Rails 8 and Bootstrap 5 tutorial, hope it helped.
Enjoy!