question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Enable &:extend() to take a class as a variable

See original GitHub issue

Feature Request

It would be very powerful if :extend could be passed a class name as a variable.

e.g. something like:

&:extend(@{extending-class-string});

or:

&:extend(@extending-class);

Use Cases:

(tl;dr this would be brilliant for making mixins reusable and for grid systems)

If you want to extend a class with numbered additions it is possible, as long as you create a mixin for every class you want to extend.

for example:

.dec-loop (@length) {
  @i: @length;

  .extended-class {
    float: left;
  }

  .loop (@i) when (@i > 0) {   
    @loop-class: ~".dec-@{i}";   
    @{loop-class} {
      &:extend(.extended-class);
    }    
    .loop(@i - 1);
  }
  .loop(@i);  
}
.dec-loop(4);

will create:

.extended-class,
.extended-class-4,
.extended-class-3,
.extended-class-2,
.extended-class-1 {
  float: left;
}

However the name of the class being extended is hard coded into the mixin, requiring a new mixin for every class you want to extend in this way. But imagine if this worked:

.inc-loop (@extending-class-name; @total) {
  @i: 1;
  @extending-class-string: ~".@{extending-class-name}";

  .loop (@i) when (@i =< @total) {   
    @loop-class: ~".@{extending-class-name}-@{i}";   
    @{loop-class} {     
      &:extend(@{extending-class-string}); // feature request
    }    
    .loop(@i + 1);
  }
  .loop(@i);  
}

.extended-class {
  float: left;
}
.inc-loop(extended-class, 8);

or even better, if this worked!:

.inc-loop (@extending-class-name; @total) {
  @i: 1;
  @extending-class-string: ~".@{extending-class-name}";

  .@{extending-class-name} { // another feature request?
    float: left;
  }

  .loop (@i) when (@i =< @total) {   
    @loop-class: ~".@{extending-class-name}-@{i}";   
    @{loop-class} {
      &:extend(@{extending-class-string}); // feature request
    }    
    .loop(@i + 1);
  }
  .loop(@i);  
}

.inc-loop(extended-class, 8);

Because this would allow us to have a SINGLE mixin, that could create and extend many different classes. Which might be just what you want if you are working on a grid layout system.

P.S. I suspect that:

.@{extending-class-name}{}

may not work for quite a different reason. Somehow it does not create a class that can be extended, however this probably ought to be a separate Feature Request or Bug Issue.

Issue Analytics

  • State:open
  • Created 10 years ago
  • Reactions:7
  • Comments:26 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
DennisJohnsencommented, Jan 26, 2018

This is a very handy feature, as it combines two powerful less tools.

The ability to extend through mixins would be very powerful to have in LESS.

Commenting to keep it from going stale.

2reactions
luxlogicacommented, Mar 28, 2020

I am trying to create a utility-first framework akin to TailwindCSS in LESS, and it is quite impossible, without this feature. Such frameworks need to auto-generate a large number of selectors, all of which will apply the same CSS property - so it’s important to be able to use :expand, so we don’t end up with gigantic duplication of properties.

For example, the framework might have classes that apply a certain background colour, like .bg-blue. That background colour might need to be applied only on specific states, so the framework might also need to create classes like bg-blue-hover, bg-blue-focus, bg-blue-visited, and so on. All of these classes would basically be applying just one property: background-color: blue;. The issue is, that we don’t know in advance what colours the user will want the framework to generate, so it needs to be generated dynamically.

We can loop easily enough using each(), but that will generate a stylesheet where every class has the background-color attribute repeated - taking up a huge amount of space:

@colours: {
  red: tomato;
  green: forestgreen;
  blue: dodgerblue;
};

@states: hover, focus, link, active, visited;

each(@colours) ,(@v, @k){
  .bg-@{k} { 
    background-color: @v;
    each(@states,{
      &-@{value}:@{value}{ background-color: @v; } // DUPLICATION PROBLEM - need :expand
    } 
}

This produces a needlessly long file, where each colour/state has the background-color property individually defined:

.bg-red { background-color: tomato; }

.bg-red-hover:hover { background-color: tomato; }

.bg-red-focus:focus { background-color: tomato; }

.bg-red-link:link { background-color: tomato; }

.bg-red-active:active { background-color: tomato; }

.bg-red-visited:visited { background-color: tomato; }

What we want instead is:

.bg-red,.bg-red-hover:hover, 
.bg-red-focus:focus, 
.bg-red-link:link, .bg-red-active:active, 
.bg-red-visited:visited { background-color: tomato; }

Ideally, to do this we should just be able to use the parent selector with the :extend, inside the each() loop, like this:

 &-@{value}:@{value}:expand(&){ } // :expand will list selector along parent selector

At the moment, there does not seem to be a way to achieve this with Less. Unfortunately, this is not a minor issue - it’s pretty major, when you consider the amount of classes and variants that we’ll need to create - for margins, padding, borders, typography, etc., and that each variant has to be repeated under media queries, for every breakpoint (ends up as thousands and thousands of needlessly repeated property lines).

This means that using another language would enable us to create much smaller compiled files - and that ends up being a very compelling argument to switch. It is even more discouraging to see that this issue has been raised 7 years ago, and has been marked as ‘low priority’. I sure hope the team will reconsider.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Can I reasonably access a variable of an extending class?
I have an array of objects from one class that I made, which includes both objects of that type and objects that extend...
Read more >
Subclassing and Inheritance - Learning Java, 4th Edition [Book]
A class in Java can be declared as a subclass of another class using the extends keyword. A subclass inherits variables and methods...
Read more >
How to Use Variables within Classes | Pluralsight
Here in this example, the component has one method called onFormSubmit() , but notice the constructor of the class. The method is bound...
Read more >
Extension Methods - C# Programming Guide - Microsoft Learn
Extension methods in C# enable you to add methods to existing types ... WriteLine("A.MethodB()"); } } class B : IMyInterface { public void ......
Read more >
extends - JavaScript - MDN Web Docs - Mozilla
The extends keyword is used in class declarations or class expressions to create a class that is a child of another class.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found