paint-brush
Integrating Bootstrap into Rails 5by@rob__race
39,871 reads
39,871 reads

Integrating Bootstrap into Rails 5

by Rob RaceMarch 7th, 2017
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

<a href="https://getbootstrap.com/" target="_blank">Bootstrap</a> is an HTML/CSS/JS framework to make it quick and easy to build a responsive website. Bootstrap uses a grid layout system that breaks the page into rows and 12 columns inside each row. This now allows you to structure your markup up in a consistent way.

People Mentioned

Mention Thumbnail

Company Mentioned

Mention Thumbnail

Coin Mentioned

Mention Thumbnail
featured image - Integrating Bootstrap into Rails 5
Rob Race HackerNoon profile picture

…and how to use a BootStrap Theme

Bootstrap is an HTML/CSS/JS framework to make it quick and easy to build a responsive website. Bootstrap uses a grid layout system that breaks the page into rows and 12 columns inside each row. This now allows you to structure your markup up in a consistent way.

Note: This tutorial is an excerpt from a chapter in my upcoming book Build A SaaS App in Rails 6. The book guides you from humble beginnings through deploying an app to production. The book is now in pre sale, and you can grab a free chapter right now!

Also, the beta for my new project Pull Manager is has been released. If you’re losing track of pull requests, have old ones lingering around or would just love a dashboard that aggregates these requests over multiple services (Github, Gitlab, and Bitbucket), check it out.

Also, the beta for my new project Pull Manager is almost ready. If you’re losing track of pull requests, have old ones lingering around or would just love a dashboard that aggregates these requests over multiple services (Github, Gitlab, and Bitbucket), check it out.

Bootstrap, now being around for many years has developed an ecosystem of themes as well. There are both premium and free themes available. Personally, I like to use Inspinia as a premium theme or AdminLTE as a free theme when building a SaaS application.

For the purpose of the post, and due to its open source and free nature we will use the AdminLTE theme. Feel free to use any other themes. Though class names and markup structure may change specific to the theme you are using.

This post will also assume you have generated a new Rails app with rails new app_name and running a rails server on the default port 3000.

Quick overview of Grid

Let’s dig into the grid system in a little more detail before integrating Bootstrap into your application. As a note before, the grid is a 12 column system that is responsive to the viewport or device width. When you create a row in the grid with <div class="row"></div> you will be able to fill that row with columns. For example, if you wanted a three column layout it would look like...











<div class="row"><div class="col-lg-3"><h1>One</h1></div><div class="col-lg-3"><h1>Two</h1></div><div class="col-lg-3"><h1>Three</h1></div></div>

In the example, you may notice the column class name contains the letters lg. This stands for large and means the columns are referencing the large viewport size. There are four sizes, each corresponding to the greatest pixel width. Extra small devices Phones (<768px). Small devices Tablets (≥768px). Medium devices Desktops (≥992px). Large devices Desktops (≥1200px).

You can use multiple column declarations within the class name to instruct the grid what to do depending on the size of the viewport.





<!-- Stack the columns on mobile by making one full-width and the other half-width --><div class="row"><div class="col-xs-12 col-md-8">One</div><div class="col-xs-6 col-md-4">Two</div></div>






<!-- Columns start at 50% wide on mobile and bump up to 33.3% wide on desktop --><div class="row"><div class="col-xs-6 col-md-4">One</div><div class="col-xs-6 col-md-4">Two</div><div class="col-xs-6 col-md-4">Three</div></div>

To go deeper on the grid system and other CSS functionality of Bootstrap you can visit the documentation.

First Controller, Views

If this is a new app, before you begin implementing the layout, we will need to implement a route and controller to bypass the default welcome page. You will be using the controller in the application as you go along.

Let’s also pause to mention that Rails comes with built-in command line generators to generate controllers, models, mailers. As well as generating database migration file or even generating a scaffold of all of those combined. In our case, let’s focus on the controller generator. The general format for this generator is rails generate controller NAME [action action] [options]. Thus, our controller generate command will look like:






















rails generate controller Activity mine feedcreate app/controllers/activity_controller.rbroute get 'activity/feed'route get 'activity/mine'invoke slimcreate app/views/activitycreate app/views/activity/mine.html.slimcreate app/views/activity/feed.html.sliminvoke rspeccreate spec/controllers/activity_controller_spec.rbcreate spec/views/activitycreate spec/views/activity/mine.html.slim_spec.rbcreate spec/views/activity/feed.html.slim_spec.rbinvoke helpercreate app/helpers/activity_helper.rbinvoke rspeccreate spec/helpers/activity_helper_spec.rbinvoke assetsinvoke coffeecreate app/assets/javascripts/activity.coffeeinvoke scsscreate app/assets/stylesheets/activity.scss

