Journal
Motion One: The Web Animations API for everyone
A new animation library, built on the Web Animations API for the smallest filesize and the fastest performance.
This JavaScript-based animation library—which can be installed via npm—leans on an existing web API to keep its file size low and uses hardware accelerated animations where possible to achieve impressively smooth results.
For fairly basic animations, this might provide an attractive alternative to the heavier Greensock. The Motion docs do however flag the limitation that it can only animate “CSS styles”. They also say “SVG styles work fine”. I hope by this they mean SVG presentation attributes rather than inline CSS on an SVG, although it’s hard to tell. However their examples look promising.
The docs website also contains some really great background information regarding animation performance.
Testing ES modules with Jest
Here are a few troubleshooting tips to enable Jest, the JavaScript testing framework, to be able to work with ES modules without needing Babel in the mix for transpilation. Let’s get going with a basic set-up.
package.json
…,
"scripts": {
"test": "NODE_ENV=test NODE_OPTIONS=--experimental-vm-modules jest"
},
"type": "module",
"devDependencies": {
"jest": "^27.2.2"
}
Note: take note of the crucial "type": "module" part as it’s the least-documented bit and your most likely omission!
After that set-up, you’re free to import and export to your heart’s content.
javascript/sum.js
export const sum = (a, b) => {
return a + b;
}
spec/sum.test.js
import { sum } from "../javascript/sum.js";
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});
Hopefully that’ll save you (and future me) some head-scratching.
(Reference: Jest’s EcmaScript Modules docs page)
Harry Roberts says “Get Your Head Straight”
Harry Roberts (who created ITCSS for organising CSS at scale but these days focuses on performance) has just given a presentation about the importance of getting the content, order and optimisation of the <head> element right, including lots of measurement data to back up his claims. Check out the slides: Get your Head Straight
While some of the information about asset loading best practices is not new, the stuff about ordering of head elements is pretty interesting. I’ll be keeping my eyes out for a video recording of the presentation though, as it’s tricky to piece together his line of argument from the slides alone.
However one really cool thing he’s made available is a bookmarklet for evaluating any website’s <head>:
— ct.css
The accessibility of conditionally revealed questions (on GOV.UK)
Here’s something to keep in mind when designing and developing forms. GOV.UK’s accessibility team found last year that there are some accessibility issues with the “conditional reveal” pattern, i.e. when selecting a particular radio button causes more inputs to be revealed.
The full background story is really interesting but the main headline seems to be: Keep it simple.
- Don’t reveal any more than a single input, otherwise the revealed section should not be in a show-and-hide but rather in its own form in the next step of the process.
- Conditionally show questions only (i.e. another form input such as Email address)—do not show or hide anything that’s not a question.
Doing otherwise causes some users confusion making it difficult for them to complete the form.
See also the Conditionally revealing a related question section on the Radios component on the GDS Design System
W3C Design System
The W3C have just published a new Design System. It was developed by British Digital Agency Studio 24, who are also working (in the open) on the redesign of the W3C website.
My initial impression is that this Design System feels pretty early-stage and work-in-progress. I’m not completely sold on all of the technical details, however it definitely contains a number of emergent best practices and lots of interesting parts.
I particularly liked the very detailed Forms section which assembles lots of good advice from Adam Silver and GOV.UK, and I also found it interesting and useful that they include a Page Templates section rather than just components and layouts.
It’s cool to see an institution like the W3C have a Design System, and I’m looking forward to seeing how it evolves.
I’ve started reading Kindred, by Octavia E. Butler.
Accessibility Testing (on adactio.com)
In this journal entry, Jeremy Keith argues that when it comes to accessibility testing it’s not just about finding issues—it’s about finding the issues at the right time.
Here’s my summary:
- Accessibility Audits performed by experts and real Assistive Technology users are good!
- But try to get the most out of them by having them focus on the things that you can’t easily do yourself.
- We ourselves can handle things like colour contrast. It can be checked at the design stage before a line of code is written.
- Likewise HTML structure such as ensuring accessible form labels, ensuring images have useful
altvalues, using landmarks likemainandnav, heading structure etc. These are not tricky to find and fix ourselves and they have a big accessibility impact. - As well as fixing those issues ourselves we should also put in place new processes, checks and automation if possible to stop them recurring
- As for custom interactive elements (tabs, carousels, navigation, dropdowns): these are specific to our site and complicated/error-prone by nature, so those are the things we should be aiming to have professional Accessibility Audits focus on in order to get best value for money.
Practical front-end performance tips
I’ve been really interested in the subject of Web Performance since I read Steve Souders’ book High Performance Websites back in 2007. Although some of the principles in that book are still relevant, it’s also fair to say that a lot has changed since then so I decided to pull together some current tips. Disclaimer: This is a living document which I’ll expand over time. Also: I’m a performance enthusiast but not an expert. If I have anything wrong, please let me know.
Inlining CSS and or JavaScript
The first thing to know is that both CSS and JavaScript are (by default) render-blocking, meaning that when a browser encounters a standard .css or .js file in the HTML, it waits until that file has finished downloading before rendering anything else.
The second thing to know is that there is a “magic file size” when it comes to HTTP requests. File data is transferred in small chunks of about 14 kb. So if a file is larger than 14 kb, it requires multiple roundtrips.
If you have a lean page and minimal CSS and or JavaScript to the extent that the page in combination with the (minified) CSS/JS content would weigh 14 kb or less after minifying and gzipping, you can achieve better performance by inlining your CSS and or JavaScript into the HTML. This is because there’d be only one request, thereby allowing the browser to get everything it needs to start rendering the page from that single request. So your page is gonna be fast.
If your page including CSS/JS is over 14 kb after minifying and gzipping then you’d be better off not inlining those assets. It’d be better for performance to link to external assets and let them be cached rather than having a bloated HTML file that requires multiple roundtrips and doesn’t get the benefit of static asset caching.
Avoid CSS @import
JavaScript modules in the head
Native JavaScript modules are included on a page using the following:
<script type="module" src="main.js"></script>
Unlike standard <script> elements, module scripts are deferred (non render-blocking) by default. Rather than placing them before the closing </body> tag I place them in the <head> so as to allow the script to be downloaded early and in parallel with the DOM being processed. That way, the JavaScript is already available as soon as the DOM is ready.
Background images
Sometimes developers implement an image as a CSS background image rather than a “content image”, either because they feel it’ll be easier to manipulate that way—a typical example being a responsive hero banner with overlaid text—or simply because it’s decorative rather than meaningful. However it’s worth being aware of how that impacts the way that image loads.
Outgoing requests for images defined in CSS rather than HTML won’t start until the browser has created the Render Tree. The browser must first download and parse the CSS then construct the CSSOM before it knows that “Element X” should be visible and has a background image specified, in order to then decide to download that image. For important images, that might feel too late.
As Harry Roberts explains it’s worth considering whether the need might be served as well or better by a content image, since by comparison that allows the browser to discover and request the image nice and early.
By moving the images to <img> elements… the browser can discover them far sooner—as they become exposed to the browser’s preload scanner—and dispatch their requests before (or in parallel to) CSSOM completion
However if still makes sense to use a background image and performance is important Harry recommends including an accompanying hidden image inline or preloading it in the <head> via link rel=preload.
Preload
From MDN’s preload docs, preload allows:
specifying resources that your page will need very soon, which you want to start loading early in the page lifecycle, before browsers' main rendering machinery kicks in. This ensures they are available earlier and are less likely to block the page's render, improving performance.
The benefits are most clearly seen on large and late-discovered resources. For example:
- Resources that are pointed to from inside CSS, like fonts or images.
- Resources that JavaScript can request such as JSON and imported scripts.
- Larger images and videos.
I’ve recently used the following to assist performance of a large CSS background image:
<link rel="preload" href="bg-illustration.svg" as="image" media="(min-width: 60em)">
Self-host your assets
Using third-party hosting services for fonts or other assets no longer offers the previously-touted benefit of the asset potentially already being in the user’s browser cache. Cross domain caching has been disabled in all major browsers.
You can still take advantage of the benefits of CDNs for reducing network latency, but preferably as part of your own infrastructure.
Miscellaneous
Critical CSS is often a wasted effort due to CSS not being a bottleneck, so is generally not worth doing.
References
- Inlining literally everything on Go Make Things
- MDN’s guide to native JavaScript modules
- How and when browsers download images by Harry Roberts
Doppler: Type scale with dynamic line-height
line-height on the web is a tricky thing, but this tool offers a clever solution.
It’s relatively easy to set a sensible unit-less default ratio for body text (say 1.5), but that tends to need tweaked and tested for headings (where spacious line-height doesn’t quite work; but tight line-height is nice until the heading wraps, etc).
Even for body text it’s a not a one-size-fits-all where a line-height like 1.5 is appropriate for all fonts.
Then you’ve got different devices to consider. For confined spaces, tighter line-height works better. But this can mean you might want one line-height for narrow viewports and another for wide.
Then, factor in vertical rhythm based on your modular type and spacing scales if you really want to blow your mind.
It can quickly get really complicated!
Doppler is an interesting idea and tool that I saw in CSS-Tricks’ newsletter this morning. It lets you apply line-height using calc() based on one em-relative value (for example 1em) and one rem-relative value (for example 0.25rem).
In effect you’ll get something like:
set line-height to the font-size of the current element plus a quarter of the user’s preferred font-size
The examples look pretty promising and seem to work well across different elements. I think I’ll give it a spin.
Big list of http static server one-liners
Lots of different options for running a local web server. Choose from npx, ruby, python and many more.
I also like Ritwick Dey’s Live Server extension for VS Code.