A modern CSS reset

Andy Bell:

In this modern era of web development, we don’t really need a heavy-handed reset, or even a reset at all, because CSS browser compatibility issues are much less likely than they were in the old IE 6 days. That era was when resets such as normalize.css came about and saved us all heaps of hell. Those days are gone now and we can trust our browsers to behave more, so I think resets like that are probably mostly redundant.

I still like to reset stuff, so I’ve been slowly and continually tinkering with a reset myself over the years in an obsessive code golf manner.

Here’s the result:

/* Box sizing rules */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Remove default padding */
ul[class],
ol[class] {
  padding: 0;
}

/* Remove default margin */
body,
h1,
h2,
h3,
h4,
p,
ul[class],
ol[class],
li,
figure,
figcaption,
blockquote,
dl,
dd {
  margin: 0;
}

/* Set core body defaults */
body {
  min-height: 100vh;
  scroll-behavior: smooth;
  text-rendering: optimizeSpeed;
  line-height: 1.5;
}

/* Remove list styles on ul, ol elements with a class attribute */
ul[class],
ol[class] {
  list-style: none;
}

/* A elements that don't have a class get default styles */
a:not([class]) {
  text-decoration-skip-ink: auto;
}

/* Make images easier to work with */
img {
  max-width: 100%;
  display: block;
}

/* Natural flow and rhythm in articles by default */
article > * + * {
  margin-top: 1em;
}

/* Inherit fonts for inputs and buttons */
input,
button,
textarea,
select {
  font: inherit;
}

/* Remove all animations and transitions for people that prefer not to see them */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

Clever usage of the [class] selector to selectively apply CSS rulesets!

A Modern CSS Reset →

Prevent Apple’s “double key press” on the butterfly keyboard with Unshaky

If you’re having this “double key press” issue, Unshaky is a software solution that will help you get by.

Unshaky tries to address an issue on the butterfly keyboard (Macbook, Macbook Air 2018 & MacBook Pro 2016 and later): Double Key Press. Unshaky might save your keyboard by dismissing such “second key hits” (any key presses that occur no later than x milliseconds after the previous effective one).

Installable through Brew Cask, or per direct download from the site:

brew cask install unshaky

Won’t fix the fact that the keyboard doesn’t sit well on the fingers …

Unshaky: A software attempt to address the “double key press” issue on Apple’s butterfly keyboard →

🚨 As Apple has acknowledged these issues, don’t forget to apply for Apple’s Keyboard Service Program for MacBook and MacBook Pro to get a new keyboard, free of charge.

Optimizing images for the web – an in-depth guide

It’s very easy for unoptimized images to end up on a production site and slow down its initial load considerably. Inexperienced devs usually aren’t aware of this potential problem. They also aren’t aware of a wide range of tools and approaches for optimizing images.

This article aims to cover most of the tools and approaches for optimizing images for the web.

Good to see that it also covers native lazy image loading. The smallest image still remains an image not loaded unnecessarily 😉

Optimizing images for the web – an in-depth guide →

💁‍♂️ Addy Osmani’s Essential Image Optimization is also worth a look.

Urql – A highly customizable and versatile GraphQL client for React

From the folks at FormidableLabs:

urql is a GraphQL client that exposes a set of React components and hooks. It’s built to be highly customisable and versatile so you can take it from getting started with your first GraphQL project all the way to building complex apps and experimenting with GraphQL clients.

// App.js
import { Provider, createClient } from 'urql';

const client = createClient({
  url: 'http://localhost:4000/graphql',
});

const App = () => (
  <Provider value={client}>
    <TodoList />
  </Provider>;
);
// TodoList.js
import React from 'react';
import { Query } from 'urql';

const getTodos = `
  query GetTodos($limit: Int!) {
    todos(limit: $limit) {
      id
      text
      isDone
    }
  }
`;

const TodoList = ({ limit = 10 }) => (
  <Query query={getTodos} variables={{ limit }}>
    {({ fetching, data, error, extensions }) => {
      if (fetching) {
        return 'Loading...';
      } else if (error) {
        return 'Oh no!';
      }

      return (
        <ul>
          {data.todos.map(({ id, text }) => (
            <li key={id}>{text}</li>
          ))}
        </ul>
      );
    }}
  </Query>;
);

I know I’ve posted about this one before, but a lot has changed since then. Biggest change is that Urql now supports React Hooks. The TodoList example from above would then become:

const TodoList = ({ limit = 10 }) => {
  const [res] = useQuery({
    query: getTodos,
    variables: { limit },
  });

  if (res.fetching) {
    return 'Loading...';
  } else if (res.error) {
    return 'Oh no!';
  }

  return (
    <ul>
      {res.data.todos.map(({ id, text }) => (
        <li key={id}>{text}</li>
      ))}
    </ul>
  );
};

