Christian Heilmann

Author Archive

Innovating the other web – my keynote at WROC#

Sunday, March 15th, 2015

Last week I was lucky enough to give the opening keynote of the inaugural WROC# event in Wroclaw, Poland. The event, organised by Objectivity was aimed at Microsoft stack based developers and I felt incredibly out of my depth. In essence, I was the Microsoft employee who had much less knowledge about the subject matter than the audience.

WROC# stage

I took the opportunity, however, to tell this sort-of-captive audience about the massive need we have in innovating “the other web”. The web these developers work on day-to-day, the web of large corporations on Windows machines who get functionality from framworks, see the front-end as a complex thing to tame and are beholden to browsers that should have been replaced years ago.

My talk slides are on Slideshare.

Innovating the other web – #wrocsharp keynote from Christian Heilmann

I also recorded a screencast of the talk and uploaded it to YouTube.

Resources I mentioned in the talk:

A few remarks about the event

As you know, I cover a lot of events and have so for several years. That’s why it is a great feeling when you still can get surprised. WROC# was outstanding in every aspect. For a first-time organised event with free tickets and a five figure price tag for the organisers everything went amazingly smooth and you can see the passion and drive of the organisers.

I am humbled and feel very thankful for having been part of this. The way the organisers made me feel welcome and left no question open was exceptional and many conferences can learn from the little tricks they used. The printout with a detailed day-to-day schedule for me was excellent. The “thank you” goodie bag in the room nothing more than overwhelming.

no-questions left with the speaker cheatsheet

Instead of a speaker dinner the day before the event we went on a tour of the city which was also a scavenger hunt. This allowed us to not only get to know the speakers, but also the organisers and get a feeling of the place and its people before being in a venue for a day and leave as strangers again.

goodie bag

Attendees had exceptional catering, endless drinks, coffee and locally brewed beer for the occasion at the after party. The wireless worked and all talks were live-streamed. There was a table football tournament, arcade machines and a band and many more things to keep people around and make them get to know one another.

All in all this was an amazing conference and I spent the next day at Objectivity to give them feedback and help them with a few of their outreach/developer evangelism questions as I felt just giving my talk and being at the event all day wasn’t enough. It was a superb experience, thanks to all involved!

Advancing JavaScript without breaking the web

Monday, March 9th, 2015

Current advancements in ECMAScript are a great opportunity, but also a challenge for the web. Whilst adding new, important features we’re also running the danger of breaking backwards compatibility.

These are my notes for a talk I gave at the MunichJS meetup last week. You can see the slides on Slideshare and watch a screencast on YouTube. There will also be a recording of the talk available once the organisers are done with post-production.The video of the talk is live on YouTube

JavaScript – the leatherman of the web

rainbow unicorn kittenAccurate visualisation of the versatility of JavaScript

JavaScript is an excellent tool, made for the web. It is incredibly flexible, light-weight, has a low learning threshold and a simple implementation mechanism. You add a SCRIPT element to an HTML document, include some JS directly or link to a JS file and you are off to the races.

JavaScript needs no compilation step, and is independent of IDE of development environment. You can write it in any text editor, be it Notepad, VI, Sublime Text, Atom, Brackets or even using complex IDEs like Eclipse, Visual Studio or whatever else you use to put text into a file.

JavaScript – the enabler of new developers

JavaScript doesn’t force you to write organised code. From a syntax point of view and when it comes to type safety and memory allocation it is an utter mess. This made JavaScript the success it is now. It is a language used in client environments like browsers and apps. For example you can script illustrator and Photoshop with JavaScript and you can now also automate OSX with it. Using node or io you can use JavaScript server-side and write APIs and bespoke servers. You can even run JS directly on hardware.

The forgivefulness of JS is what made it the fast growing success it is. It allows people to write quick and dirty things and get a great feeling of accomplishment. It drives a fast-release economy of products. PHP did the same thing server-side when it came out. It is a templating language that grew into a programming language because people used it that way and it was easier to implement than Perl or Java at that time.

JavaScript broke with conventions and challenged existing best practices. It didn’t follow an object orientated approach and its prototypical nature and scope trickery can make it look like a terribly designed hack to people who come from an OO world. It can also make it a very confusing construct of callbacks and anonymous functions to people who come from it from CSS or the design world.

