Monday, January 11th, 2016

Without delay

When I wrote about mobile Safari adding support for touch-action: manipulation, I finished with this snarky observation:

Anyway, I’m off to update my CSS even though this latest fix probably won’t land in mobile Safari until, oh ….probably next October.

Historically, Apple have tied mobile Safari updates to iOS version number increments, and they happen about once a year. But this time, it looks like my snark was unfounded:

On Safari for iOS, the 350 ms wait time to detect a second tap has been removed to create a “fast-tap” response. This is enabled for pages that declare a viewport with either width=device-width or user-scalable=no. Authors can also opt in to fast-tap behavior on specific elements by using the CSS touch-action property, using the manipulation value.

That’s from the release notes for Safari 9.1—a point release.

I’m very pleased to have been absolutely wrong with my prediction of Apple’s timing.

Sunday, January 10th, 2016

Small lessons, loosely learned

When Charlotte published her end-of-year report, she outlined her plans for 2016, which included “Document my JavaScript learning journey.”

I want to get into the habit of writing one JavaScript post every week to make sure I keep up with learning it. Even if it’s just a few words about some relevant terminology; it can be as long or short as desired or time allows, as long as it happens.

An excellent plan! If you really want to make sure you’ve understood something, write down an explanation of it. There’s nothing quite like writing to really test your grasp of an idea. Even if nobody else ever reads it, it’s still an extremely valuable exercise for yourself.

Charlotte has already started. Here’s a short post on using JavaScript to pick a random an item at random from an array:

Math.round(Math.random() * (array.length - 1))

It might seem like a small thing, but look what you have to understand:

  • How Math.round works (pretty straightforward—it rounds a floating point number to the nearest whole number).
  • How Math.random works (less straightforward—it gives a random number between zero and one, meaning you have to multiply it to do anything useful with the result).
  • How array.length works (seems straightforward—it gives you the total number of items in an array, but then catches you out when you realise there can never be an index with that total value because the indices are counted from zero …which gives rise to an entire class of programming error).

I really like this approach to learning: document each small thing as you go instead of waiting until all those individual pieces click together. That’s the approach Andy took when he was learning CSS and it led to him writing a book on the subject.

When it comes to problem-solving in general (and JavaScript in particular), I have a similar bias towards single-purpose solutions. Rather than creating a monolithic framework that attempts to solve all possible problems, I prefer a collection of smaller scripts that only do one thing, but do it really well; the UNIX philosophy.

Take, for example, Remy’s bind.js. It does two-way data-binding and nothing else. If you only need one-way data-binding, there’s Simulacra.js, which takes a similar minimalist, hands-off approach.

This approach of breaking large problems down into a collection of smaller problems also came up in a completely unrelated discussion at work recently. I floated the idea of starting a book club at Clearleft. Quite a few people are into the idea, but they’re not sure they could commit the time to reading a book on a deadline. Fair enough. Perhaps we could have the book club on a chapter-by-chapter basis? I don’t think that would work all that well for novels, but it did make me think of something related to Charlotte’s stated goal of learning more JavaScript…

Graham has been raving about the You Don’t Know JS book series by the supersmart Kyle Simpson. I suggested to Charlotte that we read through the books at the rate of one chapter a week. The first book is called Up and Going and our first chapter will be Into Programming, starting this week. Then at the end of the week we’ll get together to compare notes.

I’m hoping that by doing this together, there’s more chance that we’ll actually see it through to completion:

Why can I hit deadlines imposed by others, but not those imposed by myself?

Friday, January 8th, 2016

The Force Awakens

You can listen to an audio version of The Force Awakens.

I’d like to talk about The Force Awakens (I mean, really, how can I not?) so there will be inevitable spoilers. Bail now if you haven’t seen the film.

Star Wars was a big part of my childhood. By extension—and because I’ve never really grown up—Star Wars has always been part of my identity, at least in the shallow sense of what I’d list under “hobbies and interests” on a theoretical form. Still, I could relate to Michael’s feelings in the run-up to the new film’s release:

Despite much evidence to the contrary, I don’t hang too many of my wants and needs on Star Wars or its continuing life as a franchise. I’m the fan-equivalent of a deep history archeologist, not a pundit or an evangelist.

While I’ve always been a big fan of Star Wars: The Films, I’ve never cared much about Star Wars: The Franchise. When my local pub quiz for nerds—The Geekest Link—has a Star Wars night, I enter with a prayer of “please no ‘Expanded Universe’, please no ‘Expanded Universe’.”

