Last week I had a little hack at building a quick ‘n’ dirty extension to get image_optim better integrated into Middleman.

Let’s face it; serving big, bloated images is for chumps, that’s why the image_optim tool is really awesome. However, I wanted a way of getting Middleman to automate running it for me, and better integrate it into the whole middleman --build workflow.


It is already pretty easy to get image_optim to process a bunch of files just by using some bash in a deploy script — you can just have the deploy script run it after it has finished building markup & assets via middleman build.

For example;

image_optim -r $(find ./build -type f -iname '*.png' -o -iname '*.jpg' -o -iname '*.gif')

…but this doesn’t really work too well when you are using other tools like middleman-s3_sync, middleman-s3_redirect, or middleman-cloudfront, which are chained to run after a middleman build — not much point uploading your images before they have been run through image_optim!

So I made (the imaginatively titled) middleman-imageoptim gem! It integrates into the Middleman build process so will just be run as a part of constructing, and then deploying the rest of your site.

Anyway, if big, dirty, sweaty images aren’t your thing and you use Middleman I would love to know what you think!

Go install image_optim, stick the following in your Gemfile;

gem 'middleman-imageoptim', '~> 0.0.4'

…activate the extension (there are lots of options you can play with too — check out the repo);

activate :image_optim

…and let me know what you think!

Removing tap-delay from iOS WebViews

Have you even noticed in Mobile Safari (and UIWebViews, and Home screen web-apps) that when you tap a link or button there is a slight delay (300ms to be precise)?

The reason this exists is as an assistive mechanism for browsing the (very often) touch-hostile web. Interacting with anchors in websites where touch targets are not optimised for small screens and fat fingers can be a frustrating business and this delay/highlight is a method of messaging to the user which link they actually tapped.

That’s great and all, but what if you are a responsible developer and have accommodated for touch and designed large, tappable targets? Or if you are building a web-app that should look, feel and respond natively?

This behaviour becomes pretty frustrating in those cases, especially so in the case of a web-app where navigation & interaction is task based and helps maintain the user’s focus on the job at hand.

According to Jakob Nielsen:

1.0 second is about the limit for the user’s flow of thought to stay uninterrupted, even though the user will notice the delay. Normally, no special feedback is necessary during delays of more than 0.1 but less than 1.0 second, but the user does lose the feeling of operating directly on the data.”

So in a touch-friendly web-app we really can’t afford to throw an extra 300ms on top of the response time.

A (kinda) fix

I was wrong about removing the delay with just CSS — you actually cannot (which sucks). However, you can help give the impression of a more reactive interface by removing the visual tap cue.

Without using javascript there is no way to remove the delay completely, however there is a pretty trivial way of giving the perception of the UI being faster with just some CSS.

By default when a link is tapped UIWebViews render a garbage grey “tap-area” around the hit target, however this can be re-styled to be transparent.

In completely un-scientific testing (read: ‘IMO’) this definitely gives the impression of a more reactive UI by removing the “I tapped you and now you are just sitting there for 300ms with a janky grey thing hovering over you” experience.

-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-user-select: none;
-webkit-touch-callout: none;

Beware though that webkit-user-select does exactly what it says on the tin, if you apply that to your HTML tag then everything on your page is no longer selectable…probably not what you want.

To get around this I use this handy little bit of SCSS, which I the explicitly apply where removing delay makes sense (big UI buttons, navigation, etc). Using something like Modernizr allows you to only apply it to touch devices too.

html.touch %no-tap-delay {
  -webkit-tap-highlight-color: rgba(0,0,0,0);
  -webkit-user-select: none;
  -webkit-touch-callout: none;

I’ve been a pretty big fan of Pasquale D’Silva for ages, ever since I stumbled across some of his illustrations a few years back — he has an amazingly distinctive style which I really rather like. :-)

More recently he’s been working as an animator, and today I came across an awesome article he wrote on the subject of Transitional Interfaces.

It’s a really great read. Pasquale highlights the importance of the role that animation & motion plays in creating more engaging, and accessible user-interfaces that guide and inform, by relating animation to real-world concepts of movement.

“Folks keep throwing around the word ‘delight’ when referring to animation and cute interactions. Cool and great for those guys. Guess what though? Animation can be used functionally too. It’s not just an embellished detail.”

“[…] animation can help to provide context. It helps brains understand how the information flows.”

