Preface
Goal: Generate custom spacing classes step by step, utilizing sass loop capability.
Even when utilizing CSS Framework,
theme making require to create custom CSS.
One of my need is spacing class, that is not available
in neither Bulma nor Materialize.
This spacing class can be made utilizing SASS
.
These guidance will save you a lot of coding time. And also tons of typing.
Reading
Basic Loop:
Most code below is inspired by:
Another reading:
CSS Preprocessor
SASS/SCSS is one alternative among CSS preprocessor family.
1: @for
Imagine that we need a sequence of classes to handle margin, similar like CSS below:
.m-1 {
margin: 1px;
}
This can be achieved with this loop constructor
@for ... from ... through ... {
...
}
CSS Class Naming
We want to achieve this class naming
- .m-#{$number}
SASS Source
For comfort reason, we also need to define intial value for the loop.
-
- /spacing-scss/sass/01-for.scss
- gitlab.com/…/spacing-scss/sass/01-for.scss.
// variable initialization
$loop-begin: 1 !default;
$loop-stop: 3 !default;
// loop
@for $cursor from $loop-begin through $loop-stop {
.m-#{$cursor} {
margin: #{$cursor}px;
}
}
Variable Interpolation
Inside the loop we have this #{…} code. This is variable interpolation.
We use variable interpolation, when we want to extract value into the css.
CSS Result
The #{$cursor} variable takes care the rest, so now we have this result below:
-
- /spacing-scss/css/01-for.scss
- gitlab.com/…/spacing-scss/css/01-for.css.
.m-1 {
margin: 1px;
}
.m-2 {
margin: 2px;
}
.m-3 {
margin: 3px;
}
Limitation
The issue with @for is we cannot use interval. We can have this [1, 2, 3, 4, 5] sequence. But we cannot have this [5, 10, 15, 20, 25] sequence.
2: @while
To solve [5, 10, 15, 20, 25] sequence, we can utilize @while.
$cursor: $loop-begin;
@while $cursor <= $loop-end {
...
$cursor: $cursor + $interval;
}
CSS Class Naming
We still want to achieve this class naming
- .m-#{$number}
SASS Source
Consider this @while loop below:
-
- /spacing-scss/sass/02-while.scss
- gitlab.com/…/spacing-scss/sass/02-while.scss.
// variable initialization
$loop-begin: 5 !default;
$loop-end: 25 !default;
$interval: 5 !default;
// loop
$cursor: $loop-begin;
@while $cursor <= $loop-end {
.m-#{$cursor} {
margin: #{$cursor}px;
}
$cursor: $cursor + $interval;
}
CSS Result
-
- /spacing-scss/css/02-while.scss
- gitlab.com/…/spacing-scss/css/02-while.css.
.m-5 {
margin: 5px;
}
.m-10 {
margin: 10px;
}
.m-15 {
margin: 15px;
}
.m-20 {
margin: 20px;
}
.m-25 {
margin: 25px;
}
3: @each
Before facing complex situation, consider a simple example.
Challenge
Now we have challenge that margin property has these variants:
-
margin,
-
margin-top,
-
margin-bottom,
-
margin-left,
-
margin-right
For simplicity reason, I exclude the original margin variant.
CSS Class Naming
We want to achieve this class naming
- .m-#{$side}-5
List Declaration
Sass variable can handle a list.
$sides: (top, bottom, left, right);
Accessing List
This list can be accessed by using @each iterator.
@each ... in ... {
...
}
SASS Source
Consider accessing $sides by this example below:
-
- /spacing-scss/sass/03-each.scss
- gitlab.com/…/spacing-scss/sass/03-each.scss.
// property
$sides: (top, bottom, left, right);
@each $side in $sides {
.m-#{$side}-5 {
margin-#{$side}: 5px;
}
}
CSS Result
Now we have this:
-
- /spacing-scss/css/03-each.scss
- gitlab.com/…/spacing-scss/css/03-each.css.
.m-top-5 {
margin-top: 5px;
}
.m-bottom-5 {
margin-bottom: 5px;
}
.m-left-5 {
margin-left: 5px;
}
.m-right-5 {
margin-right: 5px;
}
This is ugly, because we want .m-t-5, instead of .m-top-5.
4: @each with Pairs
Sass has solution for this issue.
CSS Class Naming
We want to achieve this class naming
- .m-#{$abbreviation}-5
List Declaration
Luckily, sass allow us to have pairs in list. Now we have CSS sub-property as below:
$sides: (top: t, bottom: b, left: l, right: r);
SASS Source
Consider rewrite previous code.
-
- /spacing-scss/sass/04-each-pairs.scss
- gitlab.com/…/spacing-scss/sass/04-each-pairs.scss.
// property: abbreviation
$sides: (top: t, bottom: b, left: l, right: r);
@each $side, $name in $sides {
.m-#{$name}-5 {
margin-#{$side}: 5px;
}
}
CSS Result
Now we have what wee need.
-
- /spacing-scss/css/04-each-pairs.scss
- gitlab.com/…/spacing-scss/css/04-each-pairs.css.
.m-t-5 {
margin-top: 5px;
}
.m-b-5 {
margin-bottom: 5px;
}
.m-l-5 {
margin-left: 5px;
}
.m-r-5 {
margin-right: 5px;
}
Notice that I use .m-t-5, instead of .mt-5, to differ from bootstrap spacing classes.
5: @each in @while
Consider leverage to a more complex situation. We need a sequence of each classes.
CSS Class Naming
We want to achieve this class naming
- .m-#{$subname}-#{$number}
Skeleton
We put @each iterator inside @while loop.
@while $cursor <= $loop-end {
@each $side, $name in $sides {
...
}
$cursor: $cursor + $interval;
}
SASS Source
-
- /spacing-scss/sass/05-while-each-pairs.scss
- gitlab.com/…/spacing-scss/sass/05-while-each-pairs.scss.
// variable initialization
$loop-begin: 5 !default;
$loop-end: 25 !default;
$interval: 5 !default;
// sub-property: abbreviation
$sides: (top: t, bottom: b, left: l, right: r);
// loop
$cursor: $loop-begin;
@while $cursor <= $loop-end {
@each $side, $name in $sides {
.m-#{$name}-#{$cursor} {
margin-#{$side}: #{$cursor}px;
}
}
$cursor: $cursor + $interval;
}
CSS Result
-
- /spacing-scss/css/05-while-each-pairs.css
- gitlab.com/…/spacing-scss/css/05-while-each-pairs.css.
.m-t-5 {
margin-top: 5px;
}
.m-b-5 {
margin-bottom: 5px;
}
.m-l-5 {
margin-left: 5px;
}
.m-r-5 {
margin-right: 5px;
}
.m-t-10 {
margin-top: 10px;
}
.m-b-10 {
margin-bottom: 10px;
}
.m-l-10 {
margin-left: 10px;
}
.m-r-10 {
margin-right: 10px;
}
.m-t-15 {
margin-top: 15px;
}
.m-b-15 {
margin-bottom: 15px;
}
.m-l-15 {
margin-left: 15px;
}
.m-r-15 {
margin-right: 15px;
}
.m-t-20 {
margin-top: 20px;
}
.m-b-20 {
margin-bottom: 20px;
}
.m-l-20 {
margin-left: 20px;
}
.m-r-20 {
margin-right: 20px;
}
.m-t-25 {
margin-top: 25px;
}
.m-b-25 {
margin-bottom: 25px;
}
.m-l-25 {
margin-left: 25px;
}
.m-r-25 {
margin-right: 25px;
}
6: Nested @while
CSS Class Naming
We want to achieve this class naming
- .#{$name}-#{$subname}-#{$number}
List Declaration
We define CSS property list:
-
property: margin and padding
-
each has sub-property: top, bottom, left, right.
$sides: (top: t, bottom: b, left: l, right: r);
$properties: (margin: m, padding: p);
Skeleton
We put both @each iterator, inside @while loop.
@while $cursor <= $loop-end {
@each $prop, $name in $properties {
@each $side, $subname in $sides {
...
}
}
$cursor: $cursor + $interval;
}
SASS Source
-
- /spacing-scss/sass/06-while-each-pairs.scss
- gitlab.com/…/spacing-scss/sass/06-while-each-pairs.scss.
// variable initialization
$loop-begin: 5 !default;
$loop-end: 25 !default;
$interval: 5 !default;
// sub-property: abbreviation
$sides: (top: t, bottom: b, left: l, right: r);
$properties: (margin: m, padding: p);
// loop
$cursor: $loop-begin;
@while $cursor <= $loop-end {
@each $prop, $name in $properties {
@each $side, $subname in $sides {
.#{$name}-#{$subname}-#{$cursor} {
#{$prop}-#{$side}: #{$cursor}px;
}
}
}
$cursor: $cursor + $interval;
}
CSS Result
Now we have both margin and padding.
-
- /spacing-scss/css/06-while-each-pairs.css
- gitlab.com/…/spacing-scss/css/06-while-each-pairs.css.
.m-t-5 {
margin-top: 5px;
}
.m-b-5 {
margin-bottom: 5px;
}
.m-l-5 {
margin-left: 5px;
}
.m-r-5 {
margin-right: 5px;
}
.p-t-5 {
padding-top: 5px;
}
.p-b-5 {
padding-bottom: 5px;
}
.p-l-5 {
padding-left: 5px;
}
.p-r-5 {
padding-right: 5px;
}
.m-t-10 {
margin-top: 10px;
}
.m-b-10 {
margin-bottom: 10px;
}
.m-l-10 {
margin-left: 10px;
}
.m-r-10 {
margin-right: 10px;
}
.p-t-10 {
padding-top: 10px;
}
.p-b-10 {
padding-bottom: 10px;
}
.p-l-10 {
padding-left: 10px;
}
.p-r-10 {
padding-right: 10px;
}
.m-t-15 {
margin-top: 15px;
}
.m-b-15 {
margin-bottom: 15px;
}
.m-l-15 {
margin-left: 15px;
}
.m-r-15 {
margin-right: 15px;
}
.p-t-15 {
padding-top: 15px;
}
.p-b-15 {
padding-bottom: 15px;
}
.p-l-15 {
padding-left: 15px;
}
.p-r-15 {
padding-right: 15px;
}
.m-t-20 {
margin-top: 20px;
}
.m-b-20 {
margin-bottom: 20px;
}
.m-l-20 {
margin-left: 20px;
}
.m-r-20 {
margin-right: 20px;
}
.p-t-20 {
padding-top: 20px;
}
.p-b-20 {
padding-bottom: 20px;
}
.p-l-20 {
padding-left: 20px;
}
.p-r-20 {
padding-right: 20px;
}
.m-t-25 {
margin-top: 25px;
}
.m-b-25 {
margin-bottom: 25px;
}
.m-l-25 {
margin-left: 25px;
}
.m-r-25 {
margin-right: 25px;
}
.p-t-25 {
padding-top: 25px;
}
.p-b-25 {
padding-bottom: 25px;
}
.p-l-25 {
padding-left: 25px;
}
.p-r-25 {
padding-right: 25px;
}
7: Final
Now comes the final result.
CSS Class Naming
We want to achieve both class naming
-
.#{$name}-#{$number}
-
.#{$name}-#{$subname}-#{$number}
Skeleton
We put both @each iterator, inside @while loop.
@while $cursor <= $loop-end {
@each $prop, $name in $properties {
...
@each $side, $subname in $sides {
...
}
}
$cursor: $cursor + $interval;
}
SASS Source
-
- /spacing-scss/sass/07-final.scss
- gitlab.com/…/spacing-scss/sass/07-final.scss.
// variable initialization
$loop-begin: 5 !default;
$loop-end: 25 !default;
$interval: 5 !default;
// sub-property: abbreviation
$sides: (top: t, bottom: b, left: l, right: r);
$properties: (margin: m, padding: p);
// loop
$cursor: $loop-begin;
@while $cursor <= $loop-end {
@each $prop, $name in $properties {
.#{$name}-#{$cursor} {
#{$prop}: #{$cursor}px !important;
}
@each $side, $subname in $sides {
.#{$name}-#{$subname}-#{$cursor} {
#{$prop}-#{$side}: #{$cursor}px !important;
}
}
}
$cursor: $cursor + $interval;
}
Notice that I also put !important in css value.
CSS Result
-
- /spacing-scss/css/07-final.css
- gitlab.com/…/spacing-scss/css/07-final.css.
.m-5 {
margin: 5px !important;
}
.m-t-5 {
margin-top: 5px !important;
}
.m-b-5 {
margin-bottom: 5px !important;
}
.m-l-5 {
margin-left: 5px !important;
}
.m-r-5 {
margin-right: 5px !important;
}
.p-5 {
padding: 5px !important;
}
.p-t-5 {
padding-top: 5px !important;
}
.p-b-5 {
padding-bottom: 5px !important;
}
.p-l-5 {
padding-left: 5px !important;
}
.p-r-5 {
padding-right: 5px !important;
}
.m-10 {
margin: 10px !important;
}
.m-t-10 {
margin-top: 10px !important;
}
.m-b-10 {
margin-bottom: 10px !important;
}
.m-l-10 {
margin-left: 10px !important;
}
.m-r-10 {
margin-right: 10px !important;
}
.p-10 {
padding: 10px !important;
}
.p-t-10 {
padding-top: 10px !important;
}
.p-b-10 {
padding-bottom: 10px !important;
}
.p-l-10 {
padding-left: 10px !important;
}
.p-r-10 {
padding-right: 10px !important;
}
.m-15 {
margin: 15px !important;
}
.m-t-15 {
margin-top: 15px !important;
}
.m-b-15 {
margin-bottom: 15px !important;
}
.m-l-15 {
margin-left: 15px !important;
}
.m-r-15 {
margin-right: 15px !important;
}
.p-15 {
padding: 15px !important;
}
.p-t-15 {
padding-top: 15px !important;
}
.p-b-15 {
padding-bottom: 15px !important;
}
.p-l-15 {
padding-left: 15px !important;
}
.p-r-15 {
padding-right: 15px !important;
}
.m-20 {
margin: 20px !important;
}
.m-t-20 {
margin-top: 20px !important;
}
.m-b-20 {
margin-bottom: 20px !important;
}
.m-l-20 {
margin-left: 20px !important;
}
.m-r-20 {
margin-right: 20px !important;
}
.p-20 {
padding: 20px !important;
}
.p-t-20 {
padding-top: 20px !important;
}
.p-b-20 {
padding-bottom: 20px !important;
}
.p-l-20 {
padding-left: 20px !important;
}
.p-r-20 {
padding-right: 20px !important;
}
.m-25 {
margin: 25px !important;
}
.m-t-25 {
margin-top: 25px !important;
}
.m-b-25 {
margin-bottom: 25px !important;
}
.m-l-25 {
margin-left: 25px !important;
}
.m-r-25 {
margin-right: 25px !important;
}
.p-25 {
padding: 25px !important;
}
.p-t-25 {
padding-top: 25px !important;
}
.p-b-25 {
padding-bottom: 25px !important;
}
.p-l-25 {
padding-left: 25px !important;
}
.p-r-25 {
padding-right: 25px !important;
}
Now you can use this spacing sass in your project.
8: Update: XY
For practical reason, I have to update this article.
-
Using .sass instead of .scss.
-
Start form zero .0, instead of 5.
-
Consider X, and Y just like bootstrap.
.m-y-5 {
margin-top: 5px !important;
margin-bottom: 5px !important;
}
.m-x-5 {
margin-left: 5px !important;
margin-right: 5px !important;
}
The drawback is, I have bigger stylesheet size.
List Declaration
Luckily, sass allow us to have pairs in list. Now we have CSS sub-property as below:
$sides: (top: t, bottom: b, left: l, right: r)
$sidesy: (top, bottom)
$sidesx: (left, right)
$properties: (margin: m, padding: p)
And the loop is a little bit different:
// loop
$cursor: $loop-begin
@while $cursor <= $loop-end
@each $prop, $name in $properties
.#{$name}-y-#{$cursor}
@each $side in $sidesy
#{$prop}-#{$side}: #{$cursor}px !important
.#{$name}-x-#{$cursor}
@each $side in $sidesx
#{$prop}-#{$side}: #{$cursor}px !important
$cursor: $cursor + $interval
SASS Source
-
- /spacing-scss/sass/08-final-xy.sass
- gitlab.com/…/spacing-scss/sass/08-final-xy.sass.
// variable initialization
$loop-begin: 0 !default
$loop-end: 25 !default
$interval: 5 !default
// sub-property: abbreviation
$sides: (top: t, bottom: b, left: l, right: r)
$sidesy: (top, bottom)
$sidesx: (left, right)
$properties: (margin: m, padding: p)
// loop
$cursor: $loop-begin
@while $cursor <= $loop-end
@each $prop, $name in $properties
.#{$name}-#{$cursor}
#{$prop}: #{$cursor}px !important
@each $side, $subname in $sides
.#{$name}-#{$subname}-#{$cursor}
#{$prop}-#{$side}: #{$cursor}px !important
.#{$name}-y-#{$cursor}
@each $side in $sidesy
#{$prop}-#{$side}: #{$cursor}px !important
.#{$name}-x-#{$cursor}
@each $side in $sidesx
#{$prop}-#{$side}: #{$cursor}px !important
$cursor: $cursor + $interval
Conclusion
These spacing classes is ready to serve.
What do you think ?