When I heard that Lucasfilm had been sold to Disney, I was intrigued—this could get interesting! When I heard that J.J. Abrams would be directing Episode VII, I was pretty happy—I like his work, and he’s a safe pair of hands. But I didn’t want to get too excited. Partly that’s because I’ve been burnt before—although I’m something of a prequels apologist in comparison to the hatred they inspired in most people. Mostly though, it’s because I’m aware that when it comes to something that doesn’t yet exist—whether it’s a Star Wars film, a forthcoming album, or an upcoming project at work—the more hope you place on its shoulders, the more unlikely it is to be able to fulfil those over-inflated expectations.

But as The Force Awakens drew closer and closer, despite my best intentions, I couldn’t help but get excited. Jessica and I watched and re-watched the trailers. The day that tickets went on sale, the website for my cinema of choice crashed, so I picked up the phone and waited in a queue to secure seats for the minute-past-midnight first showing (if you know how much I dislike telephonic communication, you’ll appreciate how unusual that action was for me).

I began to literally count down the days. In the final week, Jessica and I re-watched the Star Wars films in Machete Order, which I can highly recommend. That culminated on the evening of December 16th with a gathering ‘round at Andy’s to eat some food, watch Return Of The Jedi, and then head to the cinema before midnight. By the time I was sitting in my seat surrounded by equally enthusiastic fans, I was positively aquiver with excitement.

When the fanfare blasted and the Star Wars logo appeared, I was grinning from ear to ear. Then I experienced something really wonderful: I had no idea what was going to happen next. Going into this film with no knowledge of plot details or twists was the best possible way to experience it.

I didn’t know what the words of the opening crawl would be. I didn’t know who any of the characters were. I didn’t know what anybody was going to say. I know that sounds like a weird thing to fixate on—after all, didn’t we get that with the prequel films too? Well, not really. Because they were all backstory, there were clearly-delineated constraints on what could and couldn’t happen in those films. But with these new films, anything is possible.

I really, really, really enjoyed watching The Force Awakens. But in order to truly evaluate the film on its own merits, I knew I’d have to see it again in more normal circumstances (and who am I kidding? I didn’t need much of an excuse to see it again).

I’ve seen it three times now. I loved it every time. If anything, the things that slightly bothered me on first seeing the film have diminished with subsequent viewings. It stands up to repeat watching, something that isn’t necessarily true of other J.J. Abrams films—I enjoyed Star Trek Into Darkness when I first saw it, but with every time I see it again, it grows a little weaker.

As I said, there were things that slightly bothered me and I’ll get to those, but my overwhelming feelings about this film are very, very positive. I think the world-building is really good. I think the film itself is superbly crafted, as described in this excellent point-by-point analysis by Chris Dickinson. But above all, what I love the most about The Force Awakens are the characters.

Rey. What can I say? She is quite simply a wonderfully-written character brought to life by an astonishingly good performance. And of course I’m going to join in the chorus of people who are glad that we finally get a lead role for a woman in this galaxy. Granted, Star Wars: The Force Awakens isn’t exactly Mad Max: Fury Road, but still, how great is it that 2015 has given us both Rey and Furiousa?

(You know what it is? It’s a good start.)

Likewise with Finn: great character; great performance. Throw in Kylo Ren, Poe Dameron and even BB8 …I’m sold. I’m invested in their stories now. I want to know what happens next. I want to spend time with them.

But The Force Awakens wasn’t just about new heroes and villains. As audacious as it would be to start from an entirely clean slate, it also needed to tie in to the beloved original films. On the whole, I think this film did a good job of balancing the past and the future.

Paul came along to that midnight viewing; a ticket became available at the last minute. But he was prepared not to enjoy it, or even understand it, given that he’s never really watched Star Wars.

“Actually”, I said, “I’d be really interested to find out what you think of it.”

I’m too close to the source material; I can’t objectively judge whether the new film could stand on its own, as opposed to be being the latest episode in an existing saga.

As it turned out, Paul really enjoyed it. Sure, there was stuff he was aware he was missing out on, but interestingly, there was even more stuff that we were all missing out on: the script is filled with references to events that happened in the intervening decades between the old films and the new. I liked that a lot. It helped solidify this as being simultaneously a brand new chapter and also just one sliver of a larger ongoing narrative.

The Force Awakens is very much a bridging piece between the old and the new. The torch was passed on with dignity, and surprisingly, it was Harrison Ford’s Han Solo that made it a convincing handover.

