You might have used style frameworks in the past like Bootstrap or Bulma. Most of these types of libraries provide utility classes you can easily use in your HTML layouts, such as ml-10
for left margin, or pr-5
for right padding. One way of doing this is with a super long file and repetitive class declarations. Not very readable or scalable though is it?
In this article, we'll dive into making our own utility style file with scss, using some cool scss magic you might not have used before. In our example we'll be working with margin
, but you could easily reproduce with any properties you like! The way we do this is flexible -- you provide the values for your classes (instead of mapping 1-100 for example).
Let's make a new .scss
file
Pretty easy. I'll let you decide on how you want to do this.
Tip: you can structure your scss files similarly to JS files and make it super readable! I love using index.scss files to group imports within a folder, then having the parent import the index file.
Let's set up some variables
We're going to need 4 variables (a couple are optional):
auto
(optional) - good practice to extract constants to variables. This is used to hold the auto value.
directions
- an array of strings, to cover the 4 different directions our margin could be (top, bottom, left, right)
css-property-map
(optional) - A scss map to map our directions above to CSS properties. SCSS maps work similarly to JS, with a key/value. I use this because I want my utility classes to be shorthand/small in size. You could avoid this by having the full direction in your class.
sizes
: an array of CSS values. These are the utility classes/values we want to generate. I've also included an auto
value which gets handled separately as it's not a standard px
value.
$auto: auto;
$directions: 't', 'b', 'l', 'r';
$css-property-map: ('t': margin-top, 'b': margin-bottom, 'l': margin-left, 'r': margin-right);
$sizes: 0, 5, 10, 20, 30, 40, 50, 60, 100, $auto;
And now some loops
We set up a couple of dynamic loops (think for each
loop in JS). This will give us all sizes for each direction.
@each $direction in $directions {
@each $size in $sizes {
// Classes coming here
}
}
Generate the actual utility class
We dynamically create CSS classes for each direction/size combo. This will give us the classes in a .ml-5
format.
@each $direction in $directions {
@each $size in $sizes {
.m#{$direction}-#{$size} {
// CSS property/values coming here
}
}
}
Setup the CSS properties and values
We compare the size to our previously defined auto
value. If it's auto
, we don't need to build a px
value.
#{map-get($css-property-map, $direction)}
let's us build dynamic CSS properties. Let's deep dive into what each bit means:
#{}
- inject an SCSS variable into CSSmap-get(map, key)
- pull out a value from a specific map with the passed key
@if $size == $auto {
#{map-get($css-property-map, $direction)}: $auto;
} @else {
#{map-get($css-property-map, $direction)}: #{$size}px;
}
Complete util code
$auto: auto;
$directions: 't', 'b', 'l', 'r';
$css-property-map: ('t': margin-top, 'b': margin-bottom, 'l': margin-left, 'r': margin-right);
$sizes: 0, 5, 10, 20, 30, 40, 50, 60, 100, $auto;
@each $direction in $directions {
@each $size in $sizes {
.m#{$direction}-#{$size} {
@if $size == $auto {
#{map-get($css-property-map, $direction)}: $auto;
} @else {
#{map-get($css-property-map, $direction)}: #{$size}px;
}
}
}
}
Top comments (0)