Lets make one quick edit to the route file to define a default route. We will add root to: 'activity#mine' to the bottom of the route file, as follows:


Rails.application.routes.draw doget 'activity/mine'

get 'activity/feed'


root to: 'activity#mine'end

Application layout

If you are using the AdminLTE Bootstrap theme, and following along, you should download them if you have not already. You can download it from this link or from the support page on the theme preview.

Once you have downloaded and unzipped the folder you will want to copy some files into your Rails application. You can run the following commands or copy the files through your OS’s file system GUI.

cp ~/Downloads/AdminLTE-2.3.11/dist/css/AdminLTE.css app/assets/stylesheets/

The download location may vary based on your machine. Also, the version number in the path for AdminLTE may change based on the time you download the theme. Use the folder you have downloaded. That command will copy the main AdminLTE CSS styles. The AdminLTE theme also comes with different colored skins. For this post, I will use the light blue, but you can use any of the included colors. The following command will move the skin CSS styles into your application.



mkdir app/assets/stylesheets/skinscp ~/Downloads/AdminLTE-2.3.11/dist/css/skins/skins-light-blue.css \app/assets/stylesheets/skins

Now that the required files are present, you will now instruct the Rails application to use the files. You will first change the assets/stylesheets/application.css file to only require itself and a new style.scss file.





/***= require style*= require_self*/

The new style.scss file will then include the bootstrap base CSS files and the AdminLTE files.


@import "bootstrap-sprockets";@import "bootstrap";


@import "AdminLTE";@import "skins/skin-blue-light";

If you reload http://localhost:3000 you will now see that the styling of the default page for the activity#mine page has an updated styling. It should now look more like the following image:

As you can see while there is no full layout, the styles have updated. We are going to need to do a bit more to implement the whole layout. First, let’s update the application layout to use a slim template(replacing the .erb file) and some basic Bootstrap styles:










#app/views/layouts/application.slimdoctype htmlhtmlheadtitle Standup App= csrf_meta_tags= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'= javascript_include_tag 'application', 'data-turbolinks-track': 'reload'= stylesheet_link_tag [href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" ]






body.fixed.skin-blue-light.wrapper= render 'layouts/navigation/layout'.content-wrapper= yield= render 'layouts/navigation/footer'











#app/views/layouts/application.erb<!DOCTYPE html><html><head><title>Standup App</title><%= csrf_meta_tags %><%= stylesheet_link_tag ‘application’, media: ‘all’, ‘data-turbolinks-track’: ‘reload’%><%= javascript_include_tag ‘application’, ‘data-turbolinks-track’: ‘reload’), false %><%= stylesheet_link_tag href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" %></head><body class="fixed skin-blue-light">


<div class="wrapper"><%= render 'layouts/navigation/layout'%>




<div class="content-wrapper"><%= yield %></div><%= render 'layouts/navigation/footer' %>



</div></body></html>

There are a few things to note here. Firstly, you may notice the lines that begin with = in the head section. This is slim templates' way of included ruby to have output. Which is different than using - in a template. The single hyphen is used to include ruby but has no output, like an if statement. The output in the head is including Rails asset javascript and CSS. We are also including FontAwesome icons through the last stylesheet inclusion helper.

You may also notice some very specific markup in the body. Here, you will be using the AdminLTE specific classes and HTML hierarchy to style your application in the AdminLTE theme.

Lastly, you will see two other helpers. = render helpers, to include other slim files. Then, = yield which is the Rails' template method for including the template from the controller and action called.

The last thing in the section to do before digging into specific sections in the layout is to modify the application.js to include necessary javascript needed for the theme to work. You will be copying another file from the theme's folder and then making sure it is referenced in your project.

To copy the javascript file you can use the following command or use your machine’s file GUI:

cp ~/Downloads/AdminLTE-2.3.11/dist/js/app.js app/assets/javascripts/

Additionally, you will need a third party javascript file from the theme folder as well:


cp ~/Downloads/AdminLTE-2.3.11/plugins/slimScroll/jquery.slimscroll.min.js \vender/assets/javascripts/

You may notice this file gets copied to a different location. It is considered best practice in a Rails app to have third party javascript in the vender folders.

Now, to make sure the newly copied javascript files are included into the project itself you will modify the application.js file:






//= require jquery//= require jquery_ujs//= require turbolinks//= require bootstrap//= require jquery.slimscroll.min//= require_tree .

The first three lines were included by default when generating the new Rails app. These lines include the basic included jQuery, tools and Turbolinks. The lines you will add include Bootstrap from the bootstrap-sass gem. And also includes the slimscroll plugin the AdminLTE theme uses. The last line is another Rails default. Meaning the file will include any javascript file in the app/assets/javascripts folder and its children folders. This line is how the copied app.js file and others got included.

