3 min read · Nov 21, 2023
--
Design tokens are a method of abstracting and organizing the design elements of a system into usable and uniform values. By utilizing CSS variables, these tokens promote a more modular and manageable approach to styling for web development.
When building our design system at McAfee, we explored various ways to create sizable collections of tokens, and decided to use ComponentVariantKindModifierProperty
as the most logical structure. This enabled us to have precise control over our components, while also making it simple to find and use them.
Let’s break down each part of this framework:
1. Component: This represents a higher-level UI component, such as a button or any other element in your design system.
2. Variant: Variations of a component might include subtypes or various designs. For example, a button might feature variants like primary, secondary, or tertiary. It’s good practice to not use primary as it is redundant in this formula and adds bloat.
3. Kind: Kinds represent state modifications or contextual variations of a component, such as error, warning, or disabled states.
4. Modifier: Modifiers are additional variations or pseudo-states applied to a component, such as active, pressed, or hovered.
5. Property: This refers to the specific design attribute or property being defined by the design token. Examples include background color, text color, or font size.
Let’s see an example of how this structure might be applied using CSS variables:
:root {
--button-background: #3498db;
--button-color: #ffffff;
--button-error-background: #2ecc71;
--button-error-color: #ffffff;
--button-error-hover-background: #2ecc71;
--button-error-hover-color: #ffffff;
/* secondary */
--button-secondary-background: #2ecc71;
--button-secondary-color: #ffffff;
--button-secondary-error-background: #2ecc71;
--button-secondary-error-color: #ffffff;
--button-secondary-error-hover-background: #2ecc71;
--button-secondary-error-hover-color: #ffffff;
/* … other design tokens */
}
Benefits of Using this Structure:
1. Consistency and Reusability: Design tokens provide a single source of truth for styling, providing a consistent look and feel throughout the application. Reusable tokens make it easy to maintain and update styles.
2. Modularity: The structured approach allows for easy modification of individual components, variants, or states without affecting the entire system.
3. Maintainability: with a clear naming convention and organization, it’s easier to understand, document, and maintain the design system over time.
4. Adaptability: Design tokens make it simpler to adapt the design system to different themes or styles by adjusting the values of the tokens.
Integration with BEM:
BEM and design tokens work together to create an efficient system. BEM’s naming conventions fit perfectly with the components, variants, kind, and modifiers found in design tokens, allowing for the creation of modular and easily maintainable styles.
For example, in the CSS snippet above, BEM classes are used to define different button states and variations, and the corresponding design tokens are applied within these BEM blocks.
/* Example usage with BEM syntax */
.button {
/* default button */
background: var(--button-background);
color: var(--button-color); &--secondary {
/* button secondary */
background: var(--button-secondary-background);
color: var(--button-secondary-color);
&:hover {
background: var(--button-secondary-hover-background);
color: var(--button-secondary-hover-color);
}
&--error {
/* button secondary error */
background: var(--button-secondary-error-background);
color: var(--button-secondary-error-color);
&:hover {
/* button secondary error hover */
background: var(--button-secondary-error-hover-background);
color: var(--button-secondary-error-hover-color);
}
}
}
&--error {
/* Error state styles */
background: var(--button-error-background);
color: var(--button-error-color);
}
&:active {
/* Active state styles */
background: var(--button-active-background);
color: var(--button-active-color);
}
/* … other styles */
}
We decided that this approach was the best fit for elements with various states, allowing us to accurately manage each one. Even though it involves a lot of coding and repetition at first, the advantages outweigh the other aspects.
Summary
Using design tokens alongside a named convention and BEM syntax helps to organize, remain consistent, and maintain your web project or design system’s look. This is an awesome way of guaranteeing that developers and designers can easily understand the variables in a practical manner without having to spend time searching for them.