Building Better Interfaces, a talk by Hakim El Hattab

At CSS Day 2019, I was fortunate to see Hakim El Hattab bring his talk Building Better Interfaces. A recording of his talk – and all other talks – are available on YouTube:

This session is a deep-dive into the areas of interface design that Hakim has specialized in for over a decade—interactivity and animation. He’s going to take an in-depth look at a few different UI components to highlight common pitfalls and present concrete solutions. He’ll talk about the correlation between having fun at work and building interfaces that are fun to work with. Most of all, he’s going to share practical tips for building better and more enjoyable user interfaces on the web.

Personally I think a more fitting title would’ve been “Building More Delightful Interfaces”, as the additions don’t necessarily make the interface itself better, as they already were really good to begin with. If you have the time to add these kind of extras, be sure to do so … they surely will bring smiles on the face of your users.

Good Code Reviews, Better Code Reviews

Gergely Orosz:

Plenty of people and organizations have shared their code review best practices and what the definition of good code reviews mean to them. Below is my personal take on what good code reviews look like and what great ones – better than good – are.

Some very good tips! In my own personal experience: Good PRs and Reviews take time to write. It’s most of the time a very sentimental thing.

Good Code Reviews, Better Code Reviews →

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)