I say “surprisingly” because remember, we had just watched Return Of The Jedi before The Force Awakens and it is so clear that Harrison Ford really didn’t want to be in that film. I know Han Solo is supposed to be somewhat sarcastic, but it was dialled up to 11 for Jedi, and I’m pretty sure it was a very, shall we say, “naturalistic” performance. But here he is over thirty years later, really breathing life into the character.

Through the stewardship of Harrison Ford, we were lovingly taken from the original films that we know so well into a new story. Han Solo picked up the audience like it was a child that had fallen asleep in the car, and he gently tucked us into our familiar childhood room where we can continue to dream. And then, with a tender brush of his hand across the cheek, he left us.

In many ways, Han Solo in The Force Awakens is Ben Kenobi in Star Wars …but with a much more fleshed-out history and a more interesting personal journey. Now he’s the one saying that the Force is real (and he does it in the very spot where he originally ridiculed Kenobi). It’s as if Scully were to slowly come around to Mulder’s worldview and finally intone “I want to believe.”

The biggest gripe that other people have with The Force Awakens is how much the plot resembles that of the original Star Wars. It’s undeniable. The question is how much that matters, and a result, how much it bothers you. It really bothered Khoi. It somewhat bothered Andy. It didn’t bother me much, but it was definitely an aspect that prevented the film from being a complete triumph. But it’s also one of those issues that diminishes with repeated viewing.

Those bothered by the echoes between Star Wars and The Force Awakens are going to be really pissed off when they find out about World War One and World War Two. “Britain and America fight Germany again? Really!?” (Probably best not to even mention any of the Gulf wars).

I get the feeling though that the people who are bothered by the plot are perhaps overplaying the similarities and underplaying the differences.

So yes, in one sense Rey in The Force Awakens is like Luke in Star Wars—a young person on a desert planet far from the action. But then there are the differences: where Luke was whining about his situation, Rey is mastering hers. And of course there’s the fact that he in 1977 is now she in 2015. “That doesn’t make any difference!” you may cry, and you’d be exactly right: it shouldn’t make any difference …so why has it taken us four decades to get to this?

The casting of Rey and Finn is simultaneously unimportant and monumental. It’s unimportant in that it makes no difference to the story whether Rey is a woman or Finn is black. It’s monumental in that they are the main characters in what everyone knew would be the biggest film of the century so far.

One of the other complaints that people have with The Force Awakens is the unclear political background. Here’s Michael again:

The rebels killed the Emperor and won, but now they’re ‘the resistance’? Why? They’re backed by the republic, so why aren’t they just the armed forces of the republic? The First Order strikes against the republic (looked like Coruscant, but apparently wasn’t). How big is the First Order? Big enough to build Starkiller Base, but what does that mean? Do they control systems? Do they have support inside the republic? Is this like a separatists thing? How long have they been around? How are they funded?

This certainly bugged me. It was the kind of issue that could have been fixed with one explanatory scene. Sure enough, it turns out that such a scene was shot but then cut from the film. Mostly that was to keep the film’s running time down, but I suspect that after the dull talkiness of the prequels, there may also have been some overcompensating course-correction away from anything with even a whiff of politics. Alas, that phobia of trade routes and senators resulted in an unclear backstory. It wasn’t until my third viewing that I realised that Hux’s speech is the closest thing to a blackboard scene for the galactic geopolitics: there’s a proxy war between wannabe extremists looking to set up a caliphate (think ISIS) and a resistance (think the Kurds) being funded by the dominant power (think America) …up until The First Order carry out a 9-11/Pearl Harbour/Vulcan scale attack, leaving the balance of power wide open—the next film could take it in any direction.

One of the most impressive achievements of The Force Awakens is that after seeing it, I didn’t want to think about how it tied back to the original films, as I expected I would want to do. Instead, I was entirely preoccupied with questions of what’s going to happen next.

Everyone is talking about Rey. Where is she from? What is her parentage? The most popular theories are currently:

  1. She is Luke Skywalker’s daughter.
  2. She is Han and Leia’s daughter, the secret sister of Kylo Ren.
  3. She is Ben Kenobi’s granddaughter.

Personally, I’d like it if her parentage were unremarkable. Maybe it’s the socialist in me, but I’ve never liked the idea that the Force is based on eugenics; a genetic form of inherited wealth for the lucky 1%. I prefer to think of the Force as something that could potentially be unlocked by anyone who tries hard enough.

But there are too many hints at Rey’s origins for her parentage to go unexplained. All the signs point to her having some kind of connection to existing bloodlines. Unless…

