Using Bootstrap and Sass with Phoenix Framework and Brunch

Sayo Ogunlegan
Sep 28, 2016 · 3 min read

A default Phoenix webapp comes with Bootstrap included as part of its starter CSS. Unfortunately, this is only the CSS. If you’re familiar enough with front-end development, you probably want to use something like Sass for styling instead of plain CSS. If you’re also familiar with Bootstrap, it’s likely that you’ll want the official Sass version, so you can access (and customize) variables for use in the rest of your styles.

Let’s get started by scaffolding a new Phoenix webapp. I assume you already have Elixir and Phoenix set up (if not, have a look here).

$ mix pbs
$ cd pbs/
$ mix ecto.create
$ mix phoenix.server

Head to http://localhost:4000 to see the running application, with some default styles. Phoenix includes some CSS in web/static/css/phoenix.css. If you look at the top of the file you should see something like this:

/* Includes Bootstrap as well as some default style for the starter
* application. This can be safely deleted to start fresh.
* Bootstrap v3.3.5 (
* ... minified Bootstrap shortly after this comment block

As they mention, you can delete the contents of this file to get a fresh start. Do exactly that. We removed the plain CSS version of Bootstrap. This will be obvious if you refresh the browser in which you are viewing the app.

Next, we’ll install some npm packages we need.

$ npm install --save-dev sass-brunch copycat-brunch
$ npm install --save bootstrap-sass jquery

The packages we installed:

With those installed, we can update our brunch configuration file. Open brunch-config.js and change the contents to the following:

exports.config = {
// See for docs.
files: {
javascripts: {
joinTo: "js/app.js"
stylesheets: {
joinTo: "css/app.css",
order: {
after: ["web/static/css/app.scss"] // concat app.css last
templates: {
joinTo: "js/app.js"
conventions: {
assets: /^(web\/static\/assets)/
// Phoenix paths configuration
paths: {
// Dependencies and current project directories to watch
watched: [
// Where to compile files to
public: "priv/static"

plugins: {
babel: {
ignore: [/web\/static\/vendor/]
copycat: {
"fonts": ["node_modules/bootstrap-sass/assets/fonts/bootstrap"] // copy node_modules/bootstrap-sass/assets/fonts/bootstrap/* to priv/static/fonts/
sass: {
options: {
includePaths: ["node_modules/bootstrap-sass/assets/stylesheets"], // tell sass-brunch where to look for files to @import
precision: 8 // minimum precision required by bootstrap-sass

modules: {
autoRequire: {
"js/app.js": ["web/static/js/app"]

npm: {
enabled: true,
globals: { // bootstrap-sass' JavaScript requires both '$' and 'jQuery' in global scope
$: 'jquery',
jQuery: 'jquery',
bootstrap: 'bootstrap-sass' // require bootstrap-sass' JavaScript globally

Now rename web/static/css/app.css to web/static/css/app.scss. We will use this file to include all the other Sass styles. We’ll show this in action by creating a new, empty file — web/static/css/_custom.scss. With the main file renamed, and the new file created, change web/static/css/app.scss to match this:

$icon-font-path: "/fonts/"; /* use fonts from priv/static/fonts/ */
@import "bootstrap"; /* imports node_modules/bootstrap-sass/assets/stylesheets/_bootstrap.scss */
/* Custom Stuff */
@import "custom";

Restart your Phoenix app to account for our changes to the brunch config, which now allows brunch to handle converting our Sass to CSS plain, including any fonts and styles from Bootstrap as we wanted. Revisiting the app again shows that while we don’t have some of the nice little defaults (unless you chose to keep them earlier), Bootstrap itself back in action.

To prove we can make use of some Bootstrap Sass variables, add the following to web/static/css/_custom.scss:

.jumbotron {
color: $brand-danger;

Refresh the app in your browser to see that the welcome text is now a shade of red, all thanks to the variable we were provided by Bootstrap.

Feel free to clone or fork the repo here.

**Note** If you clone the repo, you’ll need to go to localhost:8080 to view it once you’ve started it (as opposed to localhost:4000 mentioned above). The app was edited using Cloud9, which required the port change to run the web server. This can be changed in pbs/config/dev.exs.

**Another Note** This was post created using Phoenix v1.2. Currently, you can now install version Phoenix v1.3. I have not tested these instructions against the new version.

Thanks for reading!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store