user2680673
user2680673

Reputation: 35

Can you partial match classes in Less?

I am new to less and would like to do a partial match with classes to pre-process the CSS without writing a bunch of redundant classes.

e.g. Less:

@blue: #1f6ea9;
@white: #f5f5f5;

.square(@size, @color) {
    width: @size;
    height: @size;
    background-color: @color;
}

CSS:

div[class^="square-"] {
    div[class*="-150"] {
        div[class*="-white"] {
            .square(150px, @white);
        }

        div[class*="-blue"] {
            .square(150px, @white);
        }
    }

    div[class*="-200"] {
        div[class*="-white"] {
            .square(200px, @white);
        }

        div[class*="-blue"] {
            .square(200px, @white);
        }
    }
}

HTML:

<div class="square-150-white"></div>
<div class="square-200-blue"></div>
<div class="square-250-blue"></div> // this would not work

Doing it this way seems like it can get convoluted very easily, and is not dynamic or manageable. Ideally I would like to define one primary, so perhaps we have .square() and .circle(). Then take the rest of the class to define the variables passed to that function.

div[class^="square-"](@size, @color) {
    .square(@size, @color);
}

div[class^="circle-"](@size, @color) {
    .circle(@size, @color);
}

<div class="circle-150"></div>       // generate 150px circle, default color
<div class="circle-300-blue"></div>  // generate 300px blue circle
<div class="square-blue"></div>      // generate blue square, default size
<div class="square-50-white"></div>  // generate 50px white square

Any help on this matter is appreciated.

Upvotes: 1

Views: 413

Answers (2)

jgawrych
jgawrych

Reputation: 3541

I think you may be over engineering. One strength of CSS is to have different styles that can be combined, rather than doing all the combinations by less functions. Lets say you have 3 shapes, 3 dimensions, and 3 colors. Using plain old css, this would require 9 selectors with rules:

.square  { border-radius: 0; }
.rounded { border-radius: 5px; }
.oval    { border-radius: 50%; }

.dim-150 { width: 150px; height: 150px; }
.dim-200 { width: 200px; height: 200px; }
.dim-250 { width: 250px; height: 250px; }

.bg-red   { background-color: #ff2020; }
.bg-white { background-color: #f5f5f5; }
.bg-blue  { background-color: #1f6ea9; }

If we were to create 3 less functions, then generated the combinations, we would have 3^3 = 27 rules (not including the functions themselves). It becomes an exponential problem. Just adding 1 shape, 1 dimension, and 1 color would come up with 256 rules, yet separating the pieces would be 12 rules!


Another idea to consider that when naming classes, authors are encouraged to describe the content, rather than the presentation of the content.[1][2] The idea is that in the future, styles are more likely to change than the classes.

For example, Lets say you had a notification that was red and an oval. You could give it the class="oval bg-red" classes. But what if you later wanted to make these notifications yellow, and a rounded square? You could modify the css, but then the class name wouldn't match the style (.bg-red giving a yellow background), and other elements who reuse the same class would change color without you desiring so. That wouldn't work, so you would have to go to every place on your site in the HTML and change the classes.

Instead, what if we gave the notification the class="notification warning" classes. Notification now describes all notifications on the site, and warning describes all of your warnings. At first you want to change them from oval to square, so you modify the single css rule. You decided to repalette your site, and change all warnings from red to yellow, with the one rule. I believe the same should go for less variables. Instead of @blue, @white which wouldn't make sense to ever change, make them @accept-color, @bg-theme, etc.

Upvotes: 1

Sachin
Sachin

Reputation: 978

You could do it like this in less

LESS:

@blue: #1f6ea9;
@white: #f5f5f5;

.square(@size, @color) {
    width: @size;
    height: @size;
    background-color: @color;
}


.square {
    &-150{
        &-white{
            .square(150px, @white);
        }
        &-blue{
            .square(150px, @blue);
        }
    }   
    &-200{
        &-white{
            .square(200px, @white);
        }
        &-blue{
            .square(200px, @blue);
        }
    }   
}

This is the css that it generates

CSS:

.square-150-white {
  width: 150px;
  height: 150px;
  background-color: #f5f5f5;
}
.square-150-blue {
  width: 150px;
  height: 150px;
  background-color: #1f6ea9;
}
.square-200-white {
  width: 200px;
  height: 200px;
  background-color: #f5f5f5;
}
.square-200-blue {
  width: 200px;
  height: 200px;
  background-color: #1f6ea9;
}

Upvotes: 0

Related Questions