After reading Pasquale’s article I got thinking about how often I actually make the time to really give detailed thought to how animation can help, guide and give context in what I’m working on…more to the point how I can design UI and animation together to make it relatable to IRL concepts.

The Web is not a static medium. The way we design for it should not be either.

Ironman Melbourne

After the last three years of trying to make it to the start-line of another Ironman, I finally managed it this year. It is now the day after & I’m bed-ridden, so I decided to write a race-report!

This is completely non tech-related in any way, and is pretty long, rambling, and quite possibly incoherent. You’ve been warned! :)

I managed to have a really great build up during the few months, then weeks prior to the race. Went in feeling (really) nervous, but pretty confident that I had aced my prep and done all that I could.

Race morning was a 4am wake-up, to allow for food and then the drive to the race start. I could tell we were in for a pretty epic day early on as even that early the wind was already quite violent and gusty. This was more than confirmed when we arrived in Frankston to be greeted by white-caps and very lumpy surf (& I can call it surf, there was actually someone surfing it).

Went in and finalised my T1 (bike) transition — tyres, prepped the bike (gearing, etc), and then slowly started pulling the wetty on.

Was working really hard to stay focussed, get more food down (and keep it down!), and try and get in the zone.

Swim 30:36, 2:02/100m

 Pre swim-start warming up…lots of time to kill with the changed swim course.
Pre swim-start, warming up…lots of time to kill with the changed swim course.

Given the conditions the race organisers decided (twice) to shorten and alter the swim course, which also meant that the start time was pushed back a few times to account for the shorter duration. This made for even more standing around waiting…grrr.

In hindsight I think the decision was a good one (for the sake of safety). The swim was quite simply a meat-grinder. Completely insane.

A combination of 2200 competitors, a mass and ungraded start, very hard conditions (wind, surf and strong cross beach current), and a shorter duration tells you all you need to know. I personally saw 3 people hauled out of the water by life-guards during the 1.9km, and would not be surprised if there were more than a few black eyes and broken noses.

Personally I was really, really unhappy with my swim. Normally I really like the swim leg as it really rewards stronger swimmers over the longer duration and allows you to set the tone onto the bike (i.e beat the masses out of the water, through T1 and onto the bike — huge advantage). Today I just got absolutely beaten up. I copped elbows twice that had me seeing stars, and found swimming through the crowds and surf to be really frustrating. No ability to actually put your head down and swim. Very start/stop. I also swallowed so much sea water that I vomited twice. Eww.

Just to cap it all off I got caught out in the crowds and by the current and exited the water about 400m the wrong way down the beach, making for a long, wet-suit clad run-of-shame into T1.

If I had to run the race again I would take 3.8km of calmer water over the 1.9 kilometers of chaos. Easy decision. The average pace tells the story—in normal conditions I would usually average 1.30-40/100m for the full 3.8km, but could only manage 2.02/100m for 1.9km. Yikes, not a great way to start the day.

Bike 5:16:27, 34.13 km/h

Half way through the bike, Frankston turn-around.
Half way through the bike, Frankston turn-around.

Bike leg on Strava: http://app.strava.com/activities/45757404

Came out of the water pretty mad and with a point to prove. I also knew that I would be moving through some pretty serious traffic given my swim and would need to put the hammer down in order to get any clean air and be able to focus.

The outward trip on the first lap was against the wind, but I worked solidly and basically just sat right and passed a pretty steady stream of people on my left. I was aware that I was working a little above what I would have ideally paced myself at, but I was convinced that the trade off would be worth it to move up the field, just so long as I was careful not to push too hard.

This was working really well until I was swept up by a big (50-60 riders) group that were quite blatantly all drafting (I saw at least 5 groups like this).

These guys were riding wheel to wheel, half of them freewheeling at 35km/hr into the wind. This was really infuriating as their pace was yo-yoing as they “rolled turns”, and was making life really hard for me as I was keeping my draft-box off the back to zone in and ride my pace.

They were essentially just riding a 180km crit race. You really have to wonder what these dickheads were playing at—the whole point of an IM is that it is a solo affair. What made matters worse was that there was actually a TO (technical official) sitting alongside these wankers who was doing nothing about it.

Shortly after this I had words with the TO (who unwilling to take control of the situation—these guys should have been penalised & then DQed). Shortly after that I cracked it and lifted my pace again to ride around the bunch and off the front.