Lawrence Kasdan has been dropping hints about how odd Episode VIII is going to be, mostly because it has Rian Johnson at the helm. He gave us the terrific Looper. One of the most unsettling aspects of that film was the presence of a child with buried potential for destruction through telekinetic powers. For everyone’s safety, the child is kept far from civilisation.

Okay, I know it’s a stretch but what if Rey is on Jakku for similar reasons? Her parents aren’t Skywalkers or Kenobis, they’re just scared by the destructive episodes they’ve experienced with their Force-sensitive infant. With enormous reluctance—but for the greater good—they deposit her on a faraway world.

No?

Okay, well, if you don’t like that theory, you’re going to hate this one:

What if Rey is the daughter of Luke and Leia?

Eww! I know, I know. But, hey, you can’t say the signs weren’t there all along. And the shame of an incestuous union could be the reason for the child’s secret exile.

It’s preposterous of course. Even in a post-Game Of Thrones landscape, that would be going too far, even for Rian Johnson …or would it?

Now I’ve planted the idea in your head. Sorry about that.

Still, how great is it that we we’re all talking about what’s going to happen next?

Some people have asked me where I think The Force Awakens ranks in comparison to the other Star Wars films, and I wasn’t prepared for the question. I honestly haven’t been thinking about it in the context of the original films. Instead I’ve been thinking about the new characters and the new storyline. As Maz Kanata would say:

The belonging you seek is not behind you, it is ahead.

Sunday, January 3rd, 2016

Year’s end

I usually write a little post at the end of each year, looking back at the previous 365 days. But this time I feel like I’ve already done that. I’ve already written about my year of learning with Charlotte, which describes what I’ve been doing at work for the last twelve months.

Apart from that, there isn’t much more to say about 2015. And that’s a good thing. 2014 was a year tainted by death so I’m not complaining about having just had a year with no momentous events.

The worst that could be said of my 2015 is that Clearleft went through a tough final quarter of the year (some big projects ended up finishing around the same time, which left us floundering for new business—something we should have foreseen), but in the grand scheme of things, that’s not exactly a tragedy.

Mostly when I think back on the year, my memories are pleasant ones. I travelled to interesting places, ate some great food, and spent time with lovely people—Jenn and Sutter’s wedding being a beautiful blend of all three.

So instead of doing a year-end roundup of my own, I’ll just point to some others: James, Alice, Laura, Eliot, Remy, and Brad.

I look forward to reading more posts on their websites in 2016. I hope that you’ll be publishing on your website this year too.

Happy new year!

Japan Hackfarm Anna and Cennydd Rachel at Jon and Hannah's wedding Bletchley Park Beerleft Brad visits Brighton Visiting my mother in Ireland Jessica and Emil Homebrew Website Club Jessica and Dan Jenn and Sutter Me and Brian Clearleft turns 10 Jessica in Austin Clearleft interns Christmas jumpers Christmas in Seattle

Saturday, December 26th, 2015

Delay

Mobile browser vendors have faced a dilemma for quite a while. They’ve got this double-tap gesture that allows users to zoom in on part of a page (particularly handy on non-responsive sites). But that means that every time a user makes a single tap, the browser has to wait for just a moment to see if it’s followed by another tap. “Just a moment” in this case works out to be somewhere between 300 and 350 milliseconds. So every time a user is trying to click a link or press a button on a web page, there’s a slight but noticeable delay.

For a while, mobile browsers tried to “solve” the problem by removing the delay if the viewport size had been set to non-scalable using a meta viewport declaration of user-scalable="no". In other words, the browser was rewarding bad behaviour: sites that deliberately broke accessibility by removing the ability to zoom were the ones that felt snappier than their accessible counterparts.

Fortunately Android changed their default behaviour. They decided to remove the tap delay for any site that had a meta viewport declaration of width=device-width (which is pretty much every responsive website). That still left Apple.

I discussed this a couple of years ago with Ted (my go-to guy on the inside of the infinite loop):

He’d prefer a per-element solution rather than a per-document meta element. An attribute? Or maybe a CSS declaration similar to pointer events?

I thought for a minute, and then I spitballed this idea: what if the 300 millisecond delay only applied to non-focusable elements?

After all, the tap delay is only noticeable when you’re trying to tap on a focusable element: links, buttons, form fields. Double tapping tends to happen on text content: divs, paragraphs, sections.

Well, the Webkit team have announced their solution. As well as following Android’s lead and removing the delay for responsive sites, they’ve also provided a way for authors to declare which elements should have the delay removed using the CSS property touch-action:

Putting touch-action: manipulation; on a clickable element makes WebKit consider touches that begin on the element only for the purposes of panning and pinching to zoom. This means WebKit does not consider double-tap gestures on the element, so single taps are dispatched immediately.

