Snippets

Using requestIdleCallback

Many sites and apps have a lot of scripts to execute. Your JavaScript often needs to be run as soon as possible, but at the same time you don’t want it to get in the user’s way. If you send analytics data when the user is scrolling the page, or you append elements to the DOM while they happen to be tapping on the button, your web app can become unresponsive, resulting in a poor user experience.

[…]

The good news is that there’s now an API that can help: requestIdleCallback. In the same way that adopting requestAnimationFrame allowed us to schedule animations properly and maximize our chances of hitting 60fps, requestIdleCallback will schedule work when there is free time at the end of a frame, or when the user is inactive. This means that there’s an opportunity to do your work without getting in the user’s way.

[…]

Why should I use requestIdleCallback?

Scheduling non-essential work yourself is very difficult to do. It’s impossible to figure out exactly how much frame time remains because after requestAnimationFrame callbacks execute there are style calculations, layout, paint, and other browser internals that need to run. A home-rolled solution can’t account for any of those. In order to be sure that a user isn’t interacting in some way you would also need to attach listeners to every kind of interaction event (scroll, touch, click), even if you don’t need them for functionality, just so that you can be absolutely sure that the user isn’t interacting. The browser, on the other hand, knows exactly how much time is available at the end of the frame, and if the user is interacting, and so through requestIdleCallback we gain an API that allows us to make use of any spare time in the most efficient way possible.

You Pay (Or Maybe You Don't)

Andy and I have put a lot of work and thought into Every Layout. We want it to be the best resource it can be. Naturally, we would like to be paid for the value we are giving you. However, we know that not everyone can afford the things they’d like to have. We’re trying to address this in two ways:

  1. A large selection of free content, including all of the “rudiment” articles that cover the basics of (our take on) contemporary CSS
  2. An honor system, wherein you can claim to be eligible for the full Every Layout for free

What makes you eligible for (2)? If you are currently out of work, you are a full-time student or under 19 years old, you are trying to get your first job as a web developer or designer, or you are an unpaid volunteer for a charitable organization not involved in proselytism: consider yourself a match. Also, if you are the sole person of your ethnicity, gender, or sexual orientation at your company or in your local developer community: we will gift Every Layout to you. If you have a disability that makes accessing equivalent resources difficult, you can have this resource for free. We are trying to make it as accessible as possible.

[…]

It would be logistically and ethically implausible for us to vet, or otherwise judge, if you deserve to have Every Layout without a charge. If you believe you fit into the criteria above, let us know. That’s the honor part.

Are we suckers? Perhaps, to some. But while you alone decide if you qualify, we decide if you disqualify. That is, if we see you saying or sharing racist, homophobic, transphobic, sexist, or fascist sentiments, or you’re caught engaging in what we consider, in any way, punching down, you get fuck all for free from us.

Designing Accessible Content: Typography, Font Styling, and Structure

There are many design considerations for making your content more accessible to all. Some things to think about and build into your design workflow include:

  • Choose a common font that most users have encountered before.
  • The “serif vs. sans-serif debate” is not a huge deal if you choose a common font family or one that has unique characters.
  • Avoid specialty display fonts or font families that are not unique (ex. letters or numbers that could mirror each other).
  • Your fonts should have a minimum size of 14px (ideally more) and when coded should use relative values.
  • Pay attention to color and contrast! Use tools to check the ratio between the text and background and be wary of gray.
  • Don’t rely on color alone to signify information (ex. “click on the red button”).
  • Clearly define paragraph and letter spacing.
  • Do not let the overall width of the content exceed 80 characters (40 characters for logograms).
  • Avoid paragraph alignment (such as justified) which creates whitespace within the content.

The Fallacies of Distributed Computing (Applied to Front-End Performance)

In the mid-nineties, Laurence Peter Deutsch and colleagues at Sun Microsystems devised a list of what they called The Fallacies of Distributed Computing. These were a list of common assumptions that developers working on distributed systems were prone to making; mistakes that would impact the reliability, security, or resilience of their software. Those fallacies are as follows:

  1. The network is reliable.
  2. Latency is zero.
  3. Bandwidth is infinite.
  4. The network is secure.
  5. Topology doesn’t change.
  6. There is one administrator.
  7. Transport cost is zero.
  8. The network is homogeneous.

Reading over the eight fallacies listed out so plainly, they seem so obvious and clear that you’d struggle to believe that anyone would ever fall foul of them: of course we know bandwidth isn’t infinite! The thing is, these fallacies are obvious, but they don’t exist to teach us anything new; they exist to remind us of the fundamentals. Nor are they intended to explain or describe normal condition; they’re intended to remind us of worst case scenarios. They’re not saying that the network is always unreliable, or that latency is always high, or that bandwidth is always low: they’re saying that, sometimes, one or all of them will be sub-optimal. We should prepare for that.

Yet time and time again I see developers falling into the same old traps—making assumptions or overly-optimistic predictions about the conditions in which their apps will run. Developers frequently tell me things like most of our users are on wifi, or 4G is pretty much everywhere now, or people only ever visit the site from inside the office anyway. Even if this is statistically true—even if your analytics corroborate the claim—planning only for the best leaves you utterly unprepared for the worst. To paraphrase Jeremy, it’s not about how well it works, but how well it fails.

What if images don't arrive? A tale of a badly designed lazy loader

If you’re looking for an example of exactly what not to do in terms of front-end performance, I can’t think of a better one than this - they threw away a lot of the performance optimizations browsers give us for free in a bizarre attempt at improving page loading, which ended up doing the opposite:

I was recently conducting some exploratory work for a potential client when I hit upon a pretty severe flaw in a design decision they’d made: They’d built a responsive image lazyloader in JavaScript which, by design, worked by:

  1. immediately applying display: none; to the <body>;
  2. waiting until the very last of the page’s images had arrived;
  3. once they’d arrived, removing the display: none; and gradually fading the page into visibility.

Not only does this strike me as an unusual design decision—setting out to build a lazyloader and then having it intentionally block rendering—there had been no defensive strategy to answer the question: what if something goes wrong with image delivery?

‘Something wrong’ is exactly what happened. Due to an imperfect combination of:

  1. images being completely unoptimised, plus;
  2. a misconfiguration with their image transformation service leading to double downloads for all images;

…they’d managed to place 27.9MB of images onto the Critical Path. Almost 30MB of previously non-render blocking assets had just been turned into blocking ones on purpose with no escape hatch. Start render time was as high as 27.1s over a cable connection1.

If you’re going to build an image loader that hides the whole page until all images are ready, you must also ask yourself what if the images don’t arrive?