Dynamic CSS Classes in LESS

I’m always learning something new or getting better at things. Constant improvement is important to me. I recently began using LESS at work and figured out how to do something cool that I thought was worth documenting and sharing.

If you’re still reading this you probably already have some exposure to both LESS and CSS, so I’ll get right to it.

Repeating CSS

Sometimes you have several CSS rules that are very similar and only have slight variations. This can be kind of annoying to write and maintain, especially if the difference between each rule is predictable and logical.

The scenario that led me to learn this cool feature of LESS was indentation within my HTML table. I had several different levels of indentation that I needed to account for in a table of financial data. It didn’t make sense to use an unordered list, because my data was a table of dollars and sums; so I stuck with a table and created CSS rules I could apply to TD’s where necessary.

Here’s the raw CSS I used:

td.indent-level-1 {
    padding: 0 0 0 18px;
}
td.indent-level-2 {
    padding: 0 0 0 36px;
}
td.indent-level-3 {
    padding: 0 0 0 54px;
}

Functions in LESS

You probably noticed some similarities between the class names and rules, and a relationship between each class name and its rule.

Each class name starts with “indent-level” followed by an integer. Each padding rule is divisible by 18 and, coincidentally, the number in the class name multiplied by 18 equals the right padding I’m after; We’ll use those “coincidences” to our advantage when creating our LESS rules:

td {
    .indent-level(@depth) {
      /* do something */
    }
    .indent-level(1);
 }

“.indent-level(…)” is a LESS function that we will write. Functions in LESS – like any other Procedural Language – allow us to reuse your code. We can also pass variables to your function.

Defining and Using Variables in LESS Functions

So now that we’ve defined our function, and are calling it in our LESS stylesheet, let’s actually do something with it.

td {
    .indent-level(@depth) {
        @className: ~"indent-level-@{depth}";
        &.@{className} {
            padding: 0 0 0 (18px*@depth);
        }
    }
    .indent-level(1);
}

“@className: ..;” is a variable definition where we can use the parameter to dynamically create a string we’ll use as the class name. @{className} is how we use a variable (we’re actually doing that in our className definition too! So, LESS will take our rule and apply the variables to it and “drop it in” in place of our calls to the function.

Now, when we compile our LESS into CSS we get:

td.indent-level-1 {
    padding: 0 0 0 18px;
}

Notice how “(18px*@depth)” becomes “18px”? LESS knows that when we do math on a pixel the result will be a pixel. Also, see that we didn’t have to use “@{depth}” when doing math?

Calling LESS Function Iteratively

We have our LESS Function written and have created our first level of indentation. Great! But we need to create multiple, iterative, levels of indentation. We could call “.indent-level()” multiple times, with the numbers 1-3 hard coded into each call; or we could use a loop in LESS.

Now we can see that if we repeat our call to “.indent-leve(…)” 2 more times, we’ll get all 3 indentations defined thanks to reusable code. Our different levels of indentation will also be evenly spaced from the other levels because they will always be 18px apart!

td {
    .indent-level(@depth) when (@depth > 0) {
        @className: ~"indent-level-@{depth}";
        &.@{className} {
            padding: 0 0 0 (18px*@depth);
        }
        .indent-level(@depth - 1);
    }
    .indent-level(3);
}

Notice the call to “.indent-level(@depth – 1)” is inside our LESS Function. This is how LESS knows to continue looping. It’s not a true loop, it’s more like conditional recursion. Also notice that we only have to actually call the “.indent-level(…)” function 1 time to get things started. And in this case we’re calling it with the largest depth first, and decrementing as we go. Now here’s the result:

td.indent-level-3 {
    padding: 0 0 0 54px;
}
td.indent-level-2 {
    padding: 0 0 0 36px;
}
td.indent-level-1 {
    padding: 0 0 0 18px;
}

Pretty cool! Hopefully this is helpful for you. I’d love to hear how you are using LESS functions, variables, and such to make your CSS easier to maintain. I’m still constantly learning new things myself!

36 thoughts on “Dynamic CSS Classes in LESS

  1. Pingback: How to Add Custom CSS to WordPress - WP Like a Pro

  2. Norberto

    BOYCOTT AMERICAN WOMEN! http://www.BoycottBitches.com I am an American man, and I have decided to boycott American women. In a nutshell, American women are the most likely to cheat on you, to divorce you, to get fat, to steal half of your money in the divorce courts, don’t know how to cook or clean, don’t want to have children, etc. Therefore, what intelligent man would want to get involved with American women? American women are generally immature, selfish, extremely arrogant and self-centered, mentally unstable, irresponsible, and highly unchaste. The behavior of most American women is utterly disgusting, to say the least. This blog is my attempt to explain why I feel American women are inferior to foreign women (non-American women), and why American men should boycott American women, and date/marry only foreign (non-American) women.

    Reply
  3. Elisa Brown

    This is a comment to the Dynamic CSS Classes in LESS | Chris A Nesbit admin. Your website is missing out on at least 300 visitors per day. Our traffic system will dramatically increase your traffic to your website: http://shorturl.van.ee/h – We offer 500 free targeted visitors during our free trial period and we offer up to 30,000 targeted visitors per month. Hope this helps 🙂

    Reply
  4. Erik Lachermeier

    I am just trying to launch a small blog page, primarily to hold a few short stories We have written and get responses, but also for many other blog-type activities. This will not likely do myself any good easily can’t obtain my words where people can read them… Blogspot is certainly preferred, but anything permitting advertising will be fine. I would want to monetise eventually, and wordpress seems to decrease that, as I understand their terms of use..

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *