Preface
Goal: Generate custom color classes step by step, utilizing lessjs guard capability to achieve conditional if-then-else.
Even when utilizing CSS Framework, theme making require to create custom CSS. One of my need is color class helper, porting from materialize color. Materialize CSS’s color is so complete, something that is not available in Semantic UI. This spacing Class can be made utilizing LessJS.
These guidance will save you a lot of coding time. And also tons of typing.
Example Case
GMC: Sass to Less
This article will port google materialize color, from sass to its less counterpart.
Reading
This article require loop knowledge that you can read on
1: Shade: Basic
Consider start from the very basic case
SASS Source
Materialize has this special colors.
The process is so simple that it is only use each
.
-
- /colors/sass/01-shade.scss
- gitlab.com/…/colors/sass/01-shade.scss.
$shades: (
"black": #000000,
"white": #FFFFFF,
"transparent": transparent
);
// Shade classes
@each $color, $color_value in $shades {
.#{$color} {
background-color: $color_value !important;
}
.#{$color}-text {
color: $color_value !important;
}
}
LESS Port
The less
counterpart is also simple.
-
- /colors/less/01-shade.less
- gitlab.com/…/colors/less/01-shade.less.
@shades: {
black: #000000;
white: #FFFFFF;
transparent: transparent
}
each(@shades, {
.@{key}{
background-color: @value !important;
}
.@{key}-text {
color: @value !important;
}
})
CSS Output
Materialize has two CSS selectors
-
Background, using
color
as selector, and -
Foreground, using
color-text
as selector.
The result can be shown as below code:
-
- /colors/less/01-shade.css
- gitlab.com/…/colors/less/01-shade.css.
.black {
background-color: #000000 !important;
}
.black-text {
color: #000000 !important;
}
.white {
background-color: #FFFFFF !important;
}
.white-text {
color: #FFFFFF !important;
}
.transparent {
background-color: transparent !important;
}
.transparent-text {
color: transparent !important;
}
Thus with three colors, we have six CSS rules.
2: One Color: Simple
Consider, use the real color. It is very similar to above script.
SASS Source
I simplified the complex SASS from materialize CSS.
-
- /colors/sass/02-color.scss
- gitlab.com/…/colors/sass/02-color.scss.
$red: (
"base": #F44336,
"lighten-2": #E57373,
"lighten-1": #EF5350,
);
$color_name: "red";
$color: $red;
@each $color_type, $color_value in $color {
.#{$color_name}.#{$color_type} {
background-color: $color_value !important;
}
.#{$color_name}-text.text-#{$color_type} {
color: $color_value !important;
}
}
LESS Port
The port is also very straightforward.
-
- /colors/less/02-color.less
- gitlab.com/…/colors/less/02-color.less.
@red: {
base: #F44336;
lighten-2: #E57373;
lighten-1: #EF5350;
}
@color_name: red;
@color: @red;
each(@color, {
.@{color_name}.@{key} {
background-color: @value !important;
}
.@{color_name}-text.text-@{key} {
color: @value !important;
}
})
CSS Output
Notice that the output is still using .red.base {…}.
-
- /colors/less/02-color.css
- gitlab.com/…/colors/less/02-color.css.
.red.base {
background-color: #F44336 !important;
}
.red-text.text-base {
color: #F44336 !important;
}
.red.lighten-2 {
background-color: #E57373 !important;
}
.red-text.text-lighten-2 {
color: #E57373 !important;
}
.red.lighten-1 {
background-color: #EF5350 !important;
}
.red-text.text-lighten-1 {
color: #EF5350 !important;
}
3: One Color: Conditional
Now comes the hard part. We will output .red {…}, instead of .red.base {…}.
Issue: LessJS does not have if then else rules.
SASS Source
Consider have a look at this SASS source first, so that you will have the idea.
-
- /colors/sass/03-conditional.scss
- gitlab.com/…/colors/sass/03-conditional.scss.
$red: (
"base": #F44336,
"lighten-2": #E57373,
"lighten-1": #EF5350,
);
$color_name: "red";
$color: $red;
@each $color_type, $color_value in $color {
@if $color_type == "base" {
.#{$color_name} {
background-color: $color_value !important;
}
.#{$color_name}-text {
color: $color_value !important;
}
}
@else {
.#{$color_name}.#{$color_type} {
background-color: $color_value !important;
}
.#{$color_name}-text.text-#{$color_type} {
color: $color_value !important;
}
}
}
LESS Guard
Luckily we have guard
in LESS.
each(@color, {
@is-base: boolean(@key = base);
& when (@is-base = true) {
...
}
& when (@is-base = false) {
...
}
})
Notice, that first we need to define the truth:
- @is-base: boolean(@key = base).
It needs more steps compared to SASS counterpart, but at least it works well.
LESS Port
The complete guard code is as below:
-
- /colors/less/03-conditional.less
- gitlab.com/…/colors/less/03-conditional.less.
@red: {
base: #F44336;
lighten-2: #E57373;
lighten-1: #EF5350;
}
@color_name: red;
@color: @red;
each(@color, {
@is-base: boolean(@key = base);
& when (@is-base = true) {
.@{color_name} {
background-color: @value !important;
}
.@{color_name}-text {
color: @value !important;
}
}
& when (@is-base = false) {
.@{color_name}.@{key} {
background-color: @value !important;
}
.@{color_name}-text.text-@{key} {
color: @value !important;
}
}
})
CSS Output
Notice that now, We have .red {…}, instead of .red.base {…}.
-
- /colors/less/03-conditional.css
- gitlab.com/…/colors/less/03-conditional.css.
.red {
background-color: #F44336 !important;
}
.red-text {
color: #F44336 !important;
}
.red.lighten-2 {
background-color: #E57373 !important;
}
.red-text.text-lighten-2 {
color: #E57373 !important;
}
.red.lighten-1 {
background-color: #EF5350 !important;
}
.red-text.text-lighten-1 {
color: #EF5350 !important;
}
Mission accomplished, but consider move to this next issue.
4: Many Colors
Nested each can be an issue in lessjs
,
because nested use variable with the same name: @key
and @value
.
But this also can be solved by separating the inner part in a function.
SASS Source
Consider see the original source frome Materialize CSS.
-
- /colors/sass/04-colors.scss
- gitlab.com/…/colors/sass/04-colors.scss.
$red: (
"base": #F44336,
"lighten-2": #E57373,
"lighten-1": #EF5350,
);
$blue: (
"base": #2196F3,
"lighten-2": #64B5F6,
"lighten-1": #42A5F5,
);
$colors: (
"red": $red,
"blue": $blue
);
@each $color_name, $color in $colors {
@each $color_type, $color_value in $color {
@if $color_type == "base" {
.#{$color_name} {
background-color: $color_value !important;
}
.#{$color_name}-text {
color: $color_value !important;
}
}
@else if $color_name != "shades" {
.#{$color_name}.#{$color_type} {
background-color: $color_value !important;
}
.#{$color_name}-text.text-#{$color_type} {
color: $color_value !important;
}
}
}
}
LESS Nested Each
The skeleton is as simple as code below:
.foo_color(@color_name, @color) {
each(@color, {
...
})
}
each(@colors, {
.foo_color(@key, @value)
})
LESS Port
But the real code is actually, a little bit longer.
-
- /colors/less/04-colors.less
- gitlab.com/…/colors/less/04-colors.less.
@red: {
base: #F44336;
lighten-2: #E57373;
lighten-1: #EF5350;
}
@blue: {
base: #2196F3;
lighten-2: #64B5F6;
lighten-1: #42A5F5;
}
@colors: {
red: @red;
blue: @blue;
}
.foo_color(@color_name, @color) {
each(@color, {
@is-base: boolean(@key = base);
& when (@is-base = true) {
.@{color_name} {
background-color: @value !important;
}
.@{color_name}-text {
color: @value !important;
}
}
& when (@is-base = false) {
.@{color_name}.@{key} {
background-color: @value !important;
}
.@{color_name}-text.text-@{key} {
color: @value !important;
}
}
})
}
each(@colors, {
.foo_color(@key, @value)
})
CSS Output
Now the CSS result.
-
- /colors/less/04-colors.css
- gitlab.com/…/colors/less/04-colors.css.
.red {
background-color: #F44336 !important;
}
.red-text {
color: #F44336 !important;
}
.red.lighten-2 {
background-color: #E57373 !important;
}
.red-text.text-lighten-2 {
color: #E57373 !important;
}
.red.lighten-1 {
background-color: #EF5350 !important;
}
.red-text.text-lighten-1 {
color: #EF5350 !important;
}
.blue {
background-color: #2196F3 !important;
}
.blue-text {
color: #2196F3 !important;
}
.blue.lighten-2 {
background-color: #64B5F6 !important;
}
.blue-text.text-lighten-2 {
color: #64B5F6 !important;
}
.blue.lighten-1 {
background-color: #42A5F5 !important;
}
.blue-text.text-lighten-1 {
color: #42A5F5 !important;
}
What is Next ?
Beside this conditional
, there is also loop
article, that you might need to read.
Consider going back reading [ Less - Loop - Spacing Class ].
Thank you for reading.
Conclusion
These color classes is ready to serve.
What do you think ?