This happened several more times (get caught by the bunch, get angry, ride away, rinse/repeat) until we hit the tunnel. I knew these jokers would be messing about in the tunnel not wanting to work, and that the bunch would probably fracture on the climb out of the tunnel. I made sure to leave it in the big ring and ensured that I had enough of a margin that I didn’t have to see them again.

The ride south was awesome, sitting on 60km/hr for long stretches on a TT bike, with carbon tubulars singing underneath you is pretty awesome. :) Averaged a shade over 40km/hr for the return.

Lap two was more of the same, though I finally had enough room to pace properly. I was more disciplined about heart-rate for this 90km, though I could feel some of the unwanted efforts of the previous 90km in my back and legs. Still managed to ride strongly, especially given that the wind started to swing west during the outward journey and turned into a pretty brutal cross wind. Not a day for a disc. I was being blown meters sideways even just on my 90mm rims. Scary stuff. Was having to be opportunistic about using the TT bars.

Spent the last 20km of this lap starting to warm the legs up for the marathon, trying to match bike/run cadence, stretch back and shoulders, and get last minute food down.

Run 4:02:50, 5:45/km

About 10 meters to go. Best 10 meters EVER.
About 10 meters to go. Best 10 meters EVER

Run leg on Strava: http://app.strava.com/activities/45758380

The first 20km of the run were simply magical. I was feeling a million bucks. I think my first couple of kays were pretty close to being sub-four-minutes, and I was really having to put the brakes on and not be too silly. Loving it. I managed to settle down a little by about the 5km mark into a nice gait and was feeling really comfortable with a ~4:50min/km pace.

I was conscious that due to the really strong winds on the bike some of my food and fluid intake had been compromised (I missed a bottle and 2 gels on the bike), so I was making an effort to really utilise the aid-stations to make sure that I was properly fuelled. However I might have overcompensated slightly as I was starting to get some minor stomach cramps around 17km.

Coming into Mordy across the bridge things started to go down hill—just as the camber on the road reversed (Franga->Mordy was all in one direction in the outside lane) my left foot exploded with cramps. I pushed on from there until the next aid station were I ate about half a kilo of raw vegemite (delicious). Over the next few aid stations and about the next 8km I was really battling with various mutinous limbs. I was throwing down pretty much all the fluid I could get my hands on, despite still having a very upset stomach.

I finally managed to get the cramping under control but by this point my previous good pace was broken, and I was also now battling with really nasty stomach cramps and some nausea.

The rest of the run saw me struggling along trying as hard as possible to keep the pace up, and see-sawing between going hunger-flat and my stomach rebelling. The last five kays I couldn’t have blown out a candle—I had absolutely nothing left and the only thing keeping me from walking it out was the proximity of the finish line. There was some pretty serious internal-monologue/confirmation stuff going on for this last bit. The faster you run the faster you’re done. :)

Hitting St Kilda was obviously awesome, and running those last two hundred meters down the chute was just an amazing flood of relief, happiness and satisfaction that I left it all out there. The icing on the cake was a 9:59:56 hour day. Couldn’t be happier.

Lastly I just wanted to say a really massive thank you to all the people that came along on the day. I can’t even begin to tell you how much it helps seeing a familiar face or having someone yell out support on such a long day. Thanks! <3

TIL: The AirBnB tech-talks site (all the videos are on YouTube too) is pretty awesome! I don’t know how I managed to miss it for so long—they host a regular tech-talk by someone interesting every fortnight, and then make the video available for everyone—cool stuff!

This morning I watched the latest talk “Dive Into Performance” by Steve Souders (he also made the slides available!).

It runs a little over an hour, and is packed with awesome knowledge that you should probably try and jam into your skull. Some of it is pretty common-sense type stuff but there are some real gems in there.

A few of the things I picked up;
  • The nav timing spec (window.performance) is full of awesome information (all good browsers but only Chrome flavours of Webkit—WTF Apple?). MDN has some more interesting reading too.
  • webpagetest.org is even more amazing than I thought. You always learn a lot watching power-users, Steve is a Webpagetest.org power-user. This is a must for squeezing free speed out of your app/site.
  • Browser asset load order is != to document order. Modern browsers use speculative look-ahead parsing of a the document while blocked (say while waiting on a <script> tag) to actually eagerly-load content “further down” the document. Crazy stuff! According to a quote from Steve during his talk, the Chrome team attribute a ~30% page speed increase to this.