Skip to main content

Journal

SVG Crop

Here’s a handy-looking tool for the SVG editing toolkit.

Remove blank space from around any SVG instantly.

(via @chriscoyier)

I’ve started reading Exhalation by Ted Chiang.

Swipey image grids (on cassie.codes)

A lovely post by Cassie Evans in which she demonstrates that SVG is not just for icons and illustrations. You might also reach for it to create a responsive, animated grid of images.

we have another grid at our disposal. SVG has its own internal coordinate system and it's responsive by design.

There are lots of interesting techniques in here such as:

  • layering an <image> on top of a shape such as a <rect>;
  • using preserveAspectRatio to make the image fully cover and fit the shape when their aspect ratios differ;
  • using <clipPath> as a custom-shaped window to an image (for example a <circle>);
  • giving the <clipPath>’s nested shape a solid fill to hide the <image> to which it’s applied;
  • animating a rectangular <clipPath> applied to an image to give the effect of the image “sliding into view”; and
  • using Greensock to make sequencing multiple animations easy and to ensure they work consistently across browsers.

However I also loved this simple piece of practical advice to help picture the SVG’s viewbox and plot shapes on top:

I usually get a pen and paper out at this point and doodle it out.

Observer APIs in a nutshell

I’ve played with the various HTML5 Observer APIs (IntersectionObserver, ResizeObserver and MutationObserver) a little over the last few years—for example using ResizeObserver in a container query solution for responsive grids. But in all honesty their roles, abilities and differences haven’t yet fully stuck in my brain. So I’ve put together a brief explainer for future reference.

Intersection Observer

Lets you watch for when an element of your choice intersects with a root element of your choice—typically the viewport—and then take action in response.

So you might watch for a div that’s way down the page entering the viewport as a result of the user scrolling, then act upon that by applying a class which animates that div’s opacity from 0 to 1 to make it fade in.

Here’s how it works:

  • Instantiate a new IntersectionObserver object, passing in firstly a callback function and secondly an options array which specifies your root element (usually the viewport, or a specific subsection of it).
  • Call observe on your instance, passing in the element you want to watch. If you have multiple elements to watch, you could call observe repeatedly in a loop through the relevant NodeList.
  • in the callback function add the stuff you want to happen in response to “intersecting” and “no longer intersecting” events.

Mutation Observer

Lets you watch for changes to the attributes or content of DOM elements then take action in response.

You might use this if you have code that you want to run if and when an element changes because of another script.

Here’s how it works:

  • Your typical starting point is that you already have one or more event listeners which modify the DOM in response to an event.
  • Instantiate a new MutationObserver object, passing in a callback function.
  • The callback function will be called every time the DOM is changed.
  • Call observe on your instance, passing in as first argument the element to watch and as second argument a config object specifying what type of changes you’re interested in, for example you might only care about changes to specific attributes.
  • your callback function provides an array of MutationRecord objects—one for each change that has just taken place—which you can loop through and act upon.

Resize Observer

Lets you watch for an element meeting a given size threshold then take action in response.

For example you might add a class of wide to a given container only when it is wider than 60em so that new styles are applied. This is a way of providing container query capability while we wait for that to land in CSS.

Or you might load additional, heavier-weight media in response to a certain width threshold because you feel you can assume a device type that indicates the user is on wifi. Adding functionality rather than applying styles is something we could not achieve with CSS alone.

Given that Container Query support is coming in CSS and that we can usually get by without it in the meantime, I don’t think it’s something I need so desperately that I’ll keep reaching for JavaScript to achieve it. However that’s not the only use for ResizeObserver.

It’s also worth remembering that it’s not all about width: ResizeObserver can also be used to detect and respond to changes to an element’s height. An example might be watching for changes to a chat window’s height—something that’s liable to happen as new messages appear—and then ensuring the focus stays at the bottom, on the latest message.

References

Steve Griffiths has some great video tutorials on these topics.

Design-ish systems (by Ethan Marcotte)

Here’s an interesting new article from Ethan Marcotte, in which he muses on better ways to think about Design Systems based on his recent experience.

Once you’ve identified the root causes, you’ll be in a far, far better place to choose the right things — and, more importantly, to create a system that finally supports your design.

Here’s what I took from it:

We can consider the difference between things, issues and broader goals.

It’s easy to focus on the things (design tokens, choice of design tool, programming language).

But things are just elements of the system; they don’t solve design systems.

Focusing too much or too early on the things leads to a tendency to patch problems.

Whereas discussing the current wider organisational issues we need to address leads to defining broader goals.

This in turn helps us choose and focus on the right things for the right reasons.

Diffchecker - Online diff tool

Diffchecker is a diff tool to compare text differences between two text files.

I had cause to use this free diff tool recently to compare two large minified CSS files and it did the trick better than any others I’ve tried. Thumbs up!

Building a resilient frontend using progressive enhancement (on GOV.UK)

GOV.UK’s guidance on developing using progressive enhancement is pretty great in all departments. It begins with this solid advice:

you should start by making your page work with just HTML, before adding anything else like Cascading Style Sheets (CSS) and JavaScript. This is because HTML is the most resilient layer. If the HTML fails there’s no web page. Should the CSS or JavaScript fail, the HTML will still render correctly.

I particularly like the section where they address the misconception that a resilient baseline is only required in places where the user has explicitly disabled JavaScript and therefore not worth worrying about.

You should not assume the reason for designing a service that works without CSS or JavaScript is because a user chooses to switch these off. There are many situations when extra layers can fail to load or are filtered.

As their subsequent list of scenarios illustrates, a user turning JavaScript off is probably the least likely of a range of reasons why extra layers on top of HTML can fail.

Relatedly, I’ve often found that Everyone has JavaScript, right? serves as a great go-to reference for these sorts of conversations around resilience.

I’ve started reading Recursion by Blake Crouch.

Encapsulated Eleventy/Nunjucks components with macros (by Trys Mudford)

Trys shows us how to use the Nunjucks macro to create encapsulated components. This works out less leaky and more predictable than an include preceded by variables assigned with set.

Trys’s solution allows us to render components like so:

{{ component('button', {
  text: 'Press me'
}) }}

{# Output #}
<button type="button">Press me</button>

Update, 8th Aug 2021: when I tried implementing this I found that it results in errors when attempting to render components anywhere other than on the base template where Trys recommended including the import line. The workaround—as Paul Salaets points out—is to include the import at the top of every page-level template (index.njk, archive.njk etc) that uses the component macro.

In Praise of the Unambiguous Click Menu (on CSS-Tricks)

Mark Root-Wiley explains why navigation menus that appear on click rather than hover are better.

I like the fact that it calls out that:

When you first make this change, it’s true that some visitors might still expect hover menus. They may even say they prefer them if you ask.

But then goes on to provide some rationale (ammunition?) from various big guns on why click menus are better.

From the US Web Design System:

Avoid using hover to expand dropdown lists. Hover is difficult for some users and won’t work on touch screens. Dropdowns should expand on click or with keyboard navigation.

From popular frontend framework Bootstrap:

What it really boils down to is user intent. The purpose of a hover state is to indicate something is clickable (underlined text). The purpose of a click is to actually do something, to take an explicit action. Opening a dropdown is an explicit action and should only happen on click.

(via @jamesmockett)