InVision presents

Design Systems Handbook


by Marco Suarez, Jina Anne, Katie Sylor-Miller, Diana Mounter, and Roy Stanfield

A design system unites product teams around a common visual language. It reduces design debt, accelerates the design process, and builds bridges between teams working in concert to bring products to life. Learn how you can create your design system and help your team improve product quality while reducing design debt.


Go to Chapter
Introducing design systems
The power of scale
Repetition and reusability make scale possible. InVision’s Marco Suarez takes you back to the foundations of component-based design and the many ways design systems enable scaling. He also addresses a few common misconceptions about design systems.
 
Go to Chapter
Go to Chapter
Designing your design system
Step by step

Starting can be the hardest step. Design systems expert Jina Anne walks through what to consider as you start out. Involve the right people, find the right model, add the right pieces—and you’ll be well on your way to establishing a successful design system.

 
 
 
 
Go to Chapter
Go to Chapter
Building your design system
A strong foundation

Building a flexible, maintainable, stable, scalable design system creates a strong base for your product design team. Etsy’s Katie Sylor-Miller shares foundational knowledge learned building design systems across cross-functional teams.

 
Go to Chapter
Go to Chapter
Putting your design system into practice
Better together

Encouraging adoption of your design system forges connections and creates champions across teams. GitHub’s Diana Mounter lays out practical strategies for sharing design systems and growing adoption, including examples from her experience.

 
 
Go to Chapter
Go to Chapter
Expanding your design system
More than the sum of its parts

Components form the core of a design system, but teams can align around much more than components. Marco Suarez outlines how teams can round out their systems with vision statements, design principles, voice and tone guides, and more.

 
Go to Chapter
Go to Chapter
The future of design systems
To infinity and beyond
Design systems play a huge role in shaping our present, but we may only be scratching the surface. Airbnb’s Roy Stanfield explores a bold future of intelligent, adaptive, context-aware systems that could further accelerate design’s possibilities.
Go to Chapter
Go to Chapter
Appendix
More resources
Design systems continue to evolve, and every company’s system can offer something to our collective knowledge and understanding. We’ve curated a list of publicly available design systems and resources to help you continue your exploration. 
Go to Chapter
01

Introducing design systems

The power of scale


by Marco Suarez

In the 1960s, computer technology began outpacing the speed of software programming. Computers became faster and cheaper, but software development remained slow, difficult to maintain, and prone to errors. This gap, and the dilemma of what to do about it, became known as the “software crisis.”

In 1968, at the NATO conference on software engineering, Douglas McIlroy presented component-based development as a possible solution to the dilemma. Component-based development provided a way to speed up programming’s potential by making code reusable, thus making it more efficient and easier to scale. This lowered the effort and increased the speed of software development, allowing software to better utilize the power of modern computers.

Now, 50 years later, we’re experiencing a similar challenge, but this time in design. Design is struggling to scale with the applications it supports because design is still bespoke—tailor-made solutions for individual problems.

Have you ever performed a UI audit and found you’re using a few dozen similar hues of blue, or permutations of the same button? Multiply this by every piece of UI in your app, and you begin to realize how inconsistent, incomplete, and difficult to maintain your design has become.

For design in this state to keep up with the speed of development, companies could do 1 of 3 things:

  1. Hire more people
  2. Design faster
  3. Create solutions that work for multiple problems

Even with more hands working faster, the reality is bespoke design simply doesn’t scale. Bespoke design is slow, inconsistent, and increasingly difficult to maintain over time.

Design systems enable teams to build better products faster by making design reusable—reusability makes scale possible. This is the heart and primary value of design systems. A design system is a collection of reusable components, guided by clear standards, that can be assembled together to build any number of applications.

For more than 50 years, engineers have operationalized their work. Now it’s time for design to realize its full potential and join them.

Scaling design with systems thinking

You’re probably well aware that design systems have become a bit of a hot topic in the software industry these days—and for good reason. Design is scaling. Many businesses are investing in design as they recognize that the customer experience of their products offers a competitive advantage, attracts and retains customers, and reduces support costs.

Here are what things usually look like inside a company that’s investing in design:

  • The design team is growing
  • Design is embedded in teams throughout the company, maybe in multiple locations
  • Design is playing a key role in all products on all platforms

If you’re a designer, this sort of investment in design may sound exciting, but with it comes many challenges. How will you design consistent UIs across platforms when many teams own various parts of your products? How will you empower all of these teams to iterate quickly? How will you maintain the inevitable design debt that will build up as many designers create new and tailor-made designs?

To understand how creating a design system can address these challenges, we must understand what design systems are. Design systems marry 2 concepts with individual merit, making something more powerful than its separate parts.

Standards

Understanding not only the what, but the why, behind the design of a system is critical to creating an exceptional user experience. Defining and adhering to standards is how we create that understanding. Doing so removes the subjectivity and ambiguity that often creates friction and confusion within product teams.

Standards encompass both design and development. Standardizing things like naming conventions, accessibility requirements, and file structure will help teams work consistently and prevent errors.

Visual language is a core part of your design standards. Defining the purpose and style of color, shape, type, icons, space, and motion is essential to creating a brand aligned and consistent user experience. Every component in your system incorporates these elements, and they play an integral role in expressing the personality of your brand.

Without standards, decisions become arbitrary and difficult to critique. Not only does this not scale, it creates an inconsistent and frustrating user experience.

Lori Kaplan, co-author of the pioneering Macintosh Human Interface Guidelines (HIG), tells the story of their creation and impact on designers and developers.

Components

Components are portions of reusable code within your system and they serve as the building blocks of your application’s interface. Components range in complexity. Reducing components to a single function, like a button or a drop down increases flexibility, making them more reusable. More complex components, like tables for specific types of data, can serve their use cases well, but this complexity limits the number of applicable scenarios. The more reusable your components are, the less you need to maintain, and the easier scale becomes.

Learn more about building components in Chapter 3: Building your design system.

Component-based development reduces technical overhead by making code reusable. Standards govern the purpose, style, and usage of these components. Together, you equip your product team with a system that is easy to use, and you give them an understanding that clearly links the what with the why.

The value of design systems

Let’s take a detailed look at the many ways a design system can be a much-needed painkiller for your growing pains.

Scale design

As teams grow, it’s common for designers to concentrate on discrete areas of an app like search and discovery, account management, and more. This can lead to a fragmented visual language—like a Tower of Babel of design—with each designer speaking her own language. This happens when designers solve problems individually and not systematically.

With no common design language to unite the product, the user experience starts to break down, as does the design process. Design critiques become unproductive when there’s a dearth of design conventions. To create alignment within teams, there must be a shared source of truth—a place to reference official patterns and styles.

Most often this is a static artifact, such as a design mock, but a static reference will almost immediately become outdated. That’s why teams build monuments like Shopify’s Polaris site—a design system site, built with the system, that documents all aspects of the system including the components, guidelines, and UX best practices. And because it is built with the system, it will always be up-to-date.

An internal design systems site is the best, most accessible source of truth for product teams. It provides the gravitational pull to keep team members aligned and in sync.

Manage your debt

As applications and their teams age, they build debt. Not financial debt, but technical and design debt. Debt is acquired by building for the short-term. Design debt is made up of an overabundance of non-reusable and inconsistent styles and conventions, and the interest is the impossible task of maintaining them. Over time, the accumulation of this debt becomes a great weight that slows growth.

The act of creation does not inherently create debt—just like spending money doesn’t inherently create financial debt. But using a design system will keep you on budget by keeping your design and code overhead low, while still allowing you to grow and evolve your application.

Design consistently

Standardized components used consistently and repetitively create a more predictable and easy to understand application. Standardized components also allow designers to spend less time focused on style and more time developing a better user experience.

Prototype faster

Working within an existing design system allows you to piece together flows and interactions as quickly as pulling LEGO blocks from a bin. This allows you to build an endless amount of prototypes and variants for experimentation, helping your team gain insights and data fast.

Iterate more quickly

Whether evolving the style of your UI or making UX changes to a flow, using a design system reduces effort from hundreds of lines of code to as little as a few characters. This makes iterations quick and painless, and experimentation much faster.

Improve usability

Inconsistent interface conventions hinder usability. When CSS for countless unique interface elements and their interactions increase, so does cognitive load and page weight. This makes for a terrible user experience. It can also create conflicting CSS and JavaScript, potentially breaking your app. By using a design system, you’re able to avoid these conflicts by building a holistic library of components, instead of per page, which means you’ll spend less time in quality assurance.

Build in accessibility

Accessibility can be implemented at the component level by optimizing for those with disabilities, on slow Internet speeds, or on old computers. This is an easy usability win. In Chapter 3, Building your design system, Katie Sylor-Miller explains how design systems can help improve your product’s accessibility and compliance with your country’s laws.

Myths of design systems

Even with all their benefits, buy-in for creating a design system can still be a hard sell internally. Designers can feel limited or restrained, but often these perceived weaknesses are the greatest strengths of a design system.

Let’s debunk common myths you’ll hear as you sell the idea of creating a design system.

Myth 1: too limiting

Myth: Designers embedded in discrete areas of an app see qualities that may be different from other areas. Because of this, a universal system is perceived as being too limiting and might not serve the needs of these specific areas.

Reality: Designers often end up creating custom solutions to improve discrete areas of the app, adding to design and technical debt. With a design system, new solutions can be created and fed back into the system making those improvements available to everyone.

Myth 2: loss of creativity

Myth: If designers are restricted to using a design system, then designers will no longer be free to explore style. Front-end backlogs are often full of design style updates. Evolving the visual style of an app is typically no small task. This can also be a great risk, as it removes resources from new feature work and may negatively impact usability.

Reality: The components of a design system are interdependent. This means when a change is made in one location, the change will be inherited throughout the whole system. This makes style updates within a system trivial in effort but much greater in impact. What once was weeks—if not months—of work, can now be accomplished in an afternoon.

Myth 3: one and done

Myth: Once the design system is designed and built, the work is complete.

Reality: A design system is living, meaning it will require ongoing maintenance and improvements as needs arise. Because your application is powered by the reusable components of your system, however, the application automatically inherits improvements to the system, lowering the effort to maintain the application. This is the power of scaling that a design system offers.

Conclusion

Design systems are not a fad or even an untested hypothesis. For design to find the scale necessary to match the rapid growth of technology, component-based design and development is a proven and dependable solution.

Now that you’ve seen the true value of creating a design system, let’s dive into the actual design process in the next chapter.

02

Designing your design system

Step by step


by Jina Anne

Starting a design system can feel daunting. There are so many things to consider: the design style, how to design for modularity and scalability, how it will be used by other teams, how to sell the idea to the decision makers in the company. Where is a designer to start?

Big problems are always more manageable when broken into smaller pieces. Before diving into the design process, start by considering who needs to be involved in the creation of your design system and how the team will work together. Once you’ve got the right people assembled, you’re ready to start thinking about the design language of the system, which will include color, typography, spacing, and more. Your visual design language will be the foundation of your UI library—a series of components that can be quickly assembled to create an interface.

Let’s take a step-by-step look at how you can start designing your design system.

Who should be involved

Rachel Cohen, Jessica Clark, and David Carmona from LinkedIn's Art Deco Design System team discuss how the system was formed, rolled out, and governed.

