Category Archives: JavaScript

Jag Reehal: Responsive Workflow with Grunt, at Refresh Cambridge

Grunt logo

At last night’s Refresh Cambridge meetup, the first of 2014, we were lucky enough to have Jag Reehal come to speak about his experiences with using Grunt — the JavaScript Task Runner — to facilitate easier development of responsive websites.

After some introductory slides to define responsive design (fluid grids, flexible images, media queries) Jag jumped straight into some live coding demos. Here’s a summary of what he demonstrated, with links to the relevant Grunt plugins in the NPM archive where I could find them:

  • A basic Gruntfile is a series of tasks that you want to run, written in fairly basic JavaScript. You can output text, warnings, and cause a task to fail.
  • The time-grunt plugin lets you see how long tasks took to run.
  • The grunt-concurrent plugin allows you to run two or more tasks in parallel instead of in series.
  • It’s easy to create your own Grunt plugin; use the grunt-init-gruntplugin as a template. It includes tests, which is a important part of any plugin.
  • Since we want to build a responsive page, we’ll need to access it on a variety of devices while developing. The grunt-contrib-connect plugin starts a basic server on a local address, so you can load your work-in-progress on your phone or tablet as you work. It also includes a livereload feature, so you don’t have to refresh each device after making changes to the source files.
  • We’ll be using media queries for responsiveness; in order to avoid repetition of values or breakpoints in our CSS, we should use a preprocessor like LESS or SASS.
  • The autoprefixer plugin is especially clever; just tell it what browsers you want to support (or even how far back it should go to support) and it will automatically fill-in browser prefixes for any CSS properties that need it. And the best thing is that you don’t have to worry about going back to change support when new browsers come out!
  • By using CSS compilers, we can easily split out the various parts of our code into logical areas, and import them into one single stylesheet.
  • The grunt-browser-sync plugin is almost like magic; it synchronises form values (and presumably UI state as well) across browsers/devices — update something on your desktop and the same change will appear instantly on your mobile! It also cleverly doesn’t force a full page reload if you update a source file; it simply injects only the updated file into the page, preserving any changes you have made. And it even lets you scroll in sync across devices too!
  • Images are the biggest web performance killer. Responsive images is a confusing topic; you must consider compression, spriting, and retina images. Spriting images in particular has always been a lot of work.
  • The grunt-spritesmith plugin lets you simply maintain a source file full of images; when run, the plugin converts all the images into a single sprite, together with the accompanying CSS. Adding a new sprite is now just a case of dropping the new image into a folder; no more re-calculating background positions!
  • Alternatively, you might want to use base64 encoded images. The grunt-image-embed plugin handles this for you (although obviously you need to balance the multiple files vs CSS size performance issues).
  • The ultimate icon solution is provided by the grunt-grunticon plugin, which takes SVG icons as its default type, while also creating a sprited PNG fallback and individual images, and uses JavaScript to decide which is the best format to use.
  • When it comes to larger images, no standard solution has been decided upon yet, but in the meantime the grunt-responsive-images plugin does most of the work for you. Simply provide it the large image and it will automatically create resized versions that are interpreted by the <figure> markup to serve different images depending on screen size. Only the images needed are downloaded.
  • An alternative is the BBC’s Imager.js library, which allows you to specify the breakpoints in a simpler JSON format rather than writing out a full set of srcsets.
  • For creating production-ready resources — concatenated and minified — there are plenty of plugins such a cssmin (for CSS), uglify (for JavaScript), smushit (for images), etc.

Unfortunately I had to leave before the end of Jag’s talk, but I’ll add any additional notes I receive from other attendees. It was a great demonstration of the power of Grunt’s plugin architecture (and I’m sure that a lot of these plugins work exactly the same within new-kid-on-the-block, gulp.js too), and reminded me of the recent blog post complaining that too often programmers don’t bother to automate repetitive tasks. Armed with the power of the relatively easy-to-install Node and Grunt, designers finally have a way to automate away the most time-consuming parts of their job, and concentrate on building great user experiences.

If you’ve never given Grunt a try, I highly recommend it; it’s not as scary as it looks, and you’ll be amazed at how much easier it can make your life!

How I made a website behave more like a book

I’ve been idly sketching ideas vague ideas for a redesign of my blog this week, and found myself heading down a well-worn route. A blog (I said to myself) is really nothing more than a collection of titles and text — maybe a few images thrown in here and there, probably a datestamp, but that’s basically it. Focus on the content.

But when I started sketching how that sort of content-focused site might look, I found that it all started to look a little familiar. Andybudd.com. Zeldman.com. Medium.com. Any of a dozen Squarespace templates. There was obviously a limit to what one could do with nothing but a title and a handful of paragraphs.

Nature Paint screenshot

Then, in an interview with Cole Henley in .NET magazine, I spotted a screenshot of the Nature Paint website. Although Cole has actually used a variety of different templates to build that site, it was the two-column layout that caught my eye. Perhaps that could be the difference, the tweak I was looking for to turn a blatant rip-off into something a little bit special.

Multiple columns with CSS3

Turning plain paragraphs into multi-columnar layouts is pretty simple with CSS3 now. The column-count, column-width and column-gap properties let you create equally spaced, equal height columns within an element, and you can break up the flow through judicious use of the column-span or column-break-before properties. You can even add nice newspaper-style dividing lines with the column-rule property.

However, there is one enormous problem with trying to display multiple columns of text on the web: viewport size. In a magazine or newspaper, you can hold the entire page in front of you, and your eye can easily move from the bottom of one column to the top of the next. But on the web, it is entirely possible that your reader has scrolled so far down to read a longer piece of writing that the top of the next column is off the visible page. Breaking off mid-sentence to scroll back up to find the next column is not an optimal reading experience. Overflowing columns

I started to draw up a list of requirements for a solution.

Recipe for a pleasant multi-column read

When you read a book, you are effectively reading a double-spread page with two columns of text. You read the left-hand side, then you read the right-hand side, and then you turn to the next page. Magazines might have four or more columns; newspapers up to seven or eight. But the principle is always the same — your eye is guided from column to column across the page, until you need to move onto the next. So, if on the web you are reading a lengthy piece of writing consisting of many many paragraphs, what we need to do is break it up into chunks that fit nicely into the viewport window. The viewport becomes your double-spread book page, and readers can comfortably read each collection of blocks of text before scrolling down to the next ‘page’ of content. I experimented with a few different methods of achieving this, and eventually arrived at a relatively simple JavaScript solution: View Demo page

We declare a single class to handle the column settings:

This class is applied to the container element, so that even if the script doesn’t run we still get something approximating what we intended.

The script then loops through all of the child elements of the container, moving them in batches into new containers, which each get the same .columns class applied to them — these represent the ‘page’ we discussed above. The size of each ‘page’ is determined through a combination of the viewport size, the font size, and the line height of the site. By supplying a list of those elements that should ‘break out’ of the multi-column ordering, we can make sure that the intended flow of the article is preserved. It’s not perfect, but it prevents columns overflowing the viewport and (I think) makes for a more pleasant, book-like, reading experience.

In browsers that don’t support CSS3’s column properties, the script has no effect, since both ‘before’ and ‘after’ states use the same declarations. (If I was using Modernizr I would probably check for support of those properties first, and not run the script at all if they were not present.)

Improvements and feedback

The script makes a reasonable job of breaking up the content into roughly the right-sized blocks for the viewport, but I’m sure it could be made a lot more accurate than I managed with my rusty maths. It also need to be made a little more flexible in terms of coping with different types of the same content (e.g. inline images and larger full-width pictures), and I can imagine that adding some basic keyboard navigation would make for an even more relaxed read.

I appreciate that this isn’t an implementation that is going to be useful for very many other people, but it was fun to figure out, and if you do happen to use it or have any suggestions for improvements, let me know.

Quick Fix: Google Analytics event tracking not working? Check your types!

Google Analytics’s Event Tracking is a powerful way to gain a deeper understanding of what is happening on your website. With event tracking, you can record each click, keypress or mouse move; it becomes easy to find out which fields are being filled or skipped on a form, or which thumbnails are being hovered.

I came across one sneaky gotcha this morning, though. I wanted to track the number that was displayed in a field at the point the user clicked on an “Add” button:

_gaq.push([
  '_trackEvent', 
  'Page Updates', 
  'Plus button clicked', 
  parseInt($('#count').text())
]);

On reviewing the data in GA, however, none of the clicks were being captured.

It turns out that Google will not record the event if the fourth parameter is of type Number. The simple fix was to make it a String type:

_gaq.push([
  '_trackEvent', 
  'Page Updates', 
  'Plus button clicked', 
  parseInt($('#count').text()).toString()
]);

Normally this wouldn’t come up as JavaScript has a tendency to treat most variables as Strings unless you’re careful about how they are created. In this case, relying on parseInt() to find a number turned out to cause more problems than it solved.