Over at Egghead you can watch some lessons how to use urql with Hooks:

You will learn how to set up an Urql Provider component so that all of your React components have access to Urql. Then you will learn how to use 3 of Urql’s React Hooks:

  • useQuery
  • useMutation
  • useSubscription

There’s also a few good examples listed in GraphQL and Urql by Example on dev.to

Installation per npm/Yarn:

yarn add urql graphql

Urql →
Urql Source (GitHub)
Egghead: Introduction to Urql →

💁‍♂️ The “older” Apollo GraphQL Client also received hooks support recently …

Endangered Species visualized in Pixels

Imgur user JJSmooth44 scraped The Animal Planet endangered animals list and generated photos of several animals where each “pixel” represents one actual animal running around.

The more pixelated the image, the closer it is to extinction.

There are about 2500 Bengal Tigers, so the picture above consists of 2500 “pixels”:

The Amur Leopard is less fortunate:

Every Pixel is one animal (Imgur Gallery) →

Automate your release process with 🛳 Ship.js

Interesting work by Algolia, to more easily release new versions of your packages:

When releasing, you go through something like the following:

  • Update the version in package.json
  • Update the changelog
  • Actually release it (e.g. yarn build && yarn publish)
  • Create a git tag

As such as manual process is prone to errors, they’ve developed 🛳 Ship.js, by which you can automate the process:

  1. Run shipjs prepare which will figure out the next version and create a PR
  2. Manually review the PR
  3. Run shipjs release to trigger a release and set up the proper tags and such

Installation per npm/yarn:

yarn add -D shipjs

🛳 Ship.js →

ESNext: Immutable Datastructures in JavaScript with Records & Tuples

A new ECMAScript Proposal that I’m looking forward to is this one which introduces the Record and Tuple value types. In short:

  • Records are immutable Objects that are compared by value.
  • Tuples are immutable Arrays that are compared by value.

The proposal is currently Stage-1.

Stage-1? Stage-4?

💁‍♂️ The TC39 Committee, which is concerned with the standardization of ECMAScript, has a 5 stage process in place, ranging from stage-0 to stage-4, by which it develops a new language feature. Stage-1 is the proposal phase. Stage-4 is when a proposals becomes part of the EXMAScript Speficiation.

As it stands right now, definition of Records/Tuples goes – quite obviously – the same way you define Objects/Arrays. The only difference is that you need to prefix the # operator to them.

// Records
const record1 = #{
    a: 1,
    b: 2,
    c: 3,
};

const record2 = #{...record1, b: 5}; // #{ a: 1, c: 3, b: 5 }

// Tuples
const tuple1 = #[1, 2, 3];
const tuple2 = tuple1.with(0, 2); // #[2, 2, 3]

Knowing that # is already used for Private Fields, and that the proposal still is Stage-1, I can see the operator get replaced as the proposal progresses over time. Personally I’m thinking to use the $ modifier/prefix.

ECMAScript proposal for the Record and Tuple value types →

💡 Looking for more ESNext Proposals that excite me? Check out ESNext: Proposals to look forward to, a talk I’ve given on that subject.

Did this help you out? Like what you see?
Consider donating.

I don’t run ads on my blog nor do I do this for profit. A donation however would always put a smile on my face though. Thanks!

☕️ Buy me a Coffee ($3)

How to start using your browser’s debugger

Solid introduction – with a real use case – on how to use the browsers’s built-in debugger:

In this post, I will cover using breakpoints, stepping through your code, setting watch expressions, and applying your fixes in Chrome Developer Tools.

How to stop using console.log() and start using your browser’s debugger →

☝️ Do not confuse the debugger with extra console.… methods such as console.table(), something which you can read about here.

Mercator – It’s a flat, flat world!

In the 16th century, Gerardus Mercator, a Flemish cartographer devised a new way of depicting the world on a flat plane. We set off to explore his map in order to illustrate his biggest blunders, unearth curious facts and explain the advantages that make this representation of the globe still relevant today.

I especially like the fact that the several parts of the map get highlighted as you scroll, thanks to the use of ScrollMagic

Mercator – It’s a flat, flat world! →

📜 If you’d want to venture into your own “animate as you scroll” adventure, I’d recommend a more modern library such as the aforementioned Scrollama (which uses IntersectionObserver)

🗺 In case you want to see for yourself how much Mercator distorts our view of the world, go play The Mercator Puzzle. In case you’re really into projections you might want to check out the contents of my talk Geoshizzle (from a long long time ago)

🌍 If you’re new to mapping & projections, or don’t want to read the lengthy article, this video from Vox sums it up quite nicely what’s wrong with the Mercator projection: