Christian Heilmann

Author Archive

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.

Flipboard and the “mobile web” dream…

Sunday, February 15th, 2015

According to the luminaries of the web design world, the “mobile web” doesn’t exist. Stephen Hay said it, Smashing Magazine said so and Jeremy Keith amongst many others.

Except, it does. Not as a technical reality, but as a dream of marketing and overly excited managers who believe in magical powers of their engineers. And it is nothing new. We’ve been there before, and we probably will get there again. Every few years a new form factor or technology comes out that promises a web that is catering perfectly to a very niche need whilst being open and available to all. Or – in other words – water that is almost, but not totally wet.

Flipboard’s magical journey at 60 fps

Last week Flipboard engineering released the Kraken with their “60 fps on the mobile web” post, explaining how they managed to give the new “web version” of Flipboard a buttery smooth 60 frames per second on mobile by forfeiting the DOM and rendering the whole thing in Canvas. The general outrage was that it was read as a call to give up on the DOM and use react.js and Canvas instead.

Kid needs light-up shoes to run faster - we need canvas to have a performing web app

Not surprisingly, this sparked a lot of discussion and annoyance toward them. But let’s step back a bit: first of all, it is a good thing when engineering teams publish their findings and tell us why they made some decisions. It can be a great learning resource and is a courageous thing to do. In a world where people spend most of their time dismembering technical posts on hacker news putting yourself out there means you also need to deal with a lot of polarised feedback. You need to learn fast how to deal with trolls and people using these systems to grandstand. So, thanks are in order – thank you, Flipboard. The post is detailed, it explains what they tried to do and how they achieved it.

The usefulness of such a resource starts getting questionable when hype kicks in and people take it as gospel. Flipboard did not claim that what they do is the perfect way to achieve happiness on mobile. Instead they are very open about their intentions:

In the pursuit of 60fps we sometimes resort to extreme measures. Flipboard for mobile web is a case study in pushing the browser to its limits. While this approach may not be suitable for all applications, for us it’s enabled a level of interaction and performance that rivals native apps.

Right now, mobile is still hot. HTML5 is still hot. A company pushing the boundaries of both is hot. That’s why it is good value for a tech company to write articles like that. And I am 100% sure the Flipboard engineers have the heart in the right place and rightfully are proud of what they have achieved.

Solving the right problem with the wrong approach

That said, the title is terrible as it promises a simple answer to a huge problem. Or, on reflection, not a problem, but a massive misunderstanding.

What this post told me most of all is that it isn’t solving an issue of the web. It is about simulating a native interface for a mobile touch device at 60 fps using web technologies. It’s aim is to run smoothly on the currently hot device that the most affluent people use – let’s say the iPhone 6. They are not beating around the bush about this at all:

Now we’re coming full circle and bringing Flipboard to the web. Much of what we do at Flipboard has value independent of what device it’s consumed on: curating the best stories from all the topics, sources, and people that you care about most. Bringing our service to the web was always a logical extension.

There’s a massive flaw in this: it tries to bring value independent of what device it is consumed on and then it applies assumptions and concepts that are only beneficial to a mobile, touch-enabled device.

This is a porting exercise. This is bringing something to the web. It is not creating a web product. That would be reaching as many people as possible, and making your content available independent of hardware, ability and environment. You can not “go to web”. The web is not another form factor when your starting point is a very restricted environment. That’s how we got text-only versions of Flash movies and “accessible versions” of DHTML monstrosities. Using web technology means you start with the assumption that you have no control over the way your content is consumed. And that’s as far removed as it can from what Flipboard said:

Flipboard launched during the dawn of the smartphone and tablet as a mobile-first experience, allowing us to rethink content layout principles from the web for a more elegant user experience on a variety of touchscreen form factors.

And this is why calling this a web experience is ill-advised from the get-go. As Faruk Ates put it:

…what Flipboard unleashed onto the world a “Web” version is akin to calling a collection of tires, AA batteries and spare car parts a Tesla.

This is not about the technical implementation. The flaw is in the idea of turning a native app that was specifially designed for a certain form factor into a “web version”. The journey explained is full of assumptions.

The first one is the big 60. All our web technology efforts need to match the 60 fps threshold or they are useless, right? Well, looking at my Nexus 5 device with Android Lollipop and anything I could do to be state-of-the-art I can safely say that not a single app works consistently smoothly at 60 fps or doesn’t stutter from time to time. So, I guess, I have no apps.

Of course, we need goals to aspire to and some things to measure against. But defining something like 60fps as a baseline is pretty naive considering the fragmentation of hardware and the amount of abstraction layers an HTML5 app has to go through. Maybe considering less greedy interaction models might be a way forward?

Which brings me to the second assumption: endless scrolling is what the web is about. And from there, the article tries to make that work. True, a lot of solutions have endless scrolling. Also true, many a time that is more annoying than a pagination would have been.

What Flipboard did here is to build a native-feel solution in an environment that has no native paradigms. There are no form-factor standards on the web. They change constantly. The parallax scrolling page today is the multi-level DHTML drop-down of tomorrow.

Stretching the canvas

It is a daring and seemingly clever solution to go for canvas to reach good performance in an endless scrolling interface. But that’s all it is – a currently clever solution with a very short shelf-life. As Rachel Nabors put it:

Re: recreating the DOM in canvas and accessibility: we will look back on this as a hack. Browsers will catch up, will render the DOM faster.

When working on Firefox OS and low-end devices, the main issue just a few months ago was that canvas was too slow and people used the DOM instead and complained that it is the wrong API for games. The push was towards canvas to become hardware accelerated or – even better – mobile browsers to support WebGL. Now we have this and many a DOM solution using all kind of 3D transform tricks in CSS to force hardware accelerated layers look silly. Much like this might look silly very soon.

The honest approach to this would be to give the article the title “How we created endless scrolling at 60 fps on high-end mobile devices by replacing the DOM with Canvas”. But that’s not as quotable and it doesn’t make you sound like a trailblazer solving a “real and very common” problem.

Access denied

Flipboard already admits that in terms of accessibility, this is a horrible solution. Screenreader availability aside, my warning bells went off when I saw elements with not only fixed positions on the screen but also fixed dimensions. And when you use a tool that supports text but means you need to calculate line breaks, I’d get a queasy feeling in my stomach. There goes resizing the font. There goes copying and pasting. There goes translating a text. All things the web is great at. And it is nothing new.

Every single time we replaced text with graphics to gain more control we had to re-invent these basic features of a text-based web. Remember image replacement techniques of headlines before we had web fonts? Remember how Flash had to bend over backwards to seed the browser history and to make text highlight-able? Remember how it was impossible on mobile devices to copy and paste at all?

When reading the section of the post about accessibility I get flashbacks to horrible times:

This area needs further exploration. Using fallback content (the canvas DOM sub-tree) should allow screen readers such as VoiceOver to interact with the content. We’ve seen mixed results with the devices we’ve tested. Additionally there is a standard for focus management that is not supported by browsers yet.

One approach that was raised by Bespin in 2009 is to keep a parallel DOM in sync with the elements rendered in canvas. We are continuing to investigate the right approach to accessibility.

Wait a second. Re-read this, please, and tell me if I am crazy when I think this sounds like a lot of duct-tape around a leaking faucet.

We have a perfectly accessible way of achieving all of this: we call it HTML and we have the DOM and the accessibility API. That way we’d have a perfectly working web site that gets found, indexed, is accessible to a lot of people. We can then convert into a fast performing canvas solution on mobile devices that are touch-enabled. We can test for that – web technology is good at that. Think about it: a data source that comes with lots of accessibility benefits and already has an API to read it in part? Sign me up.

Instead we consider adding a lot of HTML content inside the canvas element as a fallback and hope browsers and assistive technology will do something with that.

Content inside canvas becomes interesting when canvas isn’t supported. Today, that’s an almost non-existent use case. Browsers support canvas. It is a blank, stateless placeholder in the page that we paint on and wipe. It is an etch-a-sketch in the page. It isn’t even vector based – it is a dumb collection of pixels. That’s why canvas is fast – the Flipboard article does a good job explaining that.

