CSS loading spinners with no HTML

Had the idea to make some loading spinners using CSS a couple of months ago. Inevitably the internet got there first, and there are already many excellent examples out there, including one from Codepen‘s “Top 100 Pens of the Year” no less – so yeah, not a new idea.

However, there was one thing I felt I could bring to the party – most of the examples I found used extra html elements, making them messier, and harder to add and remove via JS, so I made a bunch using just a class name attached to an existing containing element.

See the Pen CSS loading spinner experiments by Mat Hampson (@mathampson) on CodePen.

So if you have a container you’re loading stuff into all you need to add to the loading class is a *{display: none;} to hide whatever’s in there, and maybe a default height to give the spinner some space.

(Note the waning moon version requires spinning the container, which won’t be acceptable in every situation.)

Objective severity definitions

Task management systems usually come with severity and priority options, however I’ve rarely seen clear, up front definitions of how they should be used. There’s myriad ways of course, but here I’m going to share a simple one I’ve used in a couple of my former placements, just as a straw man.


Severity can be used to flag the difficulty of the fix, however that can be achieved by tasking out and estimating the fix. I think it’s better to use it to flag to the business how major the issue is from the user’s point of view.

There are three factors that I chose to decide that:

  • Whether functionality or content is impaired
  • How obvious that impairment is to the user
  • How many users are affected

These can be combined into 3 general situations, with severities depending on the proportion of users affected:

Situation 1: Content/functionality broken, and obvious to users

  • All users => Severity 1
  • >10% users => Severity 2
  • <10% users = > Severity 3

Situation 2:  content/functionality broken, but not obvious to users

  • All users => Severity 2
  • >10% users => Severity 3
  • <10% users = > Severity 4

Situation 3: Display issue, not obscuring content or functionality

  • All users => Severity 3
  • >10% users => Severity 4
  • <10% users = > Severity 5


Use this to flag to the developers which tasks to tackle first. It should be influenced by the severity, but also by stakeholder views and business needs – things like booked ad campaigns for the product, or politically powerful stakeholders who may otherwise cause the project difficulty.

This makes priority more subjective, but hopefully less than it would have been without the objective severity value acting as a guide.

Bonus round

After agreeing these severity definitions, the BA and project sponsor can get together and (without reference to specific issues, which gets emotive) do a cost benefit analysis to decide how much time it’s normally worth the business spending on each severity. For example:

  • Severity 1 to 3, fix no matter how long it takes
  • Severity 4 spend no more than a developer day
  • Severity 5 spend no more than a developer hour

This gives a clear, pre-agreed mechanism to drop tickets aren’t worth the money / lost development time to the business – an otherwise controversial and CYA-riddled action.


  • Give the user a voice via severity
  • Agree severity metrics up front, so you don’t get mired in subjective debate
  • Define a ticket’s severity before priority, using those metrics
  • Give the business a (better informed) final say via priority
  • Define what fixing each severity level is worth to the business

Typographical grid plugin

Here’s a snippet I wrote the other day that overlays the page with a typographical/layout grid when activated. Others exist, but very few, and not with the functionality I wanted, so there’s room for another.

I made it into a jQuery plugin simply to make it clear it’s dependent on jQuery: It’s not suitable for chaining (which apparently makes it a “utility plugin“).

Also, I’ve namespaced it as the rather vague ‘devTools’ in order to allow me to possibly add more tools to the plugin later while maintaining backwards compatibility. Hope you find a use for it!




	[columns], [column width (px)], [column margins (px)], {[optional configuration]}

Optional configuration

Key Notes Example Default
qs Value of query string value to look for if grid is to be activated that way. false leads the grid to be shown on load. ‘grid=true’ false
id The id used for the div containing the columns. ‘myGridContainer’ ‘browserToolsGrid’
container the element the grid is to be appended to. ‘#myContent’ ‘body’
center A boolean stating whether your website is centered. true false
color the colour of the grid. rgba is best so you can see through the grid. ‘rgba(200, 200, 100, 0.3)’ ‘rgba(204, 243, 204, 0.3)’
textColor the colour of the info text. ‘#ccc’ ‘#aaa’
outerMargins Use far left and far right margins true false
toggle Show the toggle button. false true


Centered site, activated by adding ‘grid’ to the query string

