Create your design system, part 6: Buttons

Buttons are the most important interactive components used by the users to perform actions. Designing buttons means creating a toolkit that allows interaction with an interface.

In this final article of our series on design systems, we’ll take a look at how to design a system of buttons in CSS.

This article is part of a series on design systems inspired by our (upcoming) library of web components. The library relies on a solid system of CSS globals.So this is us sharing the things we’ve learned setting the global style of our library! ✌

Article Series:
- Part 1: Typography
- Part 2: Grid & Layout
- Part 3: Colors
- Part 4: Spacing
- Part 5: Icons
- Part 6: Buttons

Setting the basic button style

The starting point of designing buttons in CSS is defining a basic style that can be applied to all our button components:

The basic style includes those properties that you don’t plan on overwriting while creating button variations later on, as well as reset style to prevent common style issues. For example:

  • position: relative; is used in case you want to create interactive icons where an icon replaces the text label.
  • white-space: nowrap; prevents the text label from wrapping to the next line.
  • text-decoration: none; removes the text decoration in case you’re applying the .btn class to a link.

Abstracting the font-size and border radius is particularly helpful in the early stages of creating a design system, when changes are frequent. Padding values are defined according to our spacing system, so that they are automatically responsive.

Style variations

Style variations are different styles used to convey meaning to buttons. They generally include:

  • .btn--primary → the main call-to-action button style.
  • .btn--secondary → a subtle style version, used for secondary actions or in combo with the primary/accent button.
  • .btn--accent → used to draw particular attention to the button (e.g., destructive actions).
  • .btn[disabled] → used for feedback, to identify a button that is disabled.

In CSS:

A few important notes: first of all, all the colors are defined in a separate _colors.scss file. While working on our framework, we decided to have a single source of truth storing all the colors and themes. For more information, you can check our article on this topic.

Here is a peek at how button colors are defined in our _colors.scss file:

The fontSmooth mixin is used to improve font rendering when a light text is used on a dark background. It’s quite common to see this style applied to all HTML elements these days. After doing some research, we opted for creating a mixin to target specific elements, rather than including this style in our global _reset.scss file.

Since our framework is supposed to be a customizable starting point for web projects of any kind, I tried not to include any non-essential style. For example, I didn’t include shadows, or :focus effects, because they will differ in each project. Providing a default style would force our framework adopters to search and overwrite things, as opposed to having the freedom to build upon things.

Size variations

In addition to style variations, a buttons system should also include size variations. To be clear: I’m not referring to responsive buttons that adopt at different breakpoints, but to having utility classes to create buttons with different sizes regardless of the viewport size.

A good approach to creating such variations is defining size variables (using the CSS calc() function), and then applying these variables to the size utility classes:

Using icons within buttons

In our article on icons in a design system, we explain how to align icons and text. We can use the same .icon-text-aligner class to align text labels and icons within buttons:

Since we may have a button that does not include text but only an icon, it’s a good idea to target the .icon inside the basic .btn class, and make sure the icon inherits the default color of the button label (even if the label is not there):

Button groups

Another classic use case worth including in a global CSS file is a button group. Luckily, Flexbox makes it easy to lay buttons in a simple one-dimensional layout:

Responsive buttons

If you’ve been following our series on design systems so far, you know our responsive approach relies on two CSS variables: --text-base-size and --space-unit. Updating these variables using media queries creates a cascade effect that affects the entire design system, including buttons.

In our framework, button components, like all other components, are based on em relative units. The current font-size is updated with the --text-base-size variable. Therefore our buttons are already responsive, with no need to create a single media query within the _buttons.scss file.

_buttons.scss

Putting it all together, here’s our global SCSS file for our buttons:

Conclusion

This article marks the end of our CSS-focused series on design systems! All the globals we’ve been writing about will be bundled into a repository and made available for download on Github soon! Together, they represent our first attempt at creating a framework.

Next, we’re going to code a collection of components compatible with the framework. The idea is to provide an arsenal of ready-to-use web modules that developers can copy and paste into their projects. As usual, we’ll keep you posted on the progress on Twitter.

I hope you enjoyed the article! For more web design nuggets, follow us here on Medium or Twitter. 🙌