Snippets

These snippets are my attempt to save and organize various bits of code, best practices, and resources relating to web development and design. They also function as a to do list of sorts, for things I want to implement in my own code, but haven't yet. The concept is inspired by Jeremy Keith's links and CSS-Tricks, among other things. Enjoy.

Setting Height And Width On Images Is Important Again

An example layout with a title and two paragraphs, where the second paragraph has to shift down to make space for an image.

Layout shift after image loads.

tl;dr: browsers now prevent layout shifting when images load using the inline width and height values, provided that you use the correct CSS properties when making images responsive.

Layout shifts are very disrupting to the user, especially if you have already started reading the article and suddenly you are thrown off by a jolt of movement, and you have to find your place again. This also puts extra work on the browser to recalculate the page layout as each image arrives across the internet. On a complex page with a lot of images this can place a considerable load on the device at a time when it’s probably got a lot of better things to deal with!

The traditional way to avoid this was to provide width and height attributes in the <img> markup so even when the browser has just the HTML, it is still able to allocate the appropriate amount of space[:]

Code language: HTML

<h1>Your title</h1>
<p>Introductory paragraph.</p>
<img src="hero_image.jpg" alt=""
   width="400" height="400">
<p>Lorem ipsum dolor sit amet, consectetur…</p>

Then the render [should happen] like below, where the appropriate amount of space is set aside for the image when it arrives, and there is no jarring shift of the text as the image is downloaded:

An example layout mockup with a title, a paragraph, space for an image and then a second paragraph, where the text does not shift when the image loads.

Text should not shift if image dimensions are provided so appropriate space can be allocated.

Even ignoring the annoying impact to the user in content jumping around (which you shouldn’t!), the impact on the CPU [of layout shifts] can also be quite substantial.

[…]

So, once we add the dimensions and [max-width: 100%; height: auto;], we get the best of both worlds, right? No layout shifts, but also the ability to resize images using CSS? Well until very recently you might have been surprised to find out the answer was in fact: no (I was — hence why I decided to write this article).

[…]

This affects any page where we constrain the image size in a responsive manner — i.e. small screen mobile devices. These are likely to be the very users suffering with network constraints and limited processing power that will suffer most from layout shifts! Of course, we ideally should be delivering appropriately sized images for the screen size, but you cannot cover every device size, so often images will need some resizing by the browser, particularly on mobile.

[…]

[I]f the following four conditions are true, then the correct image dimensions could be calculated without needing to wait for the images to download, and so without the need of a content layout shift:

  • height is set on the element in HTML
  • width is set on the element in HTML
  • height (or width) is set in the CSS — including using percentage values like max-width: 100%;
  • width (or height) is set to auto in the CSS.

If any one of these were not set, then the calculation would not be possible, and so would fail and be ignored and have to wait for the image to be downloaded.

[…]

So instead [of waiting for a new CSS property], [browsers] could implement the equivalent logic deep in rendering code rather than exposing it via the user-agent stylesheet, but the effect is the same.

[…]

Firefox went ahead and did this as an experiment and then turned it on by default for Firefox 71. Once that was released, then your site may well have just got faster for free — thanks Mozilla!

[…]

After Firefox’s successful experimentation, Chrome also decided to implement this (again using the layout coded method for now rather than default user-agent stylesheet), and rolled it out by default in Chrome 79. This also took care of the other chromium-based browsers (Edge, Opera and Brave, for example). More recently, in January 2020, Apple added it to their Tech Preview edition of Safari, meaning it should hopefully be coming to the production version of Safari soon, and with that, the last of the major browsers will have implemented this and the web will become better and less jolty for a huge number of sites.

Trix: A rich text editor for everyday writing

A screenshot of the Trix site header with the tagline: "a rich text editor for everyday writing."

Trix is an open-source project from Basecamp, the creators of Ruby on Rails. Millions of people trust their text to Basecamp, and we built Trix to give them the best possible editing experience.

[…]

Different By Design

Most WYSIWYG editors are wrappers around HTML’s contenteditable and execCommand APIs, designed by Microsoft to support live editing of web pages in Internet Explorer 5.5, and eventually reverse-engineered and copied by other browsers.

Because these APIs were never fully specified or documented, and because WYSIWYG HTML editors are enormous in scope, each browser’s implementation has its own set of bugs and quirks, and JavaScript developers are left to resolve the inconsistencies.

[…]

Trix sidesteps these inconsistencies by treating contenteditable as an I/O device: when input makes its way to the editor, Trix converts that input into an editing operation on its internal document model, then re-renders that document back into the editor. This gives Trix complete control over what happens after every keystroke, and avoids the need to use execCommand at all.

Stimulus Handbook: Designing a Resilient User Interface

We should also expect people to have problems accessing our application from time to time. For example, intermittent network connectivity or CDN availability could prevent some or all of our JavaScript from loading.

It’s tempting to write off support for older browsers as not worth the effort, or to dismiss network issues as temporary glitches that resolve themselves after a refresh. But often it’s trivially easy to build features in a way that’s gracefully resilient to these types of problems.

This resilient approach, commonly known as progressive enhancement, is the practice of delivering web interfaces such that the basic functionality is implemented in HTML and CSS, and tiered upgrades to that base experience are layered on top with CSS and JavaScript, progressively, when their underlying technologies are supported by the browser.

Stimulus: A modest JavaScript framework for the HTML you already have

Stimulus is a JavaScript framework with modest ambitions. It doesn’t seek to take over your entire front-end—in fact, it’s not concerned with rendering HTML at all. Instead, it’s designed to augment your HTML with just enough behavior to make it shine. Stimulus pairs beautifully with Turbolinks to provide a complete solution for fast, compelling applications with a minimal amount of effort.

[…]

Sprinkle your HTML with controller, target, and action attributes:

Code language: HTML

<!--HTML from anywhere-->
<div data-controller="hello">
  <input data-target="hello.name" type="text">
 
  <button data-action="click->hello#greet">
    Greet
  </button>
 
  <span data-target="hello.output">
  </span>
</div>

Write a compatible controller and watch Stimulus bring it to life:

Code language: JavaScript

// hello_controller.js
import { Controller } from "stimulus"
 
export default class extends Controller {
  static targets = [ "name", "output" ]
 
  greet() {
    this.outputTarget.textContent =
      `Hello, ${this.nameTarget.value}!`
  }
}

Turbolinks

Turbolinks® makes navigating your web application faster. Get the performance benefits of a single-page application without the added complexity of a client-side JavaScript framework. Use HTML to render your views on the server side and link to pages as usual. When you follow a link, Turbolinks automatically fetches the page, swaps in its <body>, and merges its <head>, all without incurring the cost of a full page load.

  • Optimizes navigation automatically. No need to annotate links or specify which parts of the page should change.
  • No server-side cooperation necessary. Respond with full HTML pages, not partial page fragments or JSON.
  • Respects the web. The Back and Reload buttons work just as you’d expect. Search engine-friendly by design.
  • Supports mobile apps. Adapters for iOS and Android let you build hybrid applications using native navigation controls.