But here’s the thing: every one of these people is cordially invited to write JavaScript – for better or worse.

JavaScript is here to stay

The big success of JavaScript amongst developers is that it was available in every browser since we moved on from Lynx. It is out there and people use it and – in many cases – rely on it. This is dangerous, and I will come back to this later, but it is a fact we have to live with.

As it is with everything that is distributed on the web once, there is no way to get rid of it again. We also can not dictate our users to use a different browser that supports another language or runtime we prefer. The fundamental truth of the web is that the user controls the experience. That’s what makes the web work: you write your code for the Silicon Valley dweller on a 8 core state-of-the-art mobile device with an evergreen and very capable browser on a fast wireless connection and much money to spend. The same code, however, should work for the person who saved up their money to have a half hour in an internet cafe in an emerging country on a Windows XP machine with an old Firefox connected with a very slow and flaky connection. Or the person whose physical condition makes them incapable to see, speak, hear or use a mouse.

Our job is not to tell that person off to keep up with the times and upgrade their hardware. Our job is to use our smarts to write intelligent solutions. Intelligent solutions that test which of their parts can execute and only give those to that person. Web technologies are designed to be flexible and adaptive, and if we don’t understand that, we shouldn’t pretend that we are web developers.

The web is a distributed system of many different consumers. This makes it a very hostile development environment, as you need to prepare for a lot of breakage and unknowns. It also makes it the platform to reach much more people than any – more defined and closed – environment could ever reach. It is also the one that allows the next consumers to get to us. It’s hardware independence means people don’t have to wait for availability of devices. All they need is something that speaks HTTP.

New challenges for JavaScript

This is all fine and well, but we reached a point in the evolution of the web where we use JavaScript to such an extend that we need to start to organise it better. It is possible to hack together large applications and even server-side solutions in JavaScript, but in order to control and maintain them we need to consider writing cleaner JavaScript and be more methodical in our approach. We could invent new ways of using it. There is no shortage of that happening, seeing that there are new JavaScript frameworks and libraries published almost weekly. Or, we could try to tweak the language itself to play more by rules that have proven themselves over decades in other languages.

In other words, we need JavaScript to be less forgiving. This means we will lose some of the first-time users as stricter rules are less fun to follow. It also means though that people coming from other, higher and more defined languages can start using it without having to re-educate themselves. Seeing that there is a need for more JavaScript developers than the job market can deliver, this doesn’t sound like a bad idea.

JavaScript – the confused layer of the web

Whilst JS is a great solution to making the web respond more immediately to our users, it is also very different to the other players like markup and style sheets. Both of these are built to be forgiving without stopping execution when encountering an error.

A browser that encounters a unknown element shrugs, doesn’t do anything to it and moves on in the DOM to the next element it does understand and knows what to do with. The HTML5 parser encountering an unclosed element or a wrongly nested element will fix these issues under the hood and move on turning the DOM into an object collection and a visual display.

A CSS parser encountering a line with a syntax error or a selector it doesn’t understand skips that instruction and moves on to the next line. This is why we can use browser-prefixed selectors like – webkit – gradient without having to test if the browser really is WebKit.

JavaScript isn’t that way. When a script encounters a syntax error or you try to access a method, object or property that doesn’t exist it stops executing and throws an error. This makes sense seeing that JavaScript is much more powerful than the others and even can replace them. You are perfectly able to create a web product with single empty BODY element and let JavaScript do the rest.

JavaScript – playing it safe by enhancing progressively

This makes JavaScript a less reliable technology than the other two. We punish our end users for mistakes made by us, the developers. Ironically, this is exactly the reason why whe shunned XHTML and defined HTML5 as its successor.

Many things can go wrong when you rely on JavaScript and end users deliberately turning it off is a ridiculously small part of that. That’s why it is good practice to not rely on JavaScript, but instead test for it and enhance a markup and page reload based solution when and if the browser was able to load and execute our script. This is called progressive enhancement and it has been around for a long time. We even use it in the physical world.