Canvas is to HTML5 what DIV and SPAN are to HTML4 - it has no semantic meaning. It is a placeholder for generated, visual content. Not text, not interactive elements. When canvas came to be, the first comments were that it is the new applet. And that is still quite a sensible way of describing it from a markup/semantic meaning angle. It is as much a black box in the page as Flash was to the rest of the markup.

Replace the DOM, but not its virtues

The problem with Flipboard’s solution to the mobile performance issue is that it wants to use canvas because of its stateless and high-performance nature and get all the benefits of HTML and the DOM at the same time. This is asking too much.

We could, however, get quite a long way by creating our canvas content from HTML that is in the document. And that is what it means to build a web product – you build a sensible HTML solution first, and then use CSS and JavaScript to enhance it. That way you don’t need to worry about covering the basics after you fine-tuned the final product. That approach will always result in disappointing fallbacks that are hardly ever maintained.

The “mobile web” thing

The whole goal of this exercise was to match native performance by using web technology and applying ideas of native environments. And this is a thing we should be aware of. The mobile web.

The issue is that according to this post and many others of the same ilk, the mobile web exists. The mobile web is not a technical thing – it is a misconception and one that is hard to match. Companies nowadays start with a native experience. This is where the short-term gain is. This is where the short-term high user numbers lie. This is the beautiful technology – the shiny devices, the backing from OS vendors and the exciting interaction models that come with the OS. It feels good, it feels that there is something to work with.

Then these people hear about the benefits of web technologies: cross-platform support, lower cost of engineering as you don’t need to pay experts of red-hot new technologies, re-use across different form factors and so on. A lot of times this happens when the honeymoon period of the native solution is over and there is new growth to be unearthed.

Then, they want both. Hence, “the mobile web”.

We have two issues to battle with this: a technical problem and an image problem.

Let’s talk technical first: matching the performance of a native app with a web app is a game the web can currently not win. At least not if all you count as performance is its fps speed and how well it integrates with the OS. The reason is that the cards are stacked against us. Unless the browser becomes the most important thing in a mobile OS, we will always have a hacky experience.

To the OS vendor, the browser is a necessary thing to offer – another app much like the calculator or the phone app. From a marketing and monetary point of view, having people build exclusively for your platform with your tools and in your languages is a win-win. You have a captive audience and you can show their numbers in huge figures during your keynotes to your stakeholders. Making the browser amazing means you have to share.

Add to this the ridiculous browser fragmentation and the amount of zombie browsers on older systems that will never get an update again and you will find that matching the newest and coolest of the native offering is really hard.

The image problem is that the web seems stale. Our market thrives on hype and short term gains. All our messaging about the web is praising its longevity. What you do now means you will benefit in years to come, even if it means some extra work. Your products will be easy to maintain for years to come. Future technology will already support what you do now and it will be easy to extend if you use progressive enhancement. This is our messaging, and it is great messaging.

Except when all you care about is the next month’s user and download numbers and how many people posted selfies and sent stickers to each other that you sold them. Then this message is just noise and sounds like arrogant “in my days” speeches.

If we love the web and want it to work out, we need to pick our battles. And the real battle lies with operating systems not having a browser we can rely on. And with lack of support of very basic features we need to give an app experience across browsers and platforms. And with a lack of standards that really get to fruition and are implemented instead of being replaced by a library that is open source, but never leaves beta.

The mobile web is real – and it isn’t. It is a dream of people who don’t get the nature of the web trying to harvest its benefits. And right now, these people get all the VC money and get the tech press excited as they promise something new. The hype as it is now is not sustainable. It killed these people once in the dotcom boom and will again – very soon.

We can stomp our foot about that and get angry and we can repeat tiring old messages. Or we can bide our time and fix what is broken and keeps us from performing the way we want to. Let those who need the quick short-term win pretend they found the solution. Our time can be used differently. The amount of devices, form factors and user needs is not decreasing any time soon. The web can cover all of them. Let’s make that happen once the fever dream of the one true app form factor is over. Much like there is not one mode of transport to cover all needs, there is no such thing as a perfect app or interaction model.