Skip to content

Planar web design

Posted 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. Don’t draw attention more than once per pixel.

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.

Wizards and workflows

Posted March 2018 in #design

Software is a multiplier — it can empower users but it can’t induce behavior. Behind every successful app stands a pre-existing motivation. In other words, while you can lead users to your landing page, you can’t make them pay. Great software makes people better at things they already want to do.

However, on the road to great software, finding an idea that serves an existing motivation is just the first step. We may know which market to fit, but how do we product? How should each feature be designed to best help the user?

An early decision is whether or not the interface should mandate a workflow. This is the difference between a wizard and a spreadsheet, or a chatbot and a text editor. Wizards constrain users: first do this, then do that. It’s the same with chatbots: answer this question and I’ll ask you the next. On the other hand, spreadsheets mandate nothing: it’s a blank canvas — an empty slate.

If you know the domain better than the user, for example if the software is an interface to your organisation, go for a wizardly approach. Be a guide, provide hints, and correct mistakes along the way — all in as few steps as possible.

On the other hand, if your idea covers a process the user knows well, be a tool. Provide the features they need, monitor usage, iterate and improve. Aim for a flat set of orthogonal but complimentary features. Provide the tools as best you can, then get out of the way. Your users already know what they want to accomplish, because technology trails incentive.

Spend time on target

Posted February 2018 in #dev

It is usually more productive to talk about feature scope than about priorities. While slight shifts in priority are seldom actionable, scoping requires decisions. Scoping scales products by their number of features, and not by overall quality. Tradeoffs must be made and features must be cut — at every level of the stack.

The first step in scoping features is to get everyone on the same page. For this, words are often not enough. A shared understanding is better achieved through detailed sketches and interactive mockups. Too much code is written based on a false assumption of agreement. Make a feature obvious, then decide its scope.

The next step is to decide on which features to keep and which features to cut. Scoping is about tradeoffs. Each potential feature has an expected cost, utility, and interplay with other features. These tradeoffs should be difficult as they decide what the product will be. And iteration does not preclude planning.

When features are fleshed out and scoped in it is finally time to build. At this point there should be no fundamental questions unanswered or important thoughts unsaid. If there are split opinions it is time to disagree and commit. Any feature of uncertain scope should be pushed for re-planning in the next iteration. Plan more, code less, and remember where you’re going.