Before beginning work on your design system, take a moment to think about the team you’ll need to bring it to life. Who needs to be involved? Spoiler alert! You’re going to need more than just designers.

Here’s a quick list of the disciplines that can be represented in your team to create an effective design system:

  • Designers to define the visual elements of the system
  • Front-end developers to create modular, efficient code
  • Accessibility experts to ensure your system conforms to standards like WCAG
  • Content strategists who can help the team nail the voice and tone of the system
  • Researchers who can help you understand customer needs
  • Performance experts who can ensure your system loads quickly on all devices
  • Product managers to ensure the system is aligned with customer needs
  • Leaders (VPs and directors) to champion and align the vision throughout the company, including up to executive leadership

Once you’ve got the right skillsets represented in the design systems team, identify leaders to represent each area. These people should be able to drive decisions forward. Know who on the team can advocate for each of the areas of the design system.

With a team of experts guided by strong leadership, your next task is to establish the right team model to help you achieve your goals.

Choosing the right team model

The team model that brings people together is as important as the team creating the design system. In “Team Models for Scaling a Design System,” design systems veteran Nathan Curtis outlines 3 popular team models used by many companies.

The solitary model: an “overlord” rules the design system.

The centralized team model: a single team maintains the design system as their full-time job.

The federated model: team members from across the company come together to work on the system.

There are strengths and weaknesses in each of the above models. A solitary model is fast and scrappy, but with 1 person in charge of so much, the “overlord” can become a bottleneck to the completion of many tasks. A centralized team, on the other hand, keeps the system well maintained, but the group may not be as connected to the customers’ needs as they may be less involved in user research. Finally, a federated team has great insight into what’s needed for all the product features and user needs, but this group can be quite busy working on those areas outside of building the system.

Many teams are moving away from the solitary model to the centralized or federated model. As Curtis mentions in his article, overlords don’t scale. The centralized or federated models are usually much better for scaling a design system.

I wrote about the Salesforce team model in response to Curtis’s piece. When I was at Salesforce on the Lightning Design System team, we used a combination of the centralized and federated models. In an enterprise organization as big as Salesforce, a centralized design systems team was not enough on its own. With so many key players involved and the amount of ground we had to cover across products and platforms, we needed a more sustainable approach.

Though the Lightning Design System has a core team, there are also core contributors from many of the product and feature areas in the Salesforce ecosystem who act as a federation of practitioners, surfacing new ideas and making requests for the design system to evolve. Researchers, accessibility specialists, lead product designers, prototypers, and UX engineers work with the central design system team to both consume and help establish the patterns, components, and the overall design system. Engineers refine all code to make sure the system is performant and production ready.

Though the solitary model is less popular in most teams because the primary contributor can become a bottleneck, there are situations where it can work quite well. In the midst of a political campaign moving at breakneck speeds, Mina Markham had little time to bring in reinforcements as she developed new online assets for Hillary Clinton. She created a design system called Pantsuit to help many teams in many locations expedite design and production while maintaining consistency in the campaign brand. The solitary model let Markham focus on speed first and longevity second, which is a different tract than a typical enterprise might take.

As you determine what team model works for you, consider your goals. If you want to move fast, the solitary method is ideal initially, though some work may need to be done later to fully adopt it across other teams. If you want to move fast, but want to encourage buy-in from the start, consider the centralized team model. And to get the most buy-in and shared ownership, the federated model is a good option. In any case, remember that a design system is a product, so staff it like a product instead of a project; you want people committed to maintaining and evolving it.

With the team and the model that organizes them established, it’s time to start your design system just as you would any new product—by talking to your customers.

Interviewing customers

As with any product design process, it’s important to do your research. Who will be using your design system and how will they use it? Your design system will get used much more often if you create it to fit into the workflow of other teams. By interviewing users, you can pinpoint problems ahead of time, define principles that will help others use the system properly, and focus your energies on the most important things.

A less common group of people to interview are members of your open source community. This exists more likely in organizations that provide developer tools for customer and partner communities. If you plan to open source your design system—a potentially bigger project—then you’ll need to speak with potential contributors and consumers to discover what use cases your design system will need to satisfy.

And then there are the executives, leaders, and management. It is important to get their thoughts as well. You will need their buy-in to support and fund the system. Listen to their concerns and use them as actionable goals and metrics to achieve. Examples of requests might be shipping features faster, better performance, and improved UI quality.

With insights in hand from customer interviews, it’s time to take an inventory. There are 2 types of interface inventories to be created:

  • An inventory of the visual attributes (such as spacing, color, and typography), which will help create a codified visual language
  • An inventory of each UI element (such as buttons, cards, and modals), which will help create a UI library of components

Let’s first focus on a global visual inventory.

Creating a visual inventory

Of course, if you’re starting a design system for a product that doesn’t yet exist, you can skip this step and jump straight to creating a visual language for your new product. Lucky you!

Conducting a visual audit

As we start to take inventory, it’s good practice to take a look at the CSS used to create all of those elements you just captured in your visual inventory. Use a tool like CSS Stats to see how many rules, selectors, declarations, and properties you have in your style sheets. More relevant, it will show you how many unique colors, font sizes, and font families you have. It also shows a bar chart for the number of spacing and sizing values. This is a great way to see where you can merge or remove values.

If you’re creating an inventory in Sketch, use the Sketch-Style-Inventory plugin to aggregate all colors, text styles, and symbols. It also gives you the ability to merge similar styles.

Creating a visual design language

I must admit, as an art school graduate the visual design language in a design system is my favorite part to work on. I love thinking about color theory, typography, and layout, which are at the core of any design system.

