Growing (and Shrinking) Pains
How to fix a broken spacing system
A recurring refrain in our conversations with operational product designers was that all our design system components were just too darn big for internal tools. Many of these tools feature full screen data tables and charts. In these information-dense contexts, it’s important to make as much content visible on the screen as possible so users can easily scan, parse, and compare information. Unfortunately, when operational product teams tried to fit our existing components into these contexts, they looked gigantic and out of place.
At first glance, it seemed we needed to considerably shrink down our components to work well for operational products — but how small could we go while still maintaining WCAG AA target size standards?
Accessibility is a Lyft-wide quality standard and is therefore non-negotiable in our design system. Previously, our internal products largely flew under the radar of this standard because there weren’t many centralized resources or guidelines for them to follow. Unsurprisingly when we brought up the 44px minimum pointer target size in initial meetings with operations teams, it was a big sticking point and a likely deal breaker.
Rather than press the issue further, we did more research. Externally, we looked at how other companies handled the same problems. These articles in particular greatly elucidated the problem:
- Space in Design Systems and Size in Design Systems both by Nathan Curtis
- Using Material Density on the Web by Una Kravets.
Internally meanwhile, we audited our existing web components to see if our current approach to sizing and spacing could be extensible to operational products.
We learned that while we had “Default” and “Compact” sizes of most of our components, those names didn’t consistently correspond to component vertical heights, content sizes (i.e. text and icon sizes), horizontal and vertical padding, or component shapes (i.e. border radius). Several components lacked two sizes entirely and others had different names for their “Default” and “Compact” versions. The component sets had grown piecemeal — a side effect of an oversight in our process.
When we add new components to our libraries, we audit their usage across different product experiences to standardize their sizes. We don’t often evaluate all our components as a set, so over time, “Default” and “Compact” came to mean slightly different things in different contexts.
Before our research, we assumed the crux of the problem was that operational products needed smaller components but that these components would have to be inherently pointer target inaccessible. Through our audit, however, we realized that we had never before approached sizing, spacing, and density holistically. So what we really needed were clear and consistent rules around how to apply density in both consumer and operational products.
Density is an overloaded term and usually refers to screen density or the literal pixel resolution of displays. While internal product teams universally asked for more dense components for dense interfaces, they weren’t talking about pixel resolutions. We discovered through our research that there are 3 dimensions that make a screen feel more or less compact. These dimensions comprise visual density, or the set of spatial relationships within and between visual elements on a screen, including:
- Content size (i.e. type scale, icon scale)
- Container padding and shape — the space within a container
- Layout — the space between screen elements
It seemed like once we defined density, everything else started falling into place. For one thing, our “Default” and “Compact” sizes could now also be defined and standardized. We set standard values for our internal padding, content scales, spacing, and container shapes in terms of our base 8px grid. We also standardized the typography styles we use within operational products (article coming soon)! These decisions had the happy side effect of greatly simplifying our decision making process for adding new components to the library.
Roughly speaking, consumer web products could use Default components while operational web products could use Compact components. But we also called out specific exceptions and provided more granular guidelines for how to mix different densities within the same screen on our documentation site.
Finally, we realized that the third density dimension, layout, was the key to unlock an accessible, visually dense, interface. With our minimum content sizes and visual height requirements, as long as there is at least 6px between each UI element, we can ensure pointer target accessibility for even the tightest of layouts. We just define the interactive area of each component to extend slightly past its visual area and ensure the interactive areas don’t overlap with our component layout requirements. To make it extra easy, we created accessibility helper components in Figma to visually show designers the minimum accessible pointer target area for each interactive UI element.
5 easy steps to fix your system spacing
Our path to spatial clarity has been meandering — fixing spacing in an existing, mature, design system is a messy business. For example, we learned the importance of publishing size changes in bulk rather than individually when system users started noticing that some of their components grew or shrank out of alignment with components we hadn’t “fixed” yet (whoops)! We also learned that only design systems enthusiasts get really jazzed about attribute updates while everyone likes shiny new components, so we started crafting our comms differently to reflect that.
If you are attempting to adapt your system to work for a new visual density or if your system suffers from inconsistent sizing and spacing like ours did, we hope this distillation of our work can help:
- Audit your system components, decide how many different visual densities you need, and name them.
- For each density, define values for content size, container padding and shape, and layout spacing in terms of your base pixel grid (bonus: involve system users in the decision making process)!
- Apply standardized visual density names and values to all existing components (this is the bulk of the work and may take months and an airtight communications strategy to complete — but it is worth it).
- Create new components so each component has a version for each visual density.
- Publish visual density changes in bulk to your libraries to reinforce the fact that this is a holistic, attribute-level, change.
Whatever your system spacing journey looks like, and however messy your audit table gets — know that accessible, information-dense, interfaces are possible!
This story is part of Lyft Product Language’s series on How to Systematize Internal Products.
Up next: Typography for Data Products