Skip to content

Planar web design

Pinned since July 2018 in #design

Web design is a study in accidental complexity. For example, while there’s no inherent aesthetic value in putting text on top of images, it’s a mainstay. Instead this kind of layering creates complexity. It constrains the text, the image, and sets up a duel for the user’s attention. Two dimensions ought to be enough.

Few habits complicate web design quite like undue layers. There are enough maligned modals to declare position: fixed forever broken — not technically, but in practice. We’ve permanently lost viewport height to a storm of sticky headers. And each layer burdens both design and code. Poor z-index.

Luckily, we have superior alternatives to every layer. Place text before or after images. Move modal content inline or extract it to a new page. Let headers remain on top. Instead of adding a loading overlay, make your site so fast that it can do without. And if the end result looks empty, redesign.

The web works best for designers, developers, and users alike when it is constrained to a single plane. We can shift the time spent on layering content to be used on improving the content itself. There is no need to compete with your own interface. Draw attention once per pixel, and keep form flat.

—   ¶

Stale data beats fresh errors

Posted June 2018 in #dev

A web browser’s back button is more than a link to the previous page. It is the navigational equivalent of undo. Going back should restore the previous page, exactly as it was last time we were there. Conversely, the forward button is redo. These actions traverse history — they should never mutate state.

Luckily, the browser is a capable time machine on its own, at least for regular web sites. It will cache content, remember form values, reset scroll bars, and all the other things required to preserve the browser history. Just make sure to keep Cache-Control: no-store out of your response headers.

However, for web apps, where we make our own little world of routes and state, it’s up to us to tackle time travel. And while an implementation as polished as the browser’s may be out of scope, a little consideration goes a long way.

An expired session is not an error when going backwards. Navigating history should never clear data or result in a spinner. It should not show any sudden 4xx or 5xx errors because of a fetch. Previous form values should be restored, even if invalid. And navigating history should always work — even when offline.

—   ¶

Unread doesn’t count

Posted May 2018 in #design

There’s a new notification about enabling notifications. The email client tells of three unread spam messages. The settings app has exactly one new system update. Twitter’s tab title counts five new tweets, as always. The home screen is littered with red badges. There’s no value in a predictable notification.

Unread counts are everywhere in modern interface design. They are tasked with retention and growth, often implemented without restraint, and typically end up ignored by most users. But just as in computer science, when it comes to what’s unread, there are only three amounts that count: zero, one, and some.

Most unread counts should stay at zero. This is the kind of feature that works best as opt-in. Better to err on the side of not-annoying. Even if important, many prefer to check counts themselves, at set intervals. And instead of counting to one, show a dot. But not a dangerous red dot. Make it blue, or green.

If there are some notifications, show, at most, a more more prominent dot. There’s probably no actionable difference between 4 or 8 or 16 unread items. However, if there are always some notifications, just remove the indicator. Nobody needs another ignored attention grabber. Leave the user alone.

—   ¶

Cascading consistency

Posted April 2018 in #dev

CSS is neither code nor markup. It’s not a query language, a configuration language, or a DSL. Instead, CSS is a style sheet language — a world of its own. Yet we haphazardly import rules from other fields. It’s far from given that our ideas about globals, inheritance, and modularity apply to the world of CSS.

The closest thing to a style sheet is not found in programming but in design. More than anything a style sheet resembles a style guide — a codified design specification. For what is a style guide but a set of design rules, invariants, and exceptions? And in both cases the ultimate goal is design consistency.

Good design is consistent. There are ground rules that apply by default, with extensions and exceptions as required. In other words, cascading inheritance is not a complexity brought by CSS, but an inherent challenge for any design language. Whether expressed in *.css or *.js, whether the cascade is implicit or explicit, inheritance is a fundamental property of good design.

This perspective informs one approach to writing CSS where we embrace cascading over isolation and inheritance over repetition. Instead of expecting consistent application of a written guide to isolated components, we use our limited pool of developer discipline for explicit reliance on global styles.

In this approach, any style that can be global should be global. Local styles should rely on styles defined further up the chain. Whenever possible, prefer unitless values and percentages to absolute measures. Prefer declarative centering to explicit offsets. Prefer intrinsics like currentColor to variables. Prefer em to rem and rem to px. Extend on a base without overrides.

—   ¶