$(function () {
	$.devTools.grid(16, 45, 15, {

More complex example

A double grid (with sub columns), shown by default.

$.devTools.grid(6, 158, 2 , {
	hideToggle: true
$.devTools.grid(6, 98, 62 , {
	hideText: true



Battleships GS

In the spirit of a brand new month of April, I’d like to launch my latest personal project. It’s an open-source, online, multi-player, real-time, cloud-based, gaming platform, with the age-old classic ‘Battleships’ as the first release. You’d be a fool not to try it out:

Play Battleships GS now!.

How to play

  • Take a copy of the game (File > Make a copy…)
  • Share your copy with a friend (share button, top right)
  • Follow the instructions on the opening tab of the spreadsheet.

Asynchronously reloading the Twitter JS widget

As anyone who’s used it knows, the standard JS Twitter Widget document.write-s itself into the page by default. This obviously sucks because a) you have to have the JS for it mixed up in your content, which in turn means b) if it hangs for some reason, all content after the widget is held up.

Asynchronous loading

The way round that (as others have found out before me) is to use an undocumented API argunment “id”, which defines the ID you would like the Widget written into. This in turn allows you to call the widget code as a function on, for example, JQuery’s document.ready, shown below, which in turn allows you to load Twitter’s widget.js at the bottom of the page, even using $.getScript() to delay it even further:

// Note: This function should not be global like this in real world use 
function renderTwitterWidget(){ 
	new TWTR.Widget({ 
		id: 'iTwitterContainer', 

		// ...Rest of normal Twitter widget code... 


$(function () { 
	$.getScript('http://widgets.twimg.com/j/2/widget.js', function(){ 
		renderTwitterWidget (); 

There: Fail Whale proof.

Asynchronous reloading

Thing is the design required that the user be able to refresh the widget with a different search term. The above code can do that, with a couple of additions:

  1. Add the search term as a parameter to be sent to the function.
  2. Use the .stop() method (found by searching the Twitter Widget source) to kill off previous instances’ setTimeouts, which otherwise carries on populating your container with the previously chosen search term(s).
// Note: Again, this variable and function should not be global in real world use: 
var twitterWidget = false; 
function renderTwitterWidget(searchString){ 
	if (twitterWidget){ 
	twitterWidget = new TWTR.Widget({ 
		id: 'iTwitterContainer', 
		search: searchString, 

		// ...Rest of normal Twitter widget code...

$(function () { 
	$.getScript('http://widgets.twimg.com/j/2/widget.js', function(){ 
			renderTwitterWidget("New Search Term"); 

Separate CSS classes for Javascript

There was a mini debate among friends on Twitter recently about using separate class names for JavaScript. For example <div class="tab iTab">; with your CSS attached to “.tab” and your JS attached to “.iTab”.

Coincidentally this is something I started doing a few projects ago, thinking separation good / overloading bad, and I have to say I’m completely sold on it, here’s a few specific positive effects I’ve experienced:

Design / Markup changes shouldn’t break JS

If you want to style a list you might put a class on the ul, if you want those items to be interactive you might target links within the list like so: $(".listClass a")… Then the design or content changes and it no longer makes sense to have a list, you change it, and the JS falls apart.

CSS classes might not be best put on the interactive element

Imagine in the situation above you want the items on the list to be individually addressable by JS – so you need classes on each item. Do you then use those classes to style the list – even though each item might look the same? No – you put a class on the ul like before. In other words since the two types of class have different purposes, they should be treated – and named – separately.

It makes collaboration easier

A new front-end dev comes along, sees a CSS class with no styles applied, removes it for the sake of tidiness, JS stops working. Or, a new JS dev comes along, wants to update how the JS works, moves / renames the trigger class, layout falls apart. And for “new dev” you can also substitute yourself, updating the project 6 months later. 🙂

Reusing code

You did a cool slideshow effect in that old project, and want to use it again, but with different styling – which are the class names you need to port over to the new markup to make it work? Cue hunt through the JS.


One good counter argument I’ve seen is that this technique pollutes your HTML with traces of JavaScript, in the nasty way that onclick=”” used to.

This is fair on the surface, but if there are interactive elements there, using CSS classes to trigger, then that cross contamination has already happened. Much better in my book to be honest about it.

Colour grouping 8-bit CSS sprites

It’s reasonably well known that Fireworks can create alpha-transparent 8-bit png files (so can various other widgets but curiously, still not Firework’s celebrity sibling, Photoshop).

That’s an awesome trick, because they’re generally about a third of the size of 32-bit – however they are limited to 256 colours, which won’t work for CSS-spriting most designs.

Which leads me to a technique I’ve been trying recently: When you have a design with several clearly identifiable colour groups, make separate sprites for each colour – blue, red, purple, whatever – then export them as 8-bit.


A recent Facebook game had a character sprite sheet that was a meg. I split out the character faces, that had lots of gradients and mixed colours into a 32-bit sprite (~200k) and 8-bit exported the mostly flat-fill, similar-coloured bodies (~200k), resulting in a hefty saving (~600k / 60%). (Note the heads and bodies were already separate as they were swoppable, so the split wasn’t a big deal.)

Another recent app had a design with several bold primary colours used for different icon and button sets. I went to town with this technique, making 4 colour-specific 8-bit sprites and a single 32-bit catch all sprite for the other colours and things that didn’t work at 8-bit:

Each sprite was at least 20k smaller than its 32-bit equivalent, which easily justifies the ‘weight’ of each extra file request (calculated by one BBC dev many years back as very roughly equivalent to ~2.5k on a default Apache install).


This may not be a suitable technique for elements where there are

  • subtle or extensive gradients
  • a mix of of colours or
  • only a few items of that colour – where the saving won’t offset the downloading of an extra file

Looped playlist with SoundManager2

Just a quickie: The other day I had to add a backing track to a game. Stack Overflow lead me to the excellent SoundManager2 library, which features an extensive API and nifty HTML5 with Flash fallback behind the scenes to give maximum platform coverage & performance.

The only problem I had was finding an example of looping through a list of files endlessly, so I rolled my own, using simple recursion, and here it is in case it helps anyone else.

var audio = [];
// Array of files you'd like played
audio.playlist = [

function playAudio(playlistId){
	// Default playlistId to 0 if not supplied 
	playlistId = playlistId ? playlistId : 0;
	// If SoundManager object exists, get rid of it...
	if (audio.nowPlaying){
		// ...and reset array key if end reached
		if(playlistId == audio.playlist.length){
			playlistId = 0;
	// Standard Sound Manager play sound function...
	soundManager.onready(function() {
		audio.nowPlaying = soundManager.createSound({
			id: 'sk4Audio',
			url: audio.playlist[playlistId],
			autoLoad: true,
			autoPlay: true,
			volume: 50,
			// ...with a recursive callback when play completes
			onfinish: function(){
				playlistId ++;

// Start

(Note for clarity I’ve stripped out the surrounding code, including most scoping, so you’ll probably want to consider/remedy that if you use this.)

Remotely rebuilding a site

Ever had to redo a site design without access to the files? Sounds ridiculous I know, however that’s exactly what I had to do recently when applying the Starbucks rebrand and associated redesign to their non-US sites (e.g. Russia, Canada) and investor relations site.

The sites were hosted by Starbucks and build by a third party, and for security vs. tight schedule reasons they wanted to limit the update to overwriting assets, specifically CSS and images, so…

First step was to get a copy of their CSS onto my localhost (or whatever local http development space you have to hand). Straightforward enough.

Next I needed to persuade the browser, when viewing the live site, to redirect the request for that CSS to my copy.

Initially I did this by editing the path in the net inspector of Firebug, however I quickly realised this would be a pain if I accidentally refreshed. It also wouldn’t allow cross browser testing.

I then looked at Fiddler (a desktop proxy tool that allows you to inspect and interfere with browser requests) but couldn’t find the requisite functionality (please enlighten me if you know how). Then a colleague suggested Charles Web Debugger might do the job. Charles is similar to Fiddler, but I’d skipped it since it wasn’t free. Turns out it has a functionality complete trial however, and after a bit of a rummage I found it can bind specific request paths to new URLs. The benefit of that? It works for as long as Charles is running, and will apply to all browsers.
Now work could start, edit the local CSS, view the live site, see changes appear.

If the site is CSS-based (as in the investor relations site) all the design images will referenced from the CSS, so updating them just means hosting the new images locally alongside the CSS and updating the URL() values in the background{} declarations to reference the localhost. (Just remember to change them back before packaging up the files for delivery.)

If the site is a bit older (tables and img tags) you can locally host those images alongside the CSS and add new paths (including * wildcards if useful) to Charles. Bit of a pain, but then working with tables always was, right?

Browser support deprecation flowchart

From the archives of jobs gone by, I thought this little known doc might be of interest: The matrix of factors to be considered in deprecating browsers from the BBC’s browser support standard.

Alongside the BBC website visitor stats this chart (from the appendix of the BBC’s browser support standard) aims to provide a clear framework for discussion around dropping support for old (or picking up support for new) browsers.

As most web folk will know this is a source of constant bickering in the industry. Multiply this by the BBC’s public service remit and you have a recipe for some very long meetings, in one of which we were passed the suggestion of maintaining support for an old version of Safari because “mac users complain a lot”. Hmm.

I felt it was time we worked through the various factors that should be considered, and made a stab at their relative importance. This chart was the result.

While it doesn’t replace the discussions (there’s always be a special case or two to consider) anything that helps scope them and provide clarity is a win in my book.

Now – which of you Mac users wish to pick holes in it? 😉