When you build a house and the only way to get to the higher floors is a lift, you broke the house when the lift stops working. If you have stairs to also get up there, the house still functions. Of course, people need to put more effort in to get up and it is not as convenient. But it is possible. We even have moving stairs called escalators that give us convenience and a fall-back option. A broken down escalator is a set of stairs.

Our code can work the same. We build stairs and we move them when the browser can execute our JavaScript and we didn’t make any mistakes. We can even add a lift later if we wanted to, but once we built the stairs, we don’t need to worry about them any more. Those will work – even when everything else fails.

JavaScript – setting a sensible baseline

The simplest way to ensure our scripts work is to test for capabilities of the environment. We can achieve that with a very simple IF statement. By using properties and objects of newer browsers this means we can block out those we don’t want to support any longer. As we created an HTML/Server solution to support those, this is totally acceptable and a very good idea.

There is no point punishing us as developers by having to test in browsers used by a very small percentage of our users and that aren’t even available on our current operating systems any longer. By not giving these browsers any JavaScript we have them covered. We don’t bother them with functionality the hardware they run on is most likely not capable to support anyways.

The developers in the BBC call this “cutting the mustard” and published a few articles on it. The current test used to not bother old browsers is this:

if ('querySelector' in document &&
    'localStorage' in window &&
    'addEventListener' in window) {
  // Capable browser. 
  // Let's add JavaScript functionality
}

Recently, Jake Archibald of Google found an even shorter version to use:

if ('visibilityState' in document) {
  // Capable browser. 
  // Let's add JavaScript functionality
}

This prevents JavaScript to run in Internet Explorer older than 10 and Android browsers based on WebKit. It is also extensible to other upcoming technologies in browsers and simple to tweak to your needs:

if ('visibilityState' in document) {
  // Capable browser. 
  // Let's load JavaScript
  if ('serviceWorker' in navigator) {
    // Let's add offline support
    navigator.serviceWorker.register('sw.js', {
      scope: './'
    });
  }
}

This, however, fails to work when we start changing the language itself.

Strict mode – giving JavaScript new powers

In order to make JavaScript safer and cleaner, we needed its parser to be less forgiving. To ensure we don’t break the web by flagging up all the mistakes developers did in the past, we needed to find a way to opt-in to these stricter parsing rules.

A rather ingenious way of doing that was to add the “use strict” parser instruction. This meant that we needed to preceed our scripts with a simple string followed by a semicolon. For example, the following JavaScript doesn’t cause an error in a browser:

x = 0;

The lenient parser doesn’t care that the variable x wasn’t initiated, it just sees a new x and defines it. If you use strict mode, the browser doesn’t keep as calm about this:

'use strict';
x = 0;

In Firefox’s console you’ll get a “ReferenceError: assignment to undeclared variable x”.

This opt-in works to advance JavaScript to a more defined and less memory consuming language. In a recent presentation Andreas Rossberg of the V8 team in Google proposed to use this to advance JavaScript to safer and cleaner versions called SaneScript and subsequently SoundScript. All of these are just proposals and – after legitimate complaints of mental health community – there is now a change to call it StrongScript. Originally the idea was to opt in to this new parser using a string called ‘use sanity’, which is cute, but also arrogant and insulting to people suffering from cognitive problems. As you can see, advancing JS isn’t easy.

ECMAScript – changing the syntax

Opting in to a new parser with a string, however, doesn’t work when we change the syntax of the language. And this is what we do right now with ECMAScript, which is touted as the future of JavaScript and covered in many a post and conference talk. For a history lesson on all of this, check out Florian Scholz’s talk at jFokus called “Whats next for JavaScript – ES6 and beyond”.

ECMAScript has a few excellent new features. You can see all of them in the detailed documentation on MDN and this post also has a good overview. It brings classes to JavaScript, sanitises scope issues, allows for template strings that span several lines and have variable replacement, adds promises, does away with the need of a lot of anonymous functions to name just a few.

It does, however, change the syntax of JavaScript and by including it into a document or putting it inside a script element in a browser that doesn’t support it, all you do is create a JavaScript error.

There is no progressive enhancement way around this issue, and an opt-in string doesn’t do the job either. In essence, we break backwards compatibility of scripting of the web. This could be not a big issue, if browsers supported ES6, but we’re not quite there yet.