If we break apart each component of a design system we find that these fundamental elements make up its visual design language:

  • Colors
  • Typography (size, leading, typefaces, and so on)
  • Spacing (margins, paddings, positioning coordinates, border spacing)
  • Images (icons, illustrations)

Depending on your needs, you may also include the following to further standardize the user experience:

  • Visual form (depth, elevation, shadows, rounded corners, texture)
  • Motion
  • Sound

Consider the role each of these design elements plays in a simple component like a button. A button typically has a background color, typography for the label, and spacing inside it. There may be an icon next to the label to create a visual cue. A border on the edge serves as simple ornamentation and may even round the corners. Finally, hovering over or clicking the button could trigger animation or sound as feedback to the user. Though a button may seem simple, there are many design decisions required to bring it to life.

Design tokens

Before we dive into visual design standards, I want to discuss design tokens. Design tokens are the “subatomic” foundation of a design system implementation. At its simplest, they’re name and value pairs stored as data to abstract the design properties you want to manage. With the values for all design tokens stored in a single place, it’s easier to achieve consistency while reducing the burden of managing your design system.

Example:

SPACING_MEDIUM: 1rem

In design tokens you can store colors, spacing, sizing, animation durations, etc., and distribute them to various platforms.

We’ll look more closely at design tokens in Chapter 3.

Color

The colors you choose for your design system are more than just an extension of your brand. A UI uses color to convey:

  • Feedback: Error and success states
  • Information: Charts, graphs, and wayfinding elements
  • Hierarchy: Showing structured order through color and typography

Common colors in a design system include 1–3 primaries that represent your brand. If none of these work well as a link and button color, then you may have an extra color for that as well. It’s a good idea to use the same color for links and button backgrounds as it makes it easier for users to recognize interactive elements.

You’ll likely have neutrals for general UI backgrounds and borders—usually grays. And finally, you’ll have colors for states such as error, warning, and success. Group these colors to see how well they work together and refine as needed.

Larger design systems sometimes include colors for objects and products. For example, at Salesforce we had a color for contacts, for sales deals, or groups, and so on. We also had them for products: Sales Cloud, Marketing Cloud, Analytics Cloud, etc. Color can be a helpful wayfinding tool for your users.

Using color for wayfinding can be tricky to do while maintaining accessibility, as people who are color blind may not be able to discern some differences.

Depending on how strict you want to be with your palette, you may want to include a range of tints—a color mixed with white—and shades—a color mixed with black. Sometimes you may use other colors instead of white or black to avoid muddiness, such as an orange to darken a yellow so it doesn’t appear brown.

These color variations allow designers to have choices. But be warned, having too many choices can lead to major design inconsistencies. Keep your inclusion of tints, shades, and neutral palettes slim to prevent misuse of the system while still giving designers the flexibility they need. You can always add more colors as you find the need.

Typography

Fonts and weights

The fonts you choose have a high impact on both your brand and your user experience. Keep legibility in mind as you select the right fonts for your system. Keeping to common system fonts like Helvetica, Times New Roman, or Verdana can be a great shortcut, as they are familiar to the user’s eye. Some companies prefer custom web fonts to better reflect their brand, but pay special attention to how you use them as performance can be affected.

Most design systems I’ve worked on include just 2 typefaces: 1 font for both headings and body copy, and a monospace font for code. Sometimes there’s an additional font for headings that compliments the body font. Most design systems do not have a need for more, unless you have a system that supports multiple brands. It’s best to keep the number low as it’s not only a best practice of typographic design, it also prevents performance issues caused by excessive use of web fonts.

These days it’s trendy to use a font at a very thin weight, but be aware that legibility can become an issue. If you want to use light or thin weights, only use them at larger text sizes.

Type scale

When selecting the size to set your type, consider the legibility of the font you’ve chosen. In most cases, a 16px font size works well. It’s the default font size in most browsers, and it’s quite easy to read for most people. I like using 16px as it works with the 4-based metrics used by Apple and Google (and is gaining traction as the standard approach). I recommend this as your baseline, though I would use it in a relative format like 1rem for CSS-based systems.

You can use a modular scale for larger or smaller font sizes for other elements such as headings. A modular scale is a set of numbers in which you have 1 base number, and a ratio to generate the next number. You keep applying the ratio to the new number to get yet another number.

As you design your type treatments, be sure to give thought to how it will respond to various screen sizes to maintain legibility. You won’t want your headings to be too large for mobile devices. And for much larger displays, you have the room to bump up sizes.

A common method is to enlarge headings on larger viewports. You can also use viewport units to scale your type based on a percentage of your screen size.

Leading

Leading, or line-height in CSS, can improve readability and aesthetics of your typography. While the best line-height can vary depending on the font face and the line length, a general rule of thumb is to have leading at around 1.4–1.5x the font-size. 1.5 is recommended by the W3C Web Accessibility Initiative.

It also makes your math more predictable, but you don’t have to calculate it. You can define your line-height without a unit of measurement and the browser will do all the hard math for you.

For headings, tighten it up depending on your typeface. In most cases, I find a 1.25 or 1.125 ratio works quite well.

Spacing and sizing

The system you use for spacing and sizing looks best when you have rhythm and balance. This means using numbers based on patterns and proportions. Using a consistent spacing scale also promotes maintainability through ratios by making layouts more predictable and more likely to “fit” and align well.

When I designed an Android app, I studied Google’s design guidelines. I noticed a pattern of using 8dp between elements and 16dp for outer gutters. It broke me out of using a 10-based scale I was accustomed to, as I found that 4-based worked so much better.

A 4-based scale is growing in popularity as the recommended scale for many reasons. Both iOS and Android use and recommend metrics that are divisible by or multiples of 4. Standard ICO size formats (which are used by most operating systems) for icons tended be 4-based (16, 24, 32, etc.) so that they scaled more easily. The browser’s default font size is usually 16. When everything is using this system, things are more likely to fit in place and line up. And finally, responsive math works out well.

For horizontal spacing, an 8-based scale works quite well. You can make margins and padding equal or in proportion to the font size. But for vertical spacing, I tend to use a 12-based system. This is due to the line-height I get of 1.5 (with the default font size of 16px) getting us to 24.

Occasionally, you may have to break this rule. If you’ve added a 1px border to something, this border can throw off alignment by a hair. So you might find yourself using a padding or margin that subtracts that amount. This is something that you do on a case-by-case basis.

You probably want elements to grow and shrink with the content. For general sizing, avoid setting widths and heights unless totally necessary. You can achieve responsive design much easier if you let elements flow to fill the space they’re given in the layout.

Images

File formats

For icons and illustrations, I find using a vector format (SVG) works best for scalability and responsive design. However, if you find yourself needing to use photography, you may need to use a rasterized image format like JPG or PNG.

For most photos, illustrations, and diagrams, you can allow the image to go 100% to the container or viewport and let the height automatically set itself by not defining it. This works best for responsive layouts. You may also want to define some preset widths for images if you don’t want it to go full width (for example, half-width, a third, or a fourth). I recommend setting these as max-widths so that the image can rescale for smaller screens.

Iconography

Before drawing your icons, come up with your guidelines around them first. Will they be filled or outline? What is the line weight? Will they use more than 1 color? What sizes will they be? Is there an icon art boundary set inside an outer boundary?

You may have different styles for different icon types. For example, utility and action icons (like a notifications bell or a settings cog icon) may be solid and 1 color, while navigation icons may be multicolored and more creative. Clear guidelines will keep your icons unified.

Illustrations

Illustrations are a great way to add some character to your product. You can use these for empty states, loading screens, modals, and other components that invite visual interest. Shopify went to great lengths to produce unique illustrations for all of the empty states of their platform, which conveyed a strong sense of brand personality (figure 19).

Similar to icons, it’s helpful to have guidelines for the style of your illustrations (figure 20).

Visual form

Visual form, or the material quality of your UI, is about the background images, gradients, and textures, shadows and elevation (z-indexes), rounded corners, and borders. These are visual qualities that help emphasize and decorate elements to add visual hierarchy and aesthetics. In any case, all are examples of ornamentation that need to be standardized.

Google does a great job indicating how depth and elevation work with layering of components (figure 21).

Motion and sound

When you define your visual language, motion and sound might not immediately come to mind. You experience these in a different way. But motion and sound can have a high impact on the experience of your app. You’ll want to have that systemized as well for consistency. I personally haven’t explored these areas as much as I’d like to admit, but there are some great examples in the wild.

Creating a user interface library

Before we conducted a visual inventory, which looked at the visual qualities of elements, such as color, spacing, and typography. Now, we will conduct a UI inventory, in which we look at the actual pieces of UI—like buttons, cards, lists, forms, and more. Where visual language is all about the visual approach and how things look on a global visual level, a user interface library (otherwise known as a pattern library) looks at actual components of a UI.

Let’s take a look at each of these design elements and the role they’ll play in your design system. Take stock of all interface elements in production to see just how much design debt you need to address and what elements are most commonly used. Warning! This can get a bit depressing, as most companies have an intense amount of inconsistency in their UIs.

To create an interface inventory simply open all products in production at your organization, screenshot all buttons, forms, various type styles, images, and collect them in a slide deck or on big posters where the whole team can see.

You can do this with cut out print-outs or through screenshots. Gather the folks you’re involving (as mentioned earlier in this chapter). Have them conduct this inventory with you, either through a shared presentation or via a hands-on activity. The idea is to gather the different components you’re using and categorize and merge them.

Some like dividing the pieces into elements, components, regions, utilities, and so on. Atomic Design is a great example of this line of thinking, which is a great conceptual model. But when it comes down to it, everything is pretty much a component, so at the end of the day, you could label all as such. But in general, what I see most design systems break things down into are:

  • elements (or basics, or atoms)—these are small, stand-alone components like buttons and icons
  • components (or molecules, or modules)—these are usually an assembly of small components into a larger component like a search form (which includes a form input, a button, and potentially even a search icon)
  • regions (or zones, or organisms)—these are an area of the UI like a left-hand navigation
  • layouts—how the pieces are laid out on the page (like a header region, followed by a sidebar and main content area, followed by a footer)

After you complete the inventory, you can merge and remove what you don’t need (either in a spreadsheet or even directly in a code refactor if you want more immediate change). Also, document what the component is and when to use it. This will become your UI library (or pattern library, or component library, depending on what your organization chooses to call it.).

Most design system documentation includes the component’s name, description, example, and code. Others may show meta data, release histories, examples, and more. What matters most is that you show what’s necessary for your team to get your work done.

Conclusion

Creating a design system not only helps your team produce more consistent user experiences, it also builds bridges between design and development. By creating a common visual language codified through design tokens, and a set of components and patterns cataloged in a UI library, you’ll vastly improve designer/developer communication. You’ll also have fine-tuned control of the UI in a way that is manageable, scalable, and robust.

03

Building your design system

A strong foundation


by Katie Sylor-Miller, Etsy

Modern design systems are the result of many years of evolution in the way we write front-end code. When I started my career, most sites were built with single-use, inefficient, fragile, and inconsistent front-end codebases. Through hard-won experience and many years of collaboration and iteration, front-end developers have established more sophisticated practices for writing and organizing our code. Now, there is an explosion of front-end frameworks and tooling to help you write better, more maintainable HTML, CSS, and JavaScript.

This represents an exciting paradigm shift in front-end development, but the number of choices available can be overwhelming. A cursory glance at the table of contents for Cody Lindley’s Front End Developer Handbook 2017’s section on tools reveals a bewildering array of considerations. I couldn’t possibly cover all of the technology choices available—the factors that go into your decision-making will be largely situational, and this is only a chapter!

Instead, I’ll save you the headache of attending the school of hard knocks by walking you through what I’ve learned from building and contributing to 3 different design systems. First, I’ll cover the technology-agnostic foundational principles that should guide the development of your design system. Then, I’ll focus on some common pitfalls and how you can avoid falling prey to them. Throughout, I’ll introduce you to some of the tools that will help you along the way, but remember this: Your technical approach doesn’t matter as much as creating a living, breathing system that’s flexible, maintainable, stable, scalable, and successful in the long-term.  

Foundations

Regardless of the technologies and tools behind them, a successful design system follows these guiding principles:

  • It’s consistent. The way components are built and managed follows a predictable pattern.
  • It’s self-contained. Your design system is treated as a standalone dependency.
  • It’s reusable. You’ve built components so they can be reused in many contexts.
  • It’s accessible. Applications built with your design system are usable by as many people as possible, no matter how they access the web.
  • It’s robust. No matter the product or platform to which your design system is applied, it should perform with grace and minimal bugs.

Let’s take a look at each of these principles in more detail.

Consistency

Your first, most important task when starting out is to define the rules of your system, document them, and ensure that everyone follows them. When you have clearly documented code standards and best practices in place, designers and developers from across your organization can easily use and, more importantly, contribute to your design system.

Code style guides

Code style guides provide the grammar rules of syntax and semantics for your code. Code syntax is the set of rules for structuring and formatting your code (e.g. curly braces always go on a new line). Code semantics provide the rules for making your code understandable (e.g. alphabetize CSS property declarations). But don’t get bogged down fighting pointless wars over tabs versus spaces. The most important thing is to end up with consistently written code, not to achieve theoretical perfection!

Automating code style

To enforce your code standards and achieve consistency in your system, help your contributors write code that follows the rules through linting and tooling.

Linting is an automated process of analyzing code and raising errors when code either doesn’t adhere to your syntax rules or is broken, buggy, or malformed. Linting tools such as CSSLint or StyleLint for CSS, and JSHint or ESLint for JavaScript, can be run manually as part of your local development process, as an automated pre-commit hook before code is checked into source control (the best option), or run as part of your build process.

Code editor configuration

An often-overlooked but important corollary to linting is providing an Editor Config to enforce code style in your editor(s) of choice. EditorConfig.org (figure 1) provides a cross-platform format to define stylistic rules for most code editors and IDEs, so you can automatically convert your tabs into spaces—thus ending the tabs versus spaces war!

Self-contained

Your design system should live in a source control repository independent from your main codebase. Although it will require more work to get up and running, a separate repository brings many long-term benefits:

  • It enables versioned releases of your code (more on this later)
  • It allows you to share code across multiple teams, products, and codebases
  • It forces you to develop components in isolation so they’re not tied to a single use case
  • It provides infrastructure for a robust front-end testing architecture
  • It forms a foundation for a living style guide website

A standalone design system repository functions as a single source of truth. There is only one place where components are defined, which then gets shared into other codebases as a discrete dependency. Because all usages point back to a canonical implementation, changes in a single place propagate through the entire system.

Ideally, all of the code for each component within your system is co-located: CSS, JavaScript, HTML templates, and documentation all live in the same place, possibly the same directory. If you’re using React with CSS-in-JS, each component may even be encapsulated in a single file. The closer the pieces are to each other, the easier it is to trace and manage dependencies between bits of code, and the easier it will be to update and maintain.

Reusable

Successful design systems are highly reusable. Bootstrap, the most-used front-end library of all time, powers hundreds (if not thousands) of websites because it was architected with reusability in mind. Writing components to be reused in multiple contexts is vitally important, yet hard to do well—make components too focused for a single use case or too inflexible, and users will end up creating their own patterns.

To be reusable and scalable, patterns need to be modular, composable, generic, and flexible.

  • Modular components are self-contained with no dependencies
  • Composable components can be combined to create new patterns
  • Generic components can handle multiple use cases
  • Flexible components can be tweaked and extended to work in a variety of contexts

Modular CSS architecture

Reusability and scalability in design systems begin with taking a modular approach to your code architecture. CSS, however, is not inherently modular. So over time, systems like SMACSS, OOCSS, and BEM have added structure and modularity to CSS. More recently, CSS-in-JS approaches such as Styled Components have solved the problem by defining CSS properties in JavaScript code structures.

Whether you use one of these systems or roll with your own, the fundamentals of any good CSS architecture are the same:

  • It has clear naming conventions for components, variations, and utilities
  • It’s tightly-scoped and has low-specificity CSS that limits unintentional side effects
  • It has utility classes that allow you to modify styles in a managed way
  • It has rules for building modular, composable, generic, and flexible components

To learn more about architecting CSS so that it meets these criteria, I highly recommend Harry Roberts’ https://CSSguidelin.es/ (figure 2), then adding this type of documentation to your system.

Accessible

For too long, accessibility, or a11y, has been misunderstood as building sites for a small group of users of assistive technology—a blind person using a screen reader—and far too often dismissed as too complex, too time-consuming, or “not our customers.” Accessibility, however, is not just for a single, small group, but for an estimated 15% of people worldwide (56.7 million people in America alone) with a wide spectrum of permanent or temporary visual, auditory, motor, and cognitive impairments.