Top Navigation

In regards to the navigation within this application, there will be two main sections. The navigation bar across the top, and a navigation sidebar on the left side of the screen.

From the application file, the navigation files were included by rendering a slim template in a navigation folder (= render 'layouts/navigation/layout'). In this file, you are then including the top navigation and side navigation templates:



#app/views/layouts/navigation/_layout.slim= render "layouts/navigation/header"= render "layouts/navigation/sidebar"



#app/views/layouts/navigation/_layout.erb<%= render "layouts/navigation/header" %><%= render "layouts/navigation/sidebar" %>

One thing to note here is the use of the underscore in the template file’s name. In Rails, partial template files are designated with an underscore at the beginning of the file name. What are partials? Partials are simply a way to break down templates into smaller chunks. This comes into far greater play in situations such as looping over a collection of items. There, you would make the template chunk to display item information a partial.

The first partial included is the header or top navigation bar template. The approach taken in this post with the layout will be to include example markup. Later you will add, remove or change the markup to meet the expectations of the application being built. Here is the header partial:























































































# app/views/layouts/navigation/_header.slimheader.main-headera.logo href="/"| Standup App nav.navbar.navbar-static-top role="navigation".navbar-custom-menuul.nav.navbar-navli.dropdown.messages-menua.dropdown-toggle data-toggle="dropdown" href="#"i.fa.fa-envelope-ospan.label.label-success 4ul.dropdown-menuli.header You have 4 messagesliul.menulia href="#".pull-leftimg.img-circle [ alt=("User Image")src="http://placehold.it/160x160" ]h4| Sender Namesmalli.fa.fa-clock-o| 5 minsp Message Excerpt| \...li.footera href="#" See All Messagesli.dropdown.notifications-menua.dropdown-toggle data-toggle="dropdown" href="#"i.fa.fa-bell-ospan.label.label-warning 10ul.dropdown-menuli.header You have 10 notificationsliul.menulia href="#"i.ion.ion-ios-people.info| Notification title| \...li.footera href="#" View allli.dropdown.tasks-menua.dropdown-toggle data-toggle="dropdown" href="#"i.fa.fa-flag-ospan.label.label-danger 9ul.dropdown-menuli.header You have 9 tasksliul.menulia href="#"h3| Design some buttonssmall.pull-right 20%.progress.xs.progress-bar.progress-bar-aqua [ aria-valuemax="100"aria-valuemin="0" aria-valuenow="20" role="progressbar"style=("width: 20%") ]span.sr-only 20% Complete| \...li.footera href="#" View all tasksli.dropdown.user.user-menua.dropdown-toggle data-toggle="dropdown" href="#"img.user-image alt=("User Image") src="http://placehold.it/160x160"span.hidden-xs Alexander Pierceul.dropdown-menuli.user-headerimg.img-circle [ alt=("User Image")src="http://placehold.it/160x160" ]p| Alexander Pierce - Web Developersmall Member since Nov. 2012li.user-body.col-xs-4.text-centera href="#" Followers.col-xs-4.text-centera href="#" Sales.col-xs-4.text-centera href="#" Friendsli.user-footer.pull-lefta.btn.btn-default.btn-flat href="#" Profile.pull-righta.btn.btn-default.btn-flat href="#" Sign out











































# app/views/layouts/navigation/_header.erb<header class="main-header"><a class="logo" href="/">Standup App</a><nav class="navbar navbar-static-top" role="navigation"><div class="navbar-custom-menu"><ul class="nav navbar-nav"><li class="dropdown messages-menu"><a class="dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-envelope-o"></i><span class="label label-success">4</span></a><ul class="dropdown-menu"><li class="header">You have 4 messages</li><li><ul class="menu"><li><a href="#"> </a><div class="pull-left"><img class="img-circle" alt="User Image" src="http://placehold.it/160x160"> </img></div><h4>Sender Name<small><i class="fa fa-clock-o"></i>5 mins</small></h4><p>Message Excerpt</p></li></ul></li><li class="footer"><a href="#"> See All Messages</a></li></ul></li><li class="dropdown notifications-menu">











































<a class="dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-bell-o"></i><span class="label label-warning">10</span></a><ul class="dropdown-menu"><li class="header">You have 10 notifications</li><li><ul class="menu"><li><a href="#"><i class="ion ion-ios-people info"></i>Notification title</a></li></ul></li><li class="footer"><a href="#"> View all</a></li></ul></li><li class="dropdown tasks-menu"><a class="dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-flag-o"></i><span class="label label-danger">9</span></a><ul class="dropdown-menu"><li class="header">You have 9 tasks</li><li><ul class="menu"><li><a href="#"></a><h3>Design some buttons<small class="pull-right">20%</small></h3><div class="progress xs"><div aria-valuemax="100" aria-valuemin="0" aria-valuenow="20" class="progress-bar progress-bar-aqua" role="progressbar" style="width: 20%">

