Component Structure
Guidelines on how to write and structure the CSS of components for the design system.
Principles
- Structured naming: All components should use a prefix and follow the BEM structure.
- Overwritable classes: All classes should be able to be overwritable by TailwindCSS classes.
- Inherited attributes: All attributes should be set by inheriting TailwindCSS classes.
Structured Naming
Prefix
All components should start with a c-
prefix. Components intended to be used on our marketing pages should start with a c_h-
prefix.
/* App */
.c-btn {}
/* Marketing pages */
.c_h-btn {}
BEM
To keep the naming structure consistent, we use the BEM structure (Block, Element, Modifier) for all our design system components.
/* Block */
.c-btn {}
/* Element */
.c-btn__icon {}
/* Modifier */
.c-btn--green {}
/* Element & Modifier */
.c-btn__icon--green
We try to avoid using grandchildren (i.e. name selectors in elements that are 2+ levels deep).
/* Don't */
.c-nav__list {}
.c-nav__list__item {}
/* Do */
.c-nav__list {}
.c-nav__item {}
Overwritable Classes
To keep all design system classes overwritable by default TailwindCSS classes, we strictly keep the specificity score of all classes as low as possible.
Here a few examples of bad practices:
Don't chain classes
Avoid chaining multiple CSS classes if possible to keep specificity low. The :where
pseudo-class function is a good alternative that always keeps specificity at 0.
/* Don't */
.c-btn--red.c-btn--disabled {}
/* Do */
:where(.c-btn--red).c-btn--disabled {}
Don't use HTML tags
Avoid styling HTML tags such as header
or h2
. Also avoid chaining a CSS class with a HTML tag, as this will increase its specificity.
/* Don't */
h2 {}
/* Do */
.c-heading {}
/* Don't */
button.c-btn {}
/* Do */
.c-btn {}
Inherited attributes
To keep components consistent and maintainable, we set all attributes of a class by inheriting TailwindCSS classes using the @apply
directive.
/* Don't */
.c-btn {
backgroundColor: green;
}
/* Do */
.c-btn {
@apply bg-green-500;
}
If an attribute is not available in TailwindCSS, we add it to the tailwind.config.js
or create a custom utility class in the design-system/utilities
folder.
/* Don't */
.c-btn {
transform: translateY(-50%);
}
/* Do */
module.exports = {
theme: {
extend: {
translate: {
"half": "-50%",
}
}
}
}
@layer components {
.c-btn {
@apply -translate-y-half;
}
}
/* Do */
@layer utilities {
.-translate-y-half {
transform: translateY(-50%);
}
}
@layer components {
.c-btn {
@apply -translate-y-half;
}
}