Thankfully these attitudes are changing and our industry is embracing a more inclusive definition of accessibility. Making your site accessible to users with disabilities improves the experience for everyone who visits your site. If that isn’t enough motivation, improving your site’s accessibility can help improve SEO, and it’s becoming increasingly more important from a legal standpoint to avoid costly lawsuits.

In a landmark case against the grocery chain Winn-Dixie, a federal judge ruled that websites are subject to the provisions of the Americans with Disabilities Act (ADA). If you’re just learning about accessibility, there are a lot of resources to help you get started. I recommend reading the introductory articles from the W3C’s Web Accessibility Initiative (WAI) WebAIM, and the A11y Project. You can inspect the current state of your site using Tota11y, an a11y visualizer bookmarklet by Khan Academy. Starting an accessibility practice where none has existed before can be challenging, but when you leverage your design system, it’s easier than you might think.

Enforce a11y with your design system

To ensure everyone at your organization builds accessible sites, features, and apps, enforce accessibility best practices in your design system code.

  • Test your color usage against established color contrast guidelines (figure 3).
  • Build components to be keyboard and screen reader accessible by default. The Ebay Accessibility MIND pattern library is an amazing, thorough resource to help guide development of accessible components and best practices. Encourage contributors to build according to these guidelines and test their code using keyboard-only navigation and assistive technology devices like screen readers.
  • Include in your documentation code standards and guidelines for common a11y best practices such as using larger, legible text sizes, always associating a form field with a label, and properly adding alt text attributes to images, to name a few. Salesforce’s Lightning design system and Shopify’s Polaris are great examples of accessibility guidelines in practice.

These accessible practices improve usability for everyone by making it easier to view, interact with, and navigate a site, improving form completion rates and reducing user mistakes.

Use the power of your single source of truth to create a foundation for accessibility, thus relieving some of the burdens from product teams. It’s much easier to build in accessibility from the start than to bolt it on after a feature has been designed and built.

Robust

A robust design system has a strong foundation of tests behind it. Testing provides confidence in your code, which facilitates adoption. Users will know that they can upgrade or change their UI without it breaking in unexpected ways. Additionally, your design system is uniquely positioned to form a foundation for robustly testing your front-end code.

Test your design system instead of your complicated UI

Keeping tests up to date for pages, applications, and features—especially on a rapidly changing site or one with heavy experimentation—requires a lot of work. Tests get out of date quickly! You can narrow the scope of your tests and gain higher levels of confidence in your site-wide front-end code by heavily testing your design system components. You already need to generate example code for the different states of each component for your documentation—use those as your test fixtures.

Types of tests

There are 4 types of tests used for ensuring stability in your design system:

  • Unit testing: These tests verify that small units of code (usually individual JavaScript functions) behave as expected. Unit tests execute functions with a set of predefined inputs, then verify that they return the expected output. Some popular frameworks to use are Mocha, Jasmine, and Jest.
  • Functional testing: In functional tests, examples of your code, or “fixtures” are run in a virtual “headless” browser, then tested by performing simulated user actions, and checking the new state of the browser for the expected result of those actions. Functional testing frameworks include Nightwatch, Protractor, and Casper.
  • Visual regression testing: These tests help catch unintended visual changes to component styles. The test framework takes screenshots of your fixtures both before and after the changes, then compares them using an algorithm to detect visual differences. There are open source frameworks like Wraith, Gemini, and BackstopJS, as well as paid services like Applitools and Percy.io. Go to Kevin Lamping’s excellent resource Visual Regression Testing for more information and options.
  • Automated accessibility testing: Leverage tooling to ensure that your components are accessible. Some options for running automated a11y audits are Paypal’s AATT and a11y by Addy Osmani, and aXe by Deque Systems.

Common challenges

No system is ever perfect. You will make decisions that you later regret, no matter how much time you put into designing your design system. You can, however, anticipate issues that arise as your system grows, and work to avoid or mitigate their effect on your project. There are 3 common challenges I’ve seen arise in multiple design systems:

  • Keeping documentation up-to-date with your system code
  • Handling breaking changes
  • Avoiding performance degradations

Let’s look at each of these concerns in detail.

Maintaining documentation

The first time I built a front-end component library, my team decided it would be easier to create a documentation website with a codebase separate from our application. In hindsight, this decision broke the cardinal rule of Don’t Repeat Yourself. Whenever a component changed in our main codebase, we had to remember to actually update the documentation, then do the tedious work of duplicating the changed code in 2 different codebases. Unsurprisingly, our documentation got out of date almost immediately!

Learn from our mistakes by reducing the distance between your documentation and code and using automation.

Minimize separation between library code and documentation code

Earlier in the chapter, we discussed storing your design system code in a separate repository that functions as your single source of truth. When documentation and code are co-located, it’s more likely that you’ll remember to update the documentation when a component changes. Consider adding a pre-commit hook to your design system repository to warn contributors when their code adjustments don’t also contain updated documentation files.

Automate documentation

Start by documenting your system using simple, human-readable files written in markdown, co-located with each component. Github is already configured to render and display any file named README.md when you’re viewing a folder’s contents—you might not need a flashy website at all!

If and when you do decide to create a full-featured documentation website, use automation to simplify the process. Instead of creating a new codebase for a separate website, use a tool that will auto-generate documentation for you—there are lots to choose from—reducing the amount of structural HTML you need to write and maintain.

Handling change

As adoption grows and your design system becomes more widely used, you will invariably realize that you didn’t get it all right the first time, and you will need a plan to handle breaking changes. A breaking change is a situation where necessary changes to a component’s code will break existing usages of that component or class. The Morningstar design system provides guidance to contributors on what is considered a breaking change. If mishandled, breaking changes can be a major pain point for your users.

The wrong way: duplication

