Customizing Bootstrap CSS Style With Gulp, Bower And SASS

By:   –  Last updated:   –  #bootstrap ·  #gulp ·  #bower ·  #sass

Code Theme [Dark]

Content Overview [Hide]

 

 

Developer can customize Bootstrap easily and more flexibly with Gulp and Sass besides using official "Compile and Download" feature.

1. Installing gulp and bower

I assume that you have installed node.js and npm in your comupter.

First of all, install gulp globally:

$ sudo npm install --global gulp

or

$ sudo npm install -g gulp

Then install bower:

$ sudo npm install -g bower

2. Initializing

Create a new project folder, for example "mybootstrap". Create sub folders as below:

mybootstrap/
    - src/
        - css/
    - dist/
        - css/
    - gulpfile.js

Here are some explanations about folder structure:

  • src/, our source files folder, usually including scss, js or html files under it. In this simple project, we will only have scss files under src/css/.
  • dist/, distribution or release folder. We will never edit files directly in this folder. Generally, all files under this folder and its sub folders will be automatically generated by gulp.
  • gulpfile.js, the main gulp source file, we will write gulp code to create tasks in this file.

Then initialize current project with npm and bower:

$ cd mybootstrap
$ npm init
$ bower init

npm init will interactively create a package.json file to save your node.js package dependencies. All required node.js module packages will be registered in this package.json and installed in node_modules folder under your project root folder.

Similarly, bower init will interactively create a bower.json file to save your bower package dependencies. All required bower packages will be registered in this bower.json and installed in bower_components folder under your project root folder.

By now your project folder structure should look something like this:

mybootstrap/
    - src/
        - css/
    - dist/
        - css/
    - gulpfile.js
    - package.json
    - bower.json

If you are using version control tool like git, you should only track these two json files, ignore node_modules and bower_components folder. Because if you clone or move the project to somewhere else, npm and bower will automatically install all required dependencies according to these two json files by commands:

$ npm install
$ bower install

3. Add gulp and bower to project dependencies

Add gulp to node module dependencies:

$ cd mybootstra
$ npm install gulp --save-dev

with the --save-dev option npm will additionaly save the dependency to package.json file of current project.

To use sass with gulp, we also need to install gulp-sass module:

$ cd mybootstrap
$ npm install gulp-sass --save-dev

After above steps your package.json may look like this:

{
  "name": "mybootstrap",
  "version": "1.0.0",
  "description": "Custom theme project for Bootstrap",
  "devDependencies": {
    "gulp": "^3.9.0",
    "gulp-sass": "^2.0.3"
  }
}

4. Installing Bootstrap scss files

The bower package bootstrap-sass-official provides scss source files of Bootstrap css. We install it as a dependency.

$ bower install bootstrap-sass-official --save-dev

Notice that with --save option bower will additionaly save the dependency to bower.json file, just like --save-dev option of npm install.

Now you can see something like this in your bower.json file:

"dependencies": {
    "bootstrap-sass-official": "~3.3.5"
}

5. Create main scss file

Create our main css source file: mybootstrap/src/css/main.scss. Then import Bootstrap into it:

/* main.scss */
@import "bootstrap";
@import "bootstrap/theme";

6. gulpfile.js

We are going to use gulp to compile scss files under mybootstrap/src/scss/ into css file and then copy it to mybootstrap/dist/css/.

We do this in gulpfile.js using gulp task.

The first step, require gulp modules:

/* gulpfile.js */
var 
    gulp = require('gulp'),
    sass = require('gulp-sass');

The second step, add configurations to gulpfile.js:

/* gulpfile.js */

......

// source and distribution folder
var
    source = 'src/',
    dest = 'dist/';

// Bootstrap scss source
var bootstrapSass = {
        in: './bower_components/bootstrap-sass-official/'
    };
    
// fonts
var fonts = {
        in: [source + 'fonts/*.*', bootstrapSass.in + 'assets/fonts/**/*'],
        out: dest + 'fonts/'
    };

// css source file: .scss files
var css = {
    in: source + 'css/main.scss',
    out: dest + 'css/',
    watch: source + 'css/**/*',
    sassOpts: {
        outputStyle: 'nested',
        precison: 3,
        errLogToConsole: true,
        includePaths: [bootstrapSass.in + 'assets/stylesheets']
    }
};

The third step, add a gulp fonts task to copy bootstrap required fonts to dist folder:

/* gulpfile.js */
......

// copy bootstrap required fonts to dest
gulp.task('fonts', function () {
    return gulp
        .src(fonts.in)
        .pipe(gulp.dest(fonts.out));
});

The fourth step, compile source scss into css and copy the result css file to dist:

/* gulpfile.js */
......

// compile scss
gulp.task('sass', ['fonts'], function () {
    return gulp.src(css.in)
        .pipe(sass(css.sassOpts))
        .pipe(gulp.dest(css.out));
});

Add default task:

/* gulpfile.js */
......

// default task
gulp.task('default', ['sass'], function () {
     gulp.watch(css.watch, ['sass']);
});

Now the whole gulpfile.js should be:

/* gulpfile.js */
var 
    gulp = require('gulp'),
    sass = require('gulp-sass');

// source and distribution folder
var
    source = 'src/',
    dest = 'dist/';

// Bootstrap scss source
var bootstrapSass = {
        in: './bower_components/bootstrap-sass-official/'
    };
    
// fonts
var fonts = {
        in: [source + 'fonts/*.*', bootstrapSass.in + 'assets/fonts/**/*'],
        out: dest + 'fonts/'
    };

// css source file: .scss files
var css = {
    in: source + 'css/main.scss',
    out: dest + 'css/',
    watch: source + 'css/**/*',
    sassOpts: {
        outputStyle: 'nested',
        precison: 3,
        errLogToConsole: true,
        includePaths: [bootstrapSass.in + 'assets/stylesheets']
    }
};

// copy bootstrap required fonts to dest
gulp.task('fonts', function () {
    return gulp
        .src(fonts.in)
        .pipe(gulp.dest(fonts.out));
});

// copy bootstrap required fonts to dest
gulp.task('fonts', function () {
    return gulp
        .src(fonts.in)
        .pipe(gulp.dest(fonts.out));
});

// compile scss
gulp.task('sass', ['fonts'], function () {
    return gulp.src(css.in)
        .pipe(sass(css.sassOpts))
        .pipe(gulp.dest(css.out));
});

// default task
gulp.task('default', ['sass'], function () {
     gulp.watch(css.watch, ['sass']);
});

7. Overriding and Customizing

The style of Bootstrap components in a theme are determined by variables. These variables are defined in _variables.scss file.

Take a glance at this file:

$gray-base:              #000 !default;
$gray-darker:            lighten($gray-base, 13.5%) !default; // #222
$gray-dark:              lighten($gray-base, 20%) !default;   // #333
$gray:                   lighten($gray-base, 33.5%) !default; // #555

Notice that there is a !default directive at the end of each declaration line. This directive means current variable will be defined and set value only if it doesn’t be defined or have a value already. So if we assign our own vaule to those variables before importing Bootstrap, we can override them.

We need a copy of _variables.scss in our css source file folder.

$ cd mybootstrap
$ cp ./bower_components/bootstrap-sass-official/assets/stylesheets/bootstrap/_variables.scss ./src/css/_variables.scss

Then import our _variables.scss copy before importing Bootstrap in our main.scss file:

/* main.scss */
@import "variables";
@import "bootstrap";
@import "bootstrap/theme";

Now override what you want in src/css/_variables.scss:

/* _variables.scss */
$body-bg: pink;
$link-color: green;
$font-size-base: 18px;

8. Recompile

At last, recompile our scss into css file:

$ cd mybootstrap
$ gulp

The overriden Bootstrap theme css file now is ready: dist/css/main.css.