<span class="sr-only">20% Complete</span>
















































</div></div></li></ul></li><li class="footer"><a href="#"> View all tasks</a></li></ul></li><li class="dropdown user user-menu"><a class="dropdown-toggle" data-toggle="dropdown" href="#"><img alt="User Image" class="user-image" src="http://placehold.it/160x160" /><span class="hidden-xs">Alexander Pierce</span></a><ul class="dropdown-menu"><li class="user-header"><img class="img-circle" alt="User Image" src="http://placehold.it/160x160"> </img><p>Alexander Pierce - Web Developer<small>Member since Nov. 2012</small></p></li><li class="user-body"><div class="col-xs-4 text-center"><a href="#"> Followers</a></div><div class="col-xs-4 text-center"><a href="#"> Sales</a></div><div class="col-xs-4 text-center"><a href="#"> Friends</a></div></li><li class="user-footer"><div class="pull-left"><a class="btn btn-default btn-flat" href="#"> Profile</a></div><div class="pull-right"><a class="btn btn-default btn-flat" href="#"> Sign out</a></div></li></ul></li></ul></div></nav></header>

As you can see in the header partial. The base Bootstrap navigation markup and styles are applied. Then, AdminLTE applies styles over the top of that to give your application a dashboard feel. Within the header navigation bar is the application’s title, dropdowns for messages/notification, and a dropdown to access other parts of the application.

Sidebar Navigation

The second template being included is the sidebar or side navigation bar template. This partial will take the same example markup approach.






















# app/views/layouts/navigation/_sidebar.slim.main-sidebar.sidebar.user-panel.pull-left.imageimg.img-circle alt=("User Image") src="http://placehold.it/160x16" /.pull-left.infop User Namea href="#"i.fa.fa-circle.text-success| Onlineform.sidebar-form action="#" method="get".input-groupinput.form-control name="q" placeholder="Search..." type="text" /span.input-group-btnbutton#search-btn.btn.btn-flat name="search" type="submit"i.fa.fa-searchul.sidebar-menuli.header HEADERli.activea href="#"span Link












lia href="#"span Another Linkli.treeviewa href="#"span Multileveli.fa.fa-angle-left.pull-rightul.treeview-menulia href="#" Link in level 2lia href="#" Link in level 2

























































# app/views/layouts/navigation/_sidebar.erb<div class="main-sidebar"><div class="sidebar"><div class="user-panel"><div class="pull-left image"><img alt="User Image" class="user-image" src="http://placehold.it/160x160" /></div><div class="pull-left info"><p>User Name</p><a href="#"><i class="fa fa-circle text-success"></i>Online</a></div></div><form action="#" class="sidebar-form" method="get"><div class="input-group"><input class="form-control" name="q" placeholder="Search..." type="text" /><span class="input-group-btn"><button class="btn btn-flat" id="search-btn" name="search" type="submit"><i class="fa fa-search"></i></button></span></div></form><ul class="sidebar-menu"><li class="header">HEADER</li><li class="active"><a href="#"><span>Link</span></a></li><li><a href="#"><span>Another Link</span></a></li><li class="treeview"><a href="#"><span>Multilevel</span><i class="fa fa-angle-left pull-right"></i></a><ul class="treeview-menu"><li><a href="#"> Link in level 2</a></li><li><a href="#"> Link in level 2</a></li></ul></li></ul></div></div>

As you see, the sidebar partial is a bit smaller and simpler. It contains a little bit of user information, a search input, and links to other parts of the application that you will change later.

Footer

The last major piece of the layout will be the footer. It will be simple and it will be short. Again, it will be another partial. Again the partial will be located in the navigation folder. Here is the slim markup:








# app/views/layouts/navigation/_footer.slimfooter.main-footer.pull-right.hidden-xs| Anything you wantstrong| Copyright © 2016a href="#" Company| All rights reserved.











# app/views/layouts/navigation/_footer.erb<footer class="main-footer"><div class="pull-right hidden-xs">Anything you want</div><strong>Copyright © 2016<a href="#"> Company</a></strong>All rights reserved.</footer>

By going to http://localhost:3000 you should now see a page that looks like this, or similar if you have deviated on theme or layout style:

That’s it. That is all of the files to copy, files to create and markup to add to give your application a layout that your individual controller action templates will render into. That wasn’t so bad, was it?