Initially, all of the CSS and JavaScript for Etsy’s Web Toolkit lived in the same monorepo with the rest of the team’s site code. This meant that whenever someone made a breaking change to a component, their commit making the change had to also contain fixes and updates for every single usage of that component. At first, when just a small team built and used the system on a subset of pages, finding and making these changes was relatively easy. But as adoption spread throughout the company, this quickly became unmanageable.

It became such a headache to make major structural changes to existing components that our team at Etsy started to duplicate and deprecate—when we refactored our Tab component to make it fully accessible, we created a new component named “Tabs2,” and deprecated “Tabs” in the hopes that teams would take on the work to upgrade their code. But without clear guidance on how, why, and a timeline stating when to upgrade, most uses haven’t been updated to use the new component. This kind of duplication is a code maintenance nightmare.

The right way: versioning

Breaking changes are easier to manage if you store your design system code in its own source control repository. This gives you the ability to do versioned releases of your code, which can be shared with other projects. Git allows you to tag a commit with a release version number, and package managers like npm and Yarn allow you to package up and publish multiple versions of your design system code.

With versioned releases, the adopters that integrate your design system code can target a specific version as a dependency and control when and how upgrades to new versions are handled. Make sure to publish release notes detailing changes so other teams can learn how upgrades will impact their codebase and better plan for upgrade work in their project timelines.

Avoiding performance issues

As a design system grows over time, generally so does the file size of assets sent over the wire on each page. This can negatively affect your site’s page load performance, which in turn negatively affects your company’s bottom line. Help the products built on your design system avoid performance issues by taking a mobile-first approach and build your system with modularity in mind.

Mobile first

Poor page load performance will have the largest negative effect on mobile visits. According to statistics from Google and Akamai, more than half of mobile visitors will abandon pages that take longer than 3 seconds to load, yet the majority of mobile sites take longer than 10 seconds to load. As mobile traffic overtakes desktop, speeding up your page’s performance is more important than ever to give you a competitive edge.

Build your design system mobile-first—test early and often on real devices with real hardware and a real network connection so you can understand the experiences of real users.

Leverage modularity

Initially, it made sense to bundle all of the Etsy Web Toolkit components and utilities into single files for CSS and JavaScript. While this is useful for prototyping, it adds unnecessary weight to production pages that don’t use all the components. Now, we’re working to avoid performance problems by better using the modularity inherent in the system. To do this, we are:

  • Deciding on a set of core components and utilities that are most frequently used. This base file will be included on all pages that use the design system and can be cached by the browser across page requests to improve load times.
  • Ensuring that all components are fully modular with no cross-component dependencies (unless they are explicit and managed by the system).

Packaging and sharing the system’s code so that it can be consumed as individual CSS and JavaScript modules added as dependencies only when a component is actually used on the page. We use an in-house system to define dependencies in our front-end code. Build your design system modules so they work with the dependency manager that your team uses. Webpack is a popular option.

Forward-thinking

Design tokens

For most of this chapter, I’ve focused on building design systems for web applications and sites. However, that’s not the full picture. Modern organizations face unique challenges with their design systems at scale. Today, we build for multiple web and native platforms that need design consistency. Larger organizations may have multiple sub-brands that want the shared support, functionality, and organization that a design system brings, but each needs a different, brand-aligned look and feel. The Salesforce UX team introduced a solution to both of these problems: design tokens (figure 8).

Cross-platform sharing

Design tokens are a way to abstract design details like colors, fonts, rounded corner radius, etc., into a format that can be shared across platforms using Salesforce’s Theo tool. Instead of defining your main brand color as a SASS $variable in your web app, a UIColor in your iOS app, and a textColor in your Android app, you define a single design token in a shared JSON file that gets compiled into platform-specific code (figure 9). Decide to change all of your rounded corners from a 3px to 5px border-radius? Change the value once in your tokens file, and it propagates to all of your apps automagically.

Multi-product theming

You can also use tokens to “theme” the same structural styling for multiple brands. One brand wants orange buttons and the other wants blue? No problem! You can define different token values for each brand, then combine each to the same, base CSS to output themed versions of your design system. That way, all of the classes are the same, and all of the accessible JavaScript functionality you worked so hard to build can be used as-is with no modification for each brand.

Conclusion

Systematizing your front-end code benefits everyone in your organization: developers move faster, designers don’t have to reinvent the wheel, and ultimately, your users have a better experience. But starting out can feel overwhelming!

Thankfully, there is a wealth of resources and a growing community of folks sharing their own best practices to help you build your system. Anna Debenham’s Styleguide Resources lists nearly 500 public design systems/style guides/pattern libraries to use as inspiration. While they look and feel very different, each shares a common goal and is built upon foundational principles that our industry has developed through many years of trial-and-error.

A flexible, maintainable, stable, scalable, and successful design system begins with a strong foundation that goes beyond frameworks or tooling. If I’ve learned anything in my career, it’s that the only constant in front-end development is change. Chances are, within a few years, the technology driving your front-end will look very different than it does right now. If you build for the long-term and plan to handle change, then you can implement new, better practices as your system grows.

That’s not to say you should aim to create another Bootstrap right out of the gate. Even if your team can only implement a few of the best practices we’ve discussed in this chapter, it’s still worthwhile—some of the techniques I recommend haven’t yet been implemented in the design system that I work on every day! Design systems are not a one-and-done thing, but a continual process of iteration and change as we make mistakes, learn from each other, and create new and better approaches to front-end code.

About the Authors

Marco Suarez
Product Designer, InVision
Katie Sylor-Miller
Staff Software Engineer, Etsy
Roy Stanfield
Design Lead, Airbnb
Diana Mounter
Design Systems Manager, GitHub
Jina Anne
Design Systems Pioneer, Independent
Design Systems Handbook
Design Systems Handbook