ohmyfetch — A better fetch API

ohmyfetch is a better fetch API. Works on node, browser and workers.

import { $fetch } from 'ohmyfetch'

Import it and use it as you’d use regular fetch. On top of that, you can use some of the extra convenience methods and options — such as easy response parsing, JSON body, Auto Retry, … — this package provides.

ohmyfetch — A better fetch API →

Bringing Bounce and Elastic easing to CSS

In this episode of HTTP 203, Jake and Surma talk about easing in CSS.

You can ease-in, you can ease-out, but CSS doesn’t let you bounce. Jake and Surma chat about a proposal to fix that.

After first going down the rabbit hole of creating a (now-abandoned) proposal to define custom easing functions, Jake went for the non-overcomplicated route: a proposal for a simple syntax in which a CSS author can define an array of (output) values that are mapped to the input range [0..1]

Below is an example with 10 values:

.whatever {
  animation-timing-function: linear(0, 0.09, 0.4, 0.8, 0.83, 0.75, 0.9, 0.95, 0.98, 1 100% 100%);

☝️ Name of the function to be bikeshed, but you get the idea.

If you crank up the number of values, you can eventually create an array of values to represent a bounce movement.

Jake being Jake, he, of course, created a tool to generate a sequence of values.

CSS Custom Properties and !important

💁‍♂️ In this post, I’m taking my own spin on a post originally by Stefan Judis. Doing so, it helped me to better grasp it myself and I was also able to simplify the examples. I hope you will find it helpful too.

What happens when you set !important on a Custom Property? Stefan Judis dug into the subject and posted about it. It all starts with this interesting paragraph from the specification:

Custom properties can contain a trailing !important, but this is automatically removed from the property’s value by the CSS parser […]

As an example, take this snippet:

div {
  --color: red !important;
  background: var(--color);

div {
  background: yellow;

Under normal circumstances, red !important would win from yellow. But since !important gets removed (because it is used in a Custom Property) the snippet basically boils down to this:

div {
  background: red;

div {
  background: yellow;

As both selectors live in the same Origin and have the same Specificity, it’s “Order of Appearance” that determines the winner: the last declaration wins, i.e. background: yellow;


This doesn’t mean that !important is entirely discarded in combination with Custom Properties though. The modifier does get used, but only when trying to determine the actual value for that Custom Property if you have multiple competing declarations.

div {
  --color: red !important;
  background: var(--color);

.class {
  --color: blue;

Although the .class selector is more specific than the div selector, the resulting value for --color will be red. This is because the !important made it win.


When the resulting value gets used in the background property, the !important part will, as per spec, be removed again.

This means that when combining both snippets …

div {
  --color: red !important;
  background: var(--color);

.class {
  --color: blue;

div {
  background: yellow;

… the result will again be yellow because we end up in the same situation as in the first example:

  • For the Custom Properties, red !important will win from blue
  • When used, (the flattened) background: red; will lose from background: yellow; because both selectors live in the same Origin, have the same Specificity, and background: yellow; is declared later.

Here’s a CodePen demo for you to play with:

See the Pen
Custom Properties vs !important
by Bramus (@bramus)
on CodePen.

Learn PWA — A free course to learn how to build Progressive Web Apps

Learn how to build Progressive Web Apps (PWA) with this free course, authored by Maximiliano Firtman, on web.dev.

You’ll learn PWA fundamentals like the Web App Manifest, Service Workers, how to design with an app in mind, what’s different from a classic web app, how to use other tools to test and debug your PWA. After these fundamentals, you’ll learn about integration with the platform and operating system, how to enhance your PWA’s installation and usage experience, and how to offer an offline experience.

Learn PWA →

💡 That’s not the only course you can find on web.dev … Responsive Web Design, Forms, CSS, … it’s all there!

PHP Monitor — Visual PHP Version Switcher that integrates with Laravel Valet

If you’re just getting started with PHP and/or Homebrew, the whole CLI aspect to install and manage PHP versions can become a bit overwhelming. With PHP Monitor by Nico Verbruggen that task becomes easier to handle.

Lightweight, native Mac menu bar app that interacts with Laravel Valet. Helps you manage multiple PHP installations, locate config files and more. Written in Swift.

Installation via Homebrew:

brew tap nicoverbruggen/homebrew-cask
brew install --cask phpmon

As PHPMon is tightly integrated with Laravel Valet, you need to have Valet installed before setting up PHPMon.

💡 Would be nice to see this app evolve into a fully fledged UI to manage Valet, removing the need to define sites via the valet link and the like.

PHP Monitor Source (GitHub) →

Townscaper – Town Generator Game

This summer Oskar Stålberg released his game Townscaper (see video above).

Build quaint island towns with curvy streets, small hamlets, soaring cathedrals, canal networks, or sky cities on stilts. Build the town your dreams, block by block.

No goal. No real gameplay. Just plenty of building and plenty of beauty. That’s it.

Yesterday he surprised us all by releasing a web version.

Looking at it via the DevTools I see that it’s powered by WebGL and Web Assembly.

Townscaper on Steam →
Townscaper on the web →


Checking Oskar’s blog, you can see that he’s been into city builders for quite some time. Take this demo from 6 years ago:

CSS Houdini Blobs

Tim Broddin — ubernerd and also my tech colleague at VRT Creative Lab — released a very nice Houdini Paint Worklet that draws some smooth blobs.

.css-houdini-blobs {
    --num-blobs: 40;

    --seed: 4749;
    --colors: #71a7ee, #7940c1, #f0e891;
    --min-opacity: 0.1;
    --max-opacity: 0.5;
    background: paint(blobs);

Glad to see Tim used css-houdini-circles as a starting point to work from. The blobs themselves are drawn using the blobs NPM package.

CSS Houdini Blob Source (GitHub) →
CSS Houdini Blobs Demo →
blobs NPM Package →

Open Props — Supercharged CSS Variables

Adam Argyle released a new project named Open Props. Similar to the aforementioned Pollen, it’s a library that offers nothing but CSS Custom Properties.

Open source CSS custom properties to help accelerate adaptive and consistent design. Available from a CDN or NPM, as CSS or Javascript.

Once included, you can use the Custom Properties the library provides: colors, margins, paddings, gradients, shadows, font properties, aspect-ratios, … even some basic animations or a conditional border-radius — they’re all there, exposed as Custom Properties!

@import "https://unpkg.com/open-props";

.card {
  border-radius: var(--radius-2);
  padding: var(--size-fluid-3);
  box-shadow: var(--shadow-2);

  &:hover {
    box-shadow: var(--shadow-3);

  @media (--motionOK) {
    animation: var(--animation-fade-in);

💡 That’s CSS Nesting you see there, soon a built-in feature.

I like this very much. Very, very much. Unlike Other Projects™, Open Props nails the “We need Design Tokens” problem by simply making them available in CSS (or via JS if that’s your thing). It doesn’t require you to set up a build pipeline, nor does it enforce you to discard CSS for a re-implementation in another language. You can keep on using what you already know: CSS.

Open Props →


Projects like this make me even more convinced of my statement that Custom Properties are the best thing that happened to CSS over the past 20 years.

Mozilla Specification Positions

Ever wanted to know Mozilla’s stance on a certain specification? They have a one-pager for that:

This page tracks Mozilla’s positions on open Web and Web-related specifications submitted to standards bodies like the IETF, W3C, and Ecma TC39.

Please remember, this isn’t a commitment to implement or participate; it’s just what we think right now. See Firefox Platform Status to find out what we’re implementing.

A pity to see that WebUSB, WebHID, Web Bluetooth, Serial API, etc. also are considered “harmful”. Surely there must be some conditions under which they could be allowed?

Mozilla Specification Positions →

Via @steren

Why don’t we use HTML to author Web Components?

Florian Schulz explores a way to define a web component entirely via markup.

For me, HTML is sort of a component format. So far we’ve used it to define everything that is required for a website to work. But because components are just smaller versions of that, HTML may be a capable format for authoring web components. You don’t need to learn how to write a constructor for a CustomElement and then figure out a way to write your multi-line template as a string or using createElement() all over the place. All you need is your knowledge about HTML as a document format.

The code covered in the technical writeup is all still exploratory, but I do like the fact that it would become as easy as this to load web components:

  <link rel="import" href="custom-search.html">
  <custom-search value="dog food"></custom-search>
  <script src="runtime.js"></script>

(that included runtime.js is a polyfill to load and run the component)

The imported custom-search.html file contains all stuff needed for the web component to work:

<body value placeholder>
  <!-- Component Markup: -->
    <!-- … -->

  <!-- Component Styles: -->
    /* … */

  <!-- Component Logic: -->
    // …

With this approach, these HTML Components can be opened as a standalone page, directly in the browser. See this color picker for example, which is used in this demo.

Self-contained components aye? I like this. A lot. 🙂

Why don’t we use HTML to author web components? →
Import CustomElements from HTML files (Technical Writeup) →


As the author notes: In Custom Elements v0 there was a thing called HTML Imports, but those are deprecated and eventually got removed from Chrome in 2020. Don’t know the specific reasoning, so feel free to enlighten me on that part 🙂

Update 2021.11.30: Thanks to reader Steren for pointing to Mozilla’s position on HTML Imports which might explain the deprecation:

Mozilla anticipated that JavaScript modules would change the landscape here and would rather invest in evolving that, e.g., through HTML Modules.

So instead of HTML Imports they wanted to pursue implementing HTML Modules, similar to how CSS Modules and JSON Modules work.