Creating Utility Classes with Design Tokens using Sass
On This Page:
At the start of a Design System, there’s a chance that things can move pretty fast.
There may be more than one or two people working on creating components (if you’re lucky). You might want to prototype things quickly with “throwaway code”. When it matures there may be certain use cases where you need a slight adjustment here and there for a particular component to work, or you may not be able to include the components you need as you would hope to.
After creating a set of Design Tokens for my clients Design System I looked at how best we can quickly create some additional utility classes for the various “exceptions to the rule” mentioned above. We needed something that would work automatically, programatically, and with as little human interaction as possible once it was set up.
Using Sass in 2019
The project was already using Sass (a decision that was made after some research (that might be another article, whenever I find the time)) and I have previously used loops and interpolation so I knew we could create these classes with a pre-processor language that is already in place without resorting to something else, an extra dependency.
As we’re using Sass already we are outputting the Design Tokens using Theo to generate files of Sass variables and maps that are needed.
To create our utility classes we would need a Sass @mixin that would use the class selector to inform the initial naming of the created rule sets. An @each rule to loop through the Sass maps, and an additional $prefix
variable to allow us to create classnames.
Design Tokens and Maps
Theo takes your Design Tokens that can be authored in a .yml
or .json
format and then can convert them into a Sass map, amongst a lot of other formats.
An example Sass map that we are going to use could look something like this:
Creating the @each loop
In the above map with have the key/value pair of the name of the colour and the hex code that represents it. To create an @each
rule we would need to write something like:
Using the @each
rule we go through key/value pairs of $ds-colors-map
and get the key: $name
and the value: $hex
. We then use these variables to create the declaration inside the rule. This @each
rule makes use of interpolation to turn the $name
variable into property inside the declaration.
But this would only create a list of CSS colour rules within the ruleset like:
What we want is to generate individual class selectors to hold each key/value pair.
Making the @mixin
To get Sass to generate the utility classes for our Design Tokens using the Sass maps. We need to create a @mixin
and slightly change the @each
rule. Before we look into that we should think about the structure of the class selectors we are wanting to create. Using colour as the example I want to create a set of CSS rules that look like this:
With a @mixin
we need to be able to create part of the selector
of a rule so that it include --
. We also need the correct key: $name
as part of the selector
, and value: $hex
as the declarations value
.
We can make use of Sass’ interpolation to help us with this, so that we can generate the correct naming conventions for the class selectors. Inside the @mixin
we can add our working @each
rule like this:
When called this @mixin
will go through the $ds-colors-map
we have and generate a class selector using the parent selector name using the &
, we add the --
to then separate the parent selector from the key: $name
of the pair in the map and then print the value: $hex
as the value in the declaration. When invoked in a class like:
We get an compiled output like:
Extending the @mixin
That works great but it’s not very flexible. I want to generate rules for each way colour can be used in CSS. Not only for text but for borders and backgrounds like this:
To do this we can modify the @mixin
we have created to allow us to set the property
that would be inside the declaration. We need to add an argument to our @mixin
that will set this property and then use that argument where needed. As it’s the property
of the declaration that is needs to be changed we can add a it to our @mixin
along with a default so the first line is like:
We then need to use that $property
argument as our property in the declaration using interpolation, so that the whole @mixin
looks like this:
Doing this allows us to include the @mixin
in the 3 types of colour classes we want to create:
Which will generate the a list of rules like I have mentioned above.
What next?
Now we can create an individual rule for each of the colours that our Design Tokens has for text, background and border but Design Tokens are more than colour. With a few modifications to the @mixin
created here we can then do this with any typographic styles and spacing values we have.
I created a CodePen that includes the @mixins
that can be used to create those additional utility classes.
See the Pen Utility Class Sass Generators by Stuart Robson (@sturobson) on CodePen.