So to get the behaviour I was hoping for—no delay on focusable elements—I can add this line to my CSS:

a, button, input, select, textarea, label, summary {
  touch-action: manipulation;
}

That ought to do it. I suppose I could also throw [tabindex]:not([tabindex="-1"]) into that list of selectors.

It probably goes without saying, but you shouldn’t do:

* { touch-action: manipulation; }

or:

body { touch-action: manipulation; }

That default behaviour of touch-action: auto is still what you want on most elements.

Anyway, I’m off to update my CSS even though this latest fix probably won’t land in mobile Safari until, oh ….probably next October.

Thursday, December 17th, 2015

Pseudo and pseudon’t

I like CSS pseudo-classes. They come in handy for adding little enhancements to interfaces based on interaction.

Take the form-related pseudo-classes, for example: :valid, :invalid, :required, :in-range, and many more.

Let’s say I want to adjust the appearance of an element based on whether it has been filled in correctly. I might have an input element like this:

<input type="email" required>

Then I can write some CSS to put green border on it once it meets the minimum requirements for validity:

input:valid {
  border: 1px solid green;
}

That works, but somewhat annoyingly, the appearance will change while the user is still typing in the field (as soon as the user types an @ symbol, the border goes green). That can be distracting, or downright annoying.

I only want to display the green border when the input is valid and the field is not focused. Luckily for me, those last two words (“not focused”) map nicely to some more pseudo-classes: not and focus:

input:not(:focus):valid {
  border: 1px solid green;
}

If I want to get really fancy, I could display an icon next to form fields that have been filled in. But to do that, I’d need more than a pseudo-class; I’d need a pseudo-element, like :after

input:not(:focus):valid::after {
  content: '✓';
}

…except that won’t work. It turns out that you can’t add generated content to replaced elements like form fields. I’d have to add a regular element into my markup, like this:

<input type="email" required>
<span></span>

So I could style it with:

input:not(:focus):valid + span::after {
  content: '✓';
}

But that feels icky.

Update: See this clever flexbox technique by Hugo Giraudel for a potential solution.

Tuesday, December 15th, 2015

Shadows and smoke

When I wrote about a year of learning with Charlotte, I made an off-hand remark in parentheses:

Hiring Charlotte was an experiment for Clearleft—could we hire someone in a “junior” position, and then devote enough time and resources to bring them up to a “senior” level? (those quotes are air quotes—I find the practice of labelling people or positions “junior” or “senior” to be laughably reductionist; you might as well try to divide the entire web into “apps” and “sites”).

It breaks my heart to see so many of my colleagues prefix their job titles “senior” (not least because it becomes completely meaningless when every single Visual Designer is also a “Senior Visual Designer”).

I remember being at a conference after-party a few years ago chatting to a very talented front-end developer. She wasn’t happy with where she was working. I advised to get a job somewhere else After all, she lived and worked in San Francisco, where her talents are in high demand. But she was hesitant.

“They’ve promised me that in a few more months, my job title would become ‘Senior Developer’”, she said. “Ah, right,” I said, “and what happens then?” “Well”, she said, “I get to have the word ‘senior’ on my resumé.” That was it. No pay rise. No change in responsibilities. Just a word on a piece of paper.

I had always been suspicious of job titles, but that exchange put me over the edge. Job titles can be downright harmful.

Dan recently wrote about the importance of job titles. I love Dan, but I couldn’t disagree with him more in this instance.

He cite two situations where he believes job titles have value:

Your title tells your colleagues how to interact with you.

No. Talking to your colleagues tells your colleagues how to interact you. Job titles attempt to short-cut that. They do a terrible job of it.

What you need to know are the verbs that your colleagues are adept in: designing, developing, thinking, communicating, facilitating …all of that gets squashed down into one reductionist noun like “Copywriter” or “Designer”.

At Clearleft, we’ve recently started kicking off projects with an exercise called “Fuzzy Edges” that Boxman has been refining. In it, we look ahead to all the upcoming project roles (e.g. “Who will lead playbacks and demos?”, “Who will run stakeholder interviews?”, “Who will lead design direction?”). Together, everyone on the project comes to a consensus on who has which roles.

It’s really, really important to clarify these roles at the start of each project, and it’s exactly the kind of thing that can’t be summed up in a job title. In fact, the existence of job titles can lead to harmful assumptions like “Oh, I figured you were leading playbacks and demos!” or “Oh, I assumed they were running stakeholder interviews!”, or worse: “Hey, you can’t lead design direction because that’s not in your job title!”

The role assignments can vary hugely from project to project, which is great. People are varied and multi-faceted. Trying to force the same people into the same roles over and over again would be demoralising and counter-productive. I fear that’s exactly what job titles do—they reinforce barriers.

Here’s the second reason Dan gives for the value of job titles:

Your title tells your clients how to interact with you.

Again, no. Talking to your clients tells your clients how to interact with you.

Dan illustrates his point by recounting a tale of deception, demonstrating that a well-placed lie about someone’s job title can mollify the kind of people who place great stock in job titles. That’s not solving the real problem. Again, while job titles might appear to be shortcuts to a shared understanding, they’re actually more like façades covering up trapdoors.

In recounting the perceived value of job titles, there’s an assumption that the titles were arrived at fairly. If someone’s job title is “Senior Designer” and someone’s job title is “Junior Designer”, then the senior person must be the better, more experienced designer, right?

But that isn’t always the case. And that’s when job titles go from being silly pointless phrases to being downright damaging, causing real harm.

Over on Rands in Repose, there’s a great post called Titles are Toxic. His experience mirrors mine:

Never in my life have I ever stared at a fancy title and immediately understood the person’s value. It took time. I spent time with those people — we debated, we discussed, we disagreed — and only then did I decide: “This guy… he really knows his stuff. I have much to learn.” In Toxic Title Douchebag World, titles are designed to document the value of an individual sans proof. They are designed to create an unnecessary social hierarchy based on ego.

See? There’s no shortcut for talking to people. Job titles are an attempt to cut out one of the most important aspects of humans working together.

The unspoken agreement was that these titles were necessary to map to a dimwitted external reality where someone would look at a business card and apply an immediate judgement on ability based on title. It’s absurd when you think about it – the fact that I’d hand you a business card that read “VP” and you’d leap to the immediate assumption: “Since his title is VP, he must be important. I should be talking to him”. I understand this is how a lot of the world works, but it’s precisely this type of reasoning that makes titles toxic.

So it’s not even that I think that job titles are bad at what they’re trying to do …I think that what they’re trying to do is bad.

Friday, December 11th, 2015

Where to start?

A lot of the talks at this year’s Chrome Dev Summit were about progressive web apps. This makes me happy. But I think the focus is perhaps a bit too much on the “app” part on not enough on “progressive”.

What I mean is that there’s an inevitable tendency to focus on technologies—Service Workers, HTTPS, manifest files—and not so much on the approach. That’s understandable. The technologies are concrete, demonstrable things, whereas approaches, mindsets, and processes are far more nebulous in comparison.

Still, I think that the most important facet of building a robust, resilient website is how you approach building it rather than what you build it with.

Many of the progressive app demos use server-side and client-side rendering, which is great …but that aspect tends to get glossed over:

Browsers without service worker support should always be served a fall-back experience. In our demo, we fall back to basic static server-side rendering, but this is only one of many options.

I think it’s vital to not think in terms of older browsers “falling back” but to think in terms of newer browsers getting a turbo-boost. That may sound like a nit-picky semantic subtlety, but it’s actually a radical difference in mindset.

Many of the arguments I’ve heard against progressive enhancement—like Tom’s presentation at Responsive Field Day—talk about the burdensome overhead of having to bolt on functionality for older or less-capable browsers (even Jake has done this). But the whole point of progressive enhancement is that you start with the simplest possible functionality for the greatest number of users. If anything gets bolted on, it’s the more advanced functionality for the newer or more capable browsers.

So if your conception of progressive enhancement is that it’s an added extra, I think you really need to turn that thinking around. And that’s hard. It’s hard because you need to rewire some well-engrained pathways.

There is some precedence for this though. It was really, really hard to convince people to stop using tables for layout and starting using CSS instead. That was a tall order—completely change the way you approach building on the web. But eventually we got there.

When Ethan came out with Responsive Web Design, it was an equally difficult pill to swallow, not because of the technologies involved—media queries, percentages, etc.—but because of the change in thinking that was required. But eventually we got there.

These kinds of fundamental changes are inevitably painful …at first. After years of building websites using tables for layout, creating your first CSS-based layout was demoralisingly difficult. But the second time was a bit easier. And the third time, easier still. Until eventually it just became normal.

Likewise with responsive design. After years of building fixed-width websites, trying to build in a fluid, flexible way was frustratingly hard. But the second time wasn’t quite as hard. And the third time …well, eventually it just became normal.

So if you’re used to thinking of the all-singing, all-dancing version of your site as the starting point, it’s going to be really, really hard to instead start by building the most basic, accessible version first and then work up to the all-singing, all-dancing version …at first. But eventually it will just become normal.

For now, though, it’s going to take work.

The recent redesign of Google+ is true case study in building a performant, responsive, progressive site:

With server-side rendering we make sure that the user can begin reading as soon as the HTML is loaded, and no JavaScript needs to run in order to update the contents of the page. Once the page is loaded and the user clicks on a link, we do not want to perform a full round-trip to render everything again. This is where client-side rendering becomes important — we just need to fetch the data and the templates, and render the new page on the client. This involves lots of tradeoffs; so we used a framework that makes server-side and client-side rendering easy without the downside of having to implement everything twice — on the server and on the client.

This took work. Had they chosen to rely on client-side rendering alone, they could have built something quicker. But I think it was worth laying that solid foundation. And the next time they need to build something this way, it’s going to be less work. Eventually it just becomes normal.

But it all starts with thinking of the server-side rendering as the default. Server-side rendering is not a fallback; client-side rendering is an enhancement.

That’s exactly the kind of mindset that enables Jack Franklin to build robust, resilient websites:

Now we’ll build the React application entirely on the server, before adding the client-side JavaScript right at the end.

I had a chance to chat briefly with Jack at the Edge conference in London and I congratulated him on the launch of a Go Cardless site that used exactly this technique. He told me that the decision to flip the switch and make it act as a single page app came right at the end of the project. Server-side rendering was the default; client-side rendering was added later.

The key to building modern, resilient, progressive sites doesn’t lie in browser technologies or frameworks; it lies in how we think about the task at hand; how we approach building from the ground up rather than the top down. Changing the way we fundamentally think about building for the web is inevitably going to be challenging …at first. But it will also be immensely rewarding.

Wednesday, December 2nd, 2015

A year of learning

An anniversary occurred last week that I don’t want to let pass by unremarked. On November 24th of last year, I made this note:

Welcoming @LotteJackson on her first day at @Clearleft.

Charlotte’s start at Clearleft didn’t just mark a new chapter for her—it also marked a big change for me. I’ve spent the last year being Charlotte’s mentor. I had no idea what I was doing.

Lyza wrote a post about mentorship a while back that really resonated with me:

I had no idea what I was doing. But I was going to do it anyway.

Hiring Charlotte coincided with me going through one of those periods when I ask myself, “Just what is it that I do anyway?” (actually, that’s pretty much a permanent state of being but sometimes it weighs heavier than others).

Let me back up a bit and explain how Charlotte ended up at Clearleft in the first place.

Clearleft has always been a small agency, deliberately so. Over the course of ten years, we might hire one, maybe two people a year. Because of that small size, anyone joining the company had to be able to hit the ground running. To put it into jobspeak, we could only hire “senior” level people—we just didn’t have the resources to devote to training up anyone less experienced.

That worked pretty well for a while but as the numbers at Clearleft began to creep into the upper teens, it became clear that it wasn’t a sustainable hiring policy—most of the “senior” people are already quite happily employed. So we began to consider the possibility of taking on somebody in a “junior” role. But we knew we could only do that if it were somebody else’s role to train them. Like I said, this was ‘round about the time I was questioning exactly what my role was anyway, so I felt ready to give it a shot.

Hiring Charlotte was an experiment for Clearleft—could we hire someone in a “junior” position, and then devote enough time and resources to bring them up to a “senior” level? (those quotes are air quotes—I find the practice of labelling people or positions “junior” or “senior” to be laughably reductionist; you might as well try to divide the entire web into “apps” and “sites”).

Well, it might only be one data point, but this experiment was a resounding success. Charlotte is a fantastic front-end developer.

Now I wish I could take credit for that, but I can’t. I’ve done my best to support, encourage, and teach Charlotte but none of that would matter if it weren’t for Charlotte’s spirit: she’s eager to learn, eager to improve, and crucially, eager to understand.

Christian wrote something a while back that stuck in my mind. He talked about the Full Stack Overflow Developer:

Full Stack Overflow developers work almost entirely by copying and pasting code from Stack Overflow instead of understanding what they are doing. Instead of researching a topic, they go there first to ask a question hoping people will just give them the result.

When we were hiring for the junior developer role that Charlotte ended up filling, I knew exactly what I didn’t want and Christian described it perfectly.

Conversely, I wasn’t looking for someone with plenty of knowledge—after all, knowledge was one of the things that I could perhaps pass on (stop sniggering). As Philip Walton puts it:

The longer I work on the web, the more I realize that what separates the good people from the really good people isn’t what they know; it’s how they think. Obviously knowledge is important—critical in some cases—but in a field that changes so quickly, how you go about acquiring that knowledge is always going to be more important (at least in the long term) than what you know at any given time. And perhaps most important of all: how you use that knowledge to solve everyday problems.

What I was looking for was a willingness—nay, an eagerness—to learn. That’s what I got with Charlotte. She isn’t content to copy and paste a solution; she wants to know why something works.

So a lot of my work for the past year has been providing a framework for Charlotte to learn within. It’s been less of me teaching her, and more of me pointing her in the right direction to teach herself.

There has been some traditional instruction along the way: code reviews, pair programming, and all of that stuff, but often the best way for Charlotte to learn is for me to get out of the way. Still, I’m always on hand to try to answer any questions or point her in the direction of a solution. I think sometimes Charlotte might regret asking me things, like a simple question about the box model.

I’ve really enjoyed those moments of teaching. I haven’t always been good at it. Sometimes, especially at the beginning, I’d lose patience. When that happened, I’d basically be an asshole. Then I’d realise I was being an asshole, apologise, and try not to do it again. Over time, I think I got better. I hope that those bursts of assholery are gone for good.

Now that Charlotte has graduated into a fully-fledged front-end developer, it’s time for me to ask myself once again, “Just what is it that I do anyway?”

But at least now I have some more understanding about what I like to do. I like to share. I like to teach.

I can very much relate to Chen Hui Jing’s feelings:

I suppose for some developers, the job is a just a means to earn a paycheck. But I truly hope that most of us are in it because this is what we love to do. And that we can raise awareness amongst developers who are earlier in their journey than ourselves on the importance of best practices. Together, we can all contribute to building a better web.

I’m writing this to mark a rewarding year of teaching and learning. Now I need to figure out how to take the best parts of that journey and apply it to the ongoing front-end development work at Clearleft with Mark, Graham, and now, Charlotte.

I have no idea what I’m doing. But I’m going to do it anyway.

Sunday, November 29th, 2015

Cache-limiting in Service Workers …again

Okay, so remember when I was talking about cache-limiting in Service Workers?

It wasn’t quite working:

The cache-limited seems to be working for pages. But for some reason the images cache has blown past its allotted maximum of 20 (you can see the items in the caches under the “Resources” tab in Chrome under “Cache Storage”).

This is almost certainly because I’m doing something wrong or have completely misunderstood how the caching works.

Sure enough, I was doing something wrong. Thanks to Brandon Rozek and Jonathon Lopes for talking me through the problem.

In a nutshell, I’m mixing up synchronous instructions (like “delete the first item from a cache”) with asynchronous events (pretty much anything to do with fetching and caching with Service Workers).

Instead of trying to clean up a cache at the same time as I’m adding a new item to it, it’s better for me to have clean-up function to run at a different time. So I’ve written that function:

var trimCache = function (cacheName, maxItems) {
    caches.open(cacheName)
        .then(function (cache) {
            cache.keys()
                .then(function (keys) {
                    if (keys.length > maxItems) {
                        cache.delete(keys[0])
                            .then(trimCache(cacheName, maxItems));
                    }
                });
        });
};

But now the question is …when should I run this function? What’s a good event to trigger a clean-up? I don’t think the activate event is going to work. I probably want something like background sync but I don’t think that’s quite ready for primetime yet.

In the meantime, if you can think of a good way of doing a periodic clean-up like this, please let me know.

Anyone? Anyone? Bueller?

In other Service Worker news, I’ve added a basic Service Worker to The Session. It caches static caches—CSS and JavaScript—and keeps another cache of site section index pages topped up. If the network connection drops (or the server goes down), there’s an offline page that gives a few basic options. Nothing too advanced, but better than nothing.

Update: Brandon has been tackling this problem and it looks like he’s found the solution: use the page load event to fire a postMessage payload to the active Service Worker:

window.addEventListener('load', function() {
    if (navigator.serviceWorker.controller) {
        navigator.serviceWorker.controller.postMessage({'command': 'trimCaches'});
    }
});

Then inside the Service Worker, I can listen for that message event and run my cache-trimming function:

self.addEventListener('message', function(event) {
    if (event.data.command == 'trimCaches') {
        trimCache(pagesCacheName, 35);
        trimCache(imagesCacheName, 20);
    }
});

So what happens is you visit a page, and the caching happens as usual. But then, once the page and all its assets are loaded, a message is fired off and the caches get trimmed.

I’ve updated my Service Worker and it looks like it’s working a treat.