ES6 support and what to do about it

The current support table of ECMAScript6 in browsers, parsers and compilers doesn’t look too encouraging. A lot is red and it is unknown in many cases if the makers of the products we rely on to run JavaScript will take the plunge.

In the case of browsers, the ECMAScript test suite to run your JavaScript engine against is publicly available on GitHub. That also means you can run your current browser against it and see how it fares.

If you want to help with the adoption of ECMAscript in browsers, please contribute to this test suite. This is the one place all of them test against and the better tests we supply, the more reliable our browsers will become.

Ways to use the upcoming ECMAScript right now

The very nature of the changes to ECMAScript make it more or less impossible to use it across browsers and other JavaScript-consuming tools. As a lot of the changes to the language are syntax errors in JavaScript and the parser is not lenient about them, we advance the language by writing erroneous code for legacy environments.

If we consider the use cases of ECMAScript, this is not that much of an issue. Many of the problems solved by the new features are either enterprise problems that only pay high dividends when you build huge projects or features needed by upcoming functionality of browsers (like, for example, promises).

The changes mostly mean that JS gets real OO features, is more memory optimised, and that it becomes a more enticing compile target for developers starting in other languages. In other words, targetted at an audience that is not likely to start writing code from scratch in a text editor, but already coming from a build environment or IDE.

That way we can convert the code to JavaScript in a build process or on the fly. This is nothing shocking these days – after all, we do the same when we convert SASS to CSS or Jade to HTML.

Quite some time ago, new languages like TypeScript got introduced that give us the functionality of ECMAScript6 now. Another tool to use is Babel.js, which even has a live editor that allows you to see what your ES6 code gets converted to in order to run in legacy environments.

Return of the type attribute?

Another way to get around the issue of browsers not supporting ECMAScript and choking on the new syntax could be to use a type attribute. Every time you add a type value to a script element the browser doesn’t understand, it skips it and doesn’t bother the script engine with its content. In the past we used this to create HTML templates and Microsoft had an own JS derivate called JScript. That one gave you much more power to use Windows internals than JavaScript.

One way to ensure that all of us could use the ECMAScript of now and tomorrow safely would be to get browsers to support a type of ‘ES’ or something similar. The question is if that is really worth it seeing the problems ECMAScript is trying to solve.

We’ve moved on in the web development world from embedding scripts and view-source to development toolchains and debugging tools in browsers. If we stick with those, switching from JavaScript to ES6 is much less of an issue than trying to get browsers to either parse or ignore syntactically wrong JavaScript.

Update: Axel Rauschmayer proposes something similar for ECMAScript modules. He proposes a MODULE element that gets a SCRIPT with type of module as a fallback for older browsers.

It doesn’t get boring

In any case, this is a good time to chime in when there are discussions about ECMAScript. We need to ensure that we are using new features when they make sense, not because they sound great. The power of the web is that everybody is invited to write code for it. There is no 100% right or wrong.

Simple things: Storing a list of booleans as a single number

Wednesday, February 25th, 2015

This blog started as a scratch pad of simple solutions to problems I encountered. So why not go back to basics?

Yesterday I was asked by someone if there is a possibility to store the state of a collection of checkboxes in a single value. The simplest way I could think of doing this is by using binary conversion.

Tron binary

You can see the result of my approach in this JSBin:

Storing a list of booleans as a single number

What’s going on here? The state of a checkbox is a Boolean, meaning it is checked or unchecked. This could be true or false, or, as JavaScript is a lenient language, 1 or 0. That’s why we can loop over all the checkboxes and assemble a string of their state that compromises of zeros and ones:

var inputs = document.querySelectorAll('input');
var all = inputs.length;
for (var i = 0; i < all; i++){
  state += inputs[i].checked ? '1' : '0';
}

This results in a string like 1001010101. This could be our value to store, but looks pretty silly and with 50 or more checkboxes becomes very long to store, for example, as a URL parameter string.

That’s why we can use parseInt() to convert this binary number into a decimal one. That’s what the second parameter in parseInt() is for – not only to please Douglas Crockford and JSLint (as it is preset to decimal – 10 – people keep omitting it). The counterpart of parseInt() in this case is toString() and that one also takes an optional parameter that is the radix of the number system you convert from. That way you can convert this state back and forth:

x = parseInt('1001010101',2);
// x -> 579
x.toString(2);
// "1001010101"

Once converted, you turn it back into a string and loop over the values to set the checked state of the checkboxes accordingly.

A small niggle: leading zeroes don’t work

One little problem here is that if the state results in a string with leading zeroes, you get a wrong result back as toString() doesn’t create them (there is no knowing how long the string needs to be, all it does is convert the number).

x = parseInt('00001010101',2);
x.toString(2);
"1010101"

You can avoid this is in two ways: either pad the string by always starting it with a 1 or by reversing the string and looping over the checkboxes in reverse. In the earlier example I did the padding part, in this JSBin you can see the reversing trick:

Storing a list of booleans as a single number (reverse)r

Personally, I like the reversing method better, it just feels cleaner. It does rely a lot on falsy/truthy though as the size of the resulting arrays differs.

Limitation

In any case, this only works when the amount of checkboxes doesn’t change in between the storing and re-storing, but that’s another issue.

As pointed out by Matthias Reuter on Twitter this is also limited to 52 checkboxes, so if you need more, this is not the solution.

Making distributed team meetings work

Tuesday, February 24th, 2015

Being in a distributed team can be tough. Here are a few tricks I learned over the years to make distributed meetings easier.
This is cross-posted on Medium, you can comment there.

Man on phone with 'shut up' on whiteboard behind himPhoto Credit: Tim Caynes

Working as distributed teams is a red flag for a lot of companies. Finding a job that allows you to work remote is becoming a rare opportunity. As someone who worked remote for the last few years I can say though that it is a much better way of working. And it results in more effective and above all, happier, teams.

What it needs is effort by all involved to succeed and often a few simple mistakes can derail the happy train.

The big issue, of course, is time difference. It is also a massive opportunity. A well organised team can cover a product in half the time. To achieve that, you need well organised and honest communication. Any promise you can’t keep means you lost a whole day instead of being able to deliver quicker.

There are many parts to this, but today, I want to talk about meetings with distributed teams. In the worst case, these are phone conferences. In the best case, you have a fancy video conferencing system all people in your team can use.

Quick aside: a lot of people will use this as an opportunity to tell me about their amazing software solutions for this problem. I am sure you can tell me a lot about your multi-media communication system with supercharged servers and affordable rates. Please, don’t. I don’t buy these things and I also have seen far too many fail. Connectivity and travel don’t go too well together. The crystal clear, uninterrupted, distraction-free meetings we see in advertisements are a product of fiction. You might as well add unicorns, at least that would make them fabulous. I’ve seen too many bad connections and terrible surroundings. What they taught me is that planning for failure beats any product you can buy. Hence these tips here.

Synchronous Asynchronicity?


World online information
Meetings are synchronous – you expect all people to be in one place at the same time. Distributed teams work asynchronous. While one part is doing the work, the others are sleeping or having a social life until it is time to switch over.
Thus, if you have a meeting at 10 in the morning California time and you talk to people in Europe you have two kind of people in the virtual room:

  • Those who already had a whole day of work with all the joys and annoyances it brings
  • Those who just got up, far too early for their own liking and got stuck in transit. Either on a packed motorway or involuntarily nestling in the armpit of a total stranger in an overcrowded train

In any case, both are kind of weary and annoyed. Without proper planning, this isn’t an opportunity for knowledge sharing. It is a recipe for disaster as both groups have wildly diverging agendas about this meeting.

  • One group wants to give an update what they did today, hand over and call it a day and
  • The other group wants to know what is important today and get on with it to fight off the cobwebs of commuting

As an expert remote worker you start to diffuse this issue a bit by shifting your daily agenda around. You allow for a few hours of overlap, either by staying longer on the job and starting later in the early afternoon. Or by getting up much earlier and communicating with your colleagues at home before leaving for the office. This works well as long as you don’t have a partner that works normal hours or you live in a country where shops close early.

In any case, you need to find a way to make both groups more efficient in this meeting, so here is the first trick:

Separate the meeting into remote updates and social interactions


sandwichPhoto by Ron Dolette

This may sound weird, but you can’t have both. Having a meeting together in a room in the office is great for the locals:

  • You can brainstorm some ideas in an animated discussion where everyone talks
  • You can cover local happenings (“did you see the game last night? What a ludicrous display”)
  • You can have a chat about what’s bothering you (“damn, the office is cold today”) and
  • talk about location-specific issues and socialise.

This doesn’t work when the topic of discussion is current and about the location you are in. Telling someone eight hours ahead and far away from you that you will enjoy company-provided food right after the event is not helping their morale — on the contrary. It alienates people outside the group even more than they already feel. It is great for the team in the room though. Don’t let one’s group perk become the others reason for jealousy.

By separating your meeting into four parts, you can focus better on giving the right people what they came for and get their updates. Make it a meeting sandwich:

  • Meet in the room, have a quick social chat,
  • Dial in the remote participants, ask them about a quick social update,
  • Have a focused info session with both groups,
  • Let the remote people disconnect and phase out the meeting with another local, social update.

This way everybody uses their time efficiently, feels listened to and not bothered by updates or benefits that don’t apply to them. I have seen this work well in the past. It also resulted in much shorter meetings and we all love those.

Have a clear agenda and turn it into live meeting notes


a clear plan where we are and what's coming
Sending out an agenda before the meeting makes things crystal clear. People know if it is worth to join and can choose not to. Make sure that all the resources you cover in the meeting are linked in the agenda. Make sure that these resources are publicly available to all people in the meeting and not on someone’s internal IP or file share only a few have access to. Having to ask “what is Margaret talking about, where can I find this?” is distracting and frustrating.

During the meeting you can add notes and findings to the agenda items. This has a lot of benefits:

  • People who can not attend the meeting or drop off half way through can look up what happened later.
  • You have an archive of your meetings without having the extra work of publishing meeting notes.
  • People who missed the meeting can scan the meeting results. This is much easier than listening to an hour long recording or watching a video of people in a room talking to a microphone. As beneficial as a video call is when you are all live, it gets tedious and hard to navigate to the items you care about when it is a recording.

Be aware of sound distractions


tis be the time of hammer
In essence what you are dealing with here is a many to one conversation. If you have several people talking to you and you can see them, this is not an issue. If you can’t see them and you don’t even have a spatial recognition where the sound comes from, it all blurs together. That’s why it is important to have one person speak at any time and others to be aware of the fact that any noise they make is distracting. This means:

  • As someone remote, mute your microphone. There is nothing more annoying than the clatter of a keyboard magnified by the microphone just above it
  • As someone in the room with others, lean away from the microphone. Don’t cough into it, don’t shift things around on the table the mic is standing on. Coffee mugs, spoons and pens can be incredibly loud on those.
  • As the speaker, lean into the microphone and speak clearly – always assume there is static and sound loss. A mumbled remark in the back of the room followed by laughter by all could come across to a remote listener as an inside joke or even an insult. No need to risk such misunderstandings.
  • If you switch the speaker, tell them to introduce themselves. This may feel silly in the room, but it helps avoiding confusion on the other side.

Use a chat system as the lifeline of the meeting


Bad skype quality
Video and Audio chat will always go wrong in one way or another. The problem is that when you are presenting the system won’t tell you that. You are not aware that the crystal clear image of yourself with perfect sound is a pixelated mess with a robot voice that makes Daft Punk jealous on the other end.

Having a chat running at the same time covers a few scenarios:

  • People can tell you when something is wrong on their end or when you stopped being comprehensible
  • People can comment without interrupting your audio flow. Many systems switch the presenter as soon as someone speaks – which is unnecessary in this case.
  • People can post resources without having to interrupt you. “In case you missed it, Jessica is talking about http://frolickinghedgehogs.com”

Have a consumable backup for each live update


upload and downloadPhoto by
John Trainor

If you are presenting things in the meeting, send out screencasts or slide decks of what you present beforehand. Far too many times you can not see it as a remote participant when someone shares their screens. Switching from presenter to presenter always ends up in a lot of time wasted waiting for the computer to do the thing we want it to.

For the presenter this allows for better explanations of what is happening. It is distracting when you present and press a button and nothing happens. The remote attendees might also have some lag and get a delayed display. This means you talk about something different than they are currently seeing on their screen.

Plan for travel and meeting as a whole team


group hugPhoto by Joris Louwes

Last, but not least, plan to have visits where you meet as a whole team. Do social things together, give people a chance to get to know one another. Once you connected a real human with the flat, blurry face on the screen, things get much easier. Build up a cadence of this. Meet every quarter or twice a year. This might look expensive at first sight, but pays out in team efficiency. My US colleagues had an “a-hah” moment when they were on a laptop late in the evening waiting for others to stop talking about local things they couldn’t care less about. I felt much more empathy for my colleagues once I had to get up much earlier than I wanted to be in the office in time to meet my European colleagues. Let the team walk in each other’s shoes for a while and future meetings will be much smoother.

Progressive Enhancement is not about JavaScript availability.

Wednesday, February 18th, 2015

I have been telling people for years that in order to create great web experiences and keep your sanity as a developer you should embrace Progressive Enhancement.

escalators are great. when there is an issue, they become stairs and still work

A lot of people do the same, others question the principle and advocate for graceful degradation and yet others don’t want anything to do with people who don’t have the newest browsers, fast connections and great hardware to run them on.

People have been constantly questioning the value of progressive enhancement. That’s good. Lately there have been some excellent thought pieces on this, for example Doug Avery’s “Progressive Enhancement Benefits“.

One thing that keeps cropping up as a knee-jerk reaction to the proposal of progressive enhancement is boiling it down to whether JavaScript is available or not. And that is not progressive enhancement. It is a part of it, but it forgets the basics.

Progressive enhancement is about building robust products and being paranoid about availability. It is about asking “if” a lot. That starts even before you think about your interface.

Having your data in a very portable format and having an API to retrieve parts of it instead of the whole set is a great idea. This allows you to build various interfaces for different use cases and form factors. It also allows you to offer this API to other people so they can come up with solutions and ideas you never thought of yourself. Or you might not, as offering an API means a lot of work and you might disappoint people as Michael Mahemoff debated eloquently the other day.

In any case, this is one level of progressive enhancement. The data is there and it is in a logical structure. That’s a given, that works. Now you can go and enhance the experience and build something on top of it.

This here is a great example: you might read this post here seeing my HTML, CSS and JavaScript interface. Or you might read it in an RSS reader. Or as a cached version in some content aggregator. Fine – you are welcome. I don’t make assumptions as to what your favourite way of reading this is. I enhanced progressively as I publish full articles in my feed. I could publish only a teaser and make you go to my blog and look at my ads instead. I chose to make it easy for you as I want you to read this.

Progressive enhancement in its basic form means not making assumptions but start with the most basic thing and check every step on the way if we are still OK to proceed. This means you never leave anything broken behind. Every step on the way results in something usable – not necessarily enjoyable or following a current “must have” format, but usable. It is checking the depth of a lake befor jumping in head-first.

Markup progressive enhancement

Web technologies and standards have this concept at their very core. Take for example the img element in HTML:

<img src="threelayers.png" 
     alt="Three layers of separation 
          - HTML(structure), 
          CSS(presentation) 
          and JavaScript(behaviour)">

By adding an alt attribute with a sensible description you now know what this image is supposed to tell you. If it can be loaded and displayed, then you get a beautiful experience. If not, browsers display this text. People who can’t see the image at all also get this text explanation. Search engines got something to index. Everybody wins.

<h1>My experience in camp</h1>

This is a heading. It is read out as that to assistive technology, and screen readers for example allow users to jump from heading to heading without having to listen to the text in between. By applying CSS, we can turn this into an image, we can rotate it, we can colour it. If the CSS can not be loaded, we still get a heading and the browser renders the text larger and bold as it has a default style sheet associated with it.

Visual progressive enhancement

CSS has the same model. If the CSS parser encounters something it doesn’t understand, it skips to the next instruction. It doesn’t get stuck, it just moves on. That way progressive enhancement in CSS itself has been around for ages, too:

.fancybutton {
  color: #fff;
  background: #333;
  background: linear-gradient(
    to bottom, #ccc 0%,#333 47%,
    #000 100%
  );
}

If the browser doesn’t understand linear gradients, then the button is white on dark grey text. Sadly, what you are more likely to see in the wild is this:

.fancybutton {
  color: #fff;
  background:  -webkit-gradient(
    linear, 
    left top, left bottom, 
    color-stop(0%,#ccc), 
    color-stop(47%,#333), 
    color-stop(100%,#000));
}

Which, if the browser doesn’t understand webkit gradient, results in a white button with white text. Only because the developer was too lazy to first define a background colour the browser could fall back on. Instead, this code assumes that the user has a webkit browser. This is not progressive enhancement. This is breaking the web. So much so, that other browsers had to consider supporting webkit specific CSS, thus bloating browsers and making the web less standardised as a browser-prefixed, experimental feature becomes a necessity.

Progressive enhancement in redirection and interactivity

<a href="http://here.com/catalog">
See catalog
</a>

This is a link pointing to a data endpoint. It is keyboard accessible, I can click, tap or touch it, I can right-click and choose “save as”, I can bookmark it, I can drag it into an email and send it to a friend. When I touch it with my mouse, the cursor changes indicating that this is an interactive element.

That’s a lot of great stuff I get for free and I know it works. If there is an issue with the endpoint, the browser tells me. It shows me when the resource takes too long to load, it shows me an error when it can’t be found. I can try again.

I can even use JavaScript, apply a handler on that link, choose to override the default behaviour with preventDefault() and show the result in the current page without reloading it.

Should my JavaScript fail to execute for all the reasons that can happen to it (slow connection, blocked resources on a firewall level, adblockers, flaky connection), no biggie: the link stays clickable and the browser redirects to the page. In your backend you probably want to check for a special header you send when you request the content with JS instead of as a redirect from the browser and return different views accordingly.

<a href="javascript:void()">
Catalog</a> or 
<a href="#">Catalog</a> or 
<a onclick="catalog()">Catalog</a>

This offers none of that working model. When JS doesn’t work, you got nothing. You still have a link that looks enticing, the cursor changed, you promised the user something. And you failed at delivering it. It is your fault, your mistake. And a simple one to avoid.

XHTML had to die, HTML5 took its place

When XHTML was the cool thing, the big outcry was that it breaks the web. XHTML meant we delivered HTML as XML. This meant that any HTML syntax error – an unclosed tag, an unencoded ampersand, a non-closed quote meant the end user got an error message instead of the thing they came for. Even worse, they got some cryptic error message instead.

HTML5 parsers are forgiving. Errors happen silently and the browser tries to fix them for you. This was considered necessary to stop the web from breaking. It was considered bad form to punish our users for our mistakes.

If you don’t progressively enhance your solutions, you do the same thing. Any small error will result in an interface that is stuck. It is up to you to include error handling, timeout handling, user interaction like right-click -> open in new tab and many other things.

This is what progressive enhancement protects us and our users from. Instead of creating a solution and hoping things work out, we create solutions that have a safety-belt. Things can not break horribly, because we planned for them.

Why don’t we do that? Because it is more work in the first place. However, this is just intelligent design. You measure twice, and cut once. You plan for a door to be wide enough for a wheelchair and a person. You have a set of stairs to reach the next floor when the lift is broken. Or – even better – you have an escalator, that, when broken, just becomes a set of stairs.

Of course I want us to build beautiful, interactive and exciting experiences. However, a lot of the criticism of progressive enhancement doesn’t take into consideration that nothing stops you from doing that. You just have to think more about the journey to reach the final product. And that means more work for the developer. But it is very important work, and every time I did this, I ended up with a smaller, more robust and more beautiful end product.

By applying progressive enhancement to our product plan we deliver a lot of different products along the way. Each working for a different environment, and yet each being the same code base. Each working for a certain environment without us having to specifically test for it. All by turning our assumptions into an if statement. In the long run, you save that way, as you do not have to maintain various products for different environments.

We continuously sacrifice robustness of our products for developer convenience. We’re not the ones using our products. It doesn’t make sense to save time and effort for us when the final product fails to deliver because of a single error.