Tom

Optimising your Front End Development

Learn about the useful tools & libraries that have helped us speed up and optimise our frontend development workflow. These include Bootstrap, Sass, Grunt, and a few more.

Bootstrap

At Webscope we use the Bootstrap  Framework for most builds. It is an incredibly solid foundation to build on top of, with simple, consistent styling for the majority of base elements already set for most web browsers.

It has a simple yet flexible grid system, that makes it easy to create the most effective layouts for mobile, tablet, and desktop devices. 

Drupal Bootstrap

We have started our own subtheme based on the contributed Drupal Bootstrap theme which includes a number of code snippets that we found ourselves reusing on every project.

We use Sass as our CSS pre-processor of choice so we use the official Sass port of Bootstrap. 

We have also recently switched to using Libsass and Grunt to compile our Sass code. This has meant we no longer have any Ruby dependencies which has made things much simpler (if you have ever tried to debug compiling issues with a Compass/Ruby setup you’ll know what I mean). It also compiles extremely fast, usually under one second, while our old Compass/Ruby setup could take over 10 seconds to compile (depending on the project). When you're saving and compiling your code hundreds of times a day, this soon adds up to a significant benefit.

Working with Media Queries

We have borrowed some handy mixins from Ben Frain for dealing with Media Queries

They allow us to use Media Queries in the normal flow of the document, rather than in a separate file, or all lumped at the bottom, as we had done previously. This personally has been the most beneficial improvement to my workflow of late. At a glance I can see the cascade of media queries for a single element, whereas previously I was jumping back & forth between files, struggling to understand what was happening at each breakpoint.

// Media Query Variables
$XS: 580px;
$S: 768px;
$M: 992px;
$L: 1200px;
$XL: 1440px;
 
// Media Query Mixin
@mixin MQ($canvas){
  @if $canvas == XS{
     @media only screen and (min-width: $XS) { @content; }
  }
  @else if $canvas == S{
     @media only screen and (min-width: $S) { @content; }
  }
  @else if $canvas == Sneg{
    @media only screen and (max-width: $Sneg - 1) { @content; }
  }
  @else if $canvas == M{
     @media only screen and (min-width: $M) { @content; }
  }
  @else if $canvas == L{
     @media only screen and (min-width: $L) { @content; }
  }
  @else if $canvas == XL{
     @media only screen and (min-width: $XL) { @content; }
  }
}

I’ve also created some sublime snippets to speed up writing these mixins, you can download them here.

Below is is an example of working with these mixins, also featuring the excellent Hayaku plugin for Sublime Text 

The code in the above example will compile to...

Using Grunt

Grunt is a JavaScript task-runner written in node.js. It allows you to automate repetitive tasks like minifying and concatenating JavaScript, and compiling css from sass.

Here is the gruntfile we are currently using

module.exports = function(grunt) {
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),
		watch: {
			sass: {
				files: ['sass/**/*.{scss,sass}','sass/_partials/**/*.{scss,sass}'],
				tasks: ['sass:dist'],
        options: {
          livereload: true
        }
			},
		},
		sass: {
			options: {
				sourceComments: 'map',
				outputStyle: 'compressed'
			},
			dist: {
			  options: {
          includePaths: require('node-bourbon').includePaths
        },
				files: {
					'stylesheets/style.css': 'sass/style.scss'
				}
			}
		},
    concat: {
      option: {
        separator: ';'
      },
      dist: {
        src: [
          'external/bootstrap-sass-official/assets/javascripts/bootstrap/*.js', 
          'external/bootstrap-select/dist/js/bootstrap-select.js', 
          'external/bootstrapValidator/dist/js/bootstrapValidator,js',
          'javascripts/**/*.js', 
        ],
        dest: 'javascripts/<%= pkg.name %>.js'
      }
    },
		uglify: {
      dist: {
        options: {
          mangle: true,
          compress: true,
          banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
        },
        files: {
          'javascripts/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
        }
      }
    }
	});
	grunt.registerTask('default', ['sass:dist', 'watch']);
	grunt.registerTask('deploy', ['concat:dist', 'uglify:dist']);
	grunt.loadNpmTasks('grunt-sass');
	grunt.loadNpmTasks('grunt-contrib-watch');
	grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-bower-clean'); 
};

So when we run  grunt, Grunt will watch all the Sass files and compile them to CSS on save. It also runs livereload, so our browser will reload automatically, allowing us to see the changes instantly.

It also creates a sass map file which allows us to inspect the webpage in Chrome Developer tools and see exactly which file and which line is creating the generated CSS.

We also have grunt deploy which scans our theme folder and concatenates all our javascript files into one file, and then compresses it using uglifyjs.

Project Structure

I typically break up the CSS into sections and place them in a folder called 'components'. These are then imported into the main style.scss file, e.g.

// Libraries
@import "bootstrap-select";

// Sections
@import "header";
@import "footer";
@import "homepage";

// Content Types
@import "team-member";
@import "service";
@import "project";
@import "timeline";
 

Then, within a file for a content-type, I'll structure it like this…

.node-service{
//general styles that will apply to all instances  
}
.node-service.node-teaser{
//just for service teaser
}
.node-service.node-full{
//just for full node
}

Next Steps

Autoprefixer looks like a really nice way to handle vendor prefixes. You just write regular CSS, and autoprefixer will parse it and add vendor prefixes when need be, based on the latest data from Can I Use.

I'm also looking into methods to automatically combine matching media queries into one media query definition, and adding it to our grunt workflow.​ This would cut out a lot of duplicate code.

Follow us on twitter for announcements on when we update our frontend gruntfile, or an upcoming article from Sasha on our backend development workflow.

More blog posts by Tom Rishworth

FontAwesome has become our go to font icon for most projects these days. Its extremely easy to use and has a great range of fonts which are constantly being added to.