New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

:extend mixins #1177

Open
jonschlinkert opened this Issue Feb 12, 2013 · 112 comments

Comments

Projects
None yet
@jonschlinkert
Contributor

jonschlinkert commented Feb 12, 2013

This feature request was proposed as a solution to this issue #1155

This is the synopsis

The awesome thing about mixins is that they speed up development, keep my work surface clean, I only have to write them once, and I know what the compiled result will be. However, a disadvantage of mixins is that they aren't DRY. Especially when you use "utility" mixins a lot, like clearfix. This is where extends could be a much better option. In fact, this is a great, concrete use case for extending mixins. It would basically work like extending nested selectors, accept with mixins. So mixins wouldn't change at all, they would still work the same way. If you have a mixin and don't use it, it won't show in the compiled CSS. If you do use it, it's properties will still show up in the compiled code in each selector where it was used. And if you extend a mixin, the selector (or selectors) extending the mixin will show up in place of the mixin. So if you do this:

.clearfix() {
    // stuff
}
.navbar {
    &:extend(.clearfix());
}
.banner {
    &:extend(.clearfix());
}

and the compiled result will be:

.navbar,
.banner {
   // clearfix stuff
}

So the mixins properties are still inherited by the selectors that extended it, but the mixin (selector) itself doesn't show up in the compiled result.

This would make both extends and mixins far more powerful than they are on their own.

@lukeapage

This comment has been minimized.

Show comment
Hide comment
@lukeapage

lukeapage Feb 13, 2013

Member

I like it, but just to be clear.. this doesn't allow you do something you couldn't do before, it just means that you get..

.navbar,
.banner {
    // clearfix stuff
}

rather than

.navbar {
    // clearfix stuff
}
.banner {
    // clearfix stuff
}

or have I misunderstood?

Member

lukeapage commented Feb 13, 2013

I like it, but just to be clear.. this doesn't allow you do something you couldn't do before, it just means that you get..

.navbar,
.banner {
    // clearfix stuff
}

rather than

.navbar {
    // clearfix stuff
}
.banner {
    // clearfix stuff
}

or have I misunderstood?

@dmi3y

This comment has been minimized.

Show comment
Hide comment
@dmi3y

dmi3y Feb 13, 2013

I would love have both, parametric and usual mixins, to have

.navbar,
.banner {
    // clearfix stuff
}
.....

or

.clearfix,
.navbar,
.banner {
    // clearfix stuff
}
....

whenever you need, I know this is the simular way how mixins already works, so the question mostly having flexibility and way for better handling the final CSS output in terms of optimization.

surely

.clearfix,
.navbar,
.banner {
    // clearfix stuff
}

is shorter than

 .clearfix {
    // clearfix stuff
  }
 .navbar{
    // clearfix stuff
 }
.banner {
    // clearfix stuff
}

and for more complicated examples that could be critical, and I know some people switched to SASS just because of this shortage

dmi3y commented Feb 13, 2013

I would love have both, parametric and usual mixins, to have

.navbar,
.banner {
    // clearfix stuff
}
.....

or

.clearfix,
.navbar,
.banner {
    // clearfix stuff
}
....

whenever you need, I know this is the simular way how mixins already works, so the question mostly having flexibility and way for better handling the final CSS output in terms of optimization.

surely

.clearfix,
.navbar,
.banner {
    // clearfix stuff
}

is shorter than

 .clearfix {
    // clearfix stuff
  }
 .navbar{
    // clearfix stuff
 }
.banner {
    // clearfix stuff
}

and for more complicated examples that could be critical, and I know some people switched to SASS just because of this shortage

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert Feb 13, 2013

Contributor

Regular mixins couldn't change. They are pretty much a fixture of Less. @agatronic, yeah I see it that way as well. There are challenges to this though, like would we be able to extend parametric mixins? And if so how would that work? Assuming this was supported, let's say you extend a parametric mixin twice but use different variables each time, like this:

.transition(@transition) {
  -webkit-transition: @transition;
     -moz-transition: @transition;
       -o-transition: @transition;
          transition: @transition;
}
.navbar {
    &:extend(.transition(opacity .2s linear));
}
.banner {
    &:extend(.transition(opacity .3s linear));
}

I imagine it might create two copies of the mixin, which is no less code, and no advantage over regular mixins:

.navbar {
  -webkit-transition: opacity .2s linear;
     -moz-transition: opacity .2s linear;
       -o-transition: opacity .2s linear;
          transition: opacity .2s linear;
}
.banner {
  -webkit-transition: opacity .3s linear;
     -moz-transition: opacity .3s linear;
       -o-transition: opacity .3s linear;
          transition: opacity .3s linear;
}

However, you might use this particular mixin a lot, so when you use the mixin again on .dropdown with the same variables as .banner, it might result in this:

.navbar {
  -webkit-transition: opacity .2s linear;
     -moz-transition: opacity .2s linear;
       -o-transition: opacity .2s linear;
          transition: opacity .2s linear;
}
.banner,
.dropdown {
  -webkit-transition: opacity .3s linear;
     -moz-transition: opacity .3s linear;
       -o-transition: opacity .3s linear;
          transition: opacity .3s linear;
}

And this is what makes this interesting to me. it would be good to hear feedback from others too

Contributor

jonschlinkert commented Feb 13, 2013

Regular mixins couldn't change. They are pretty much a fixture of Less. @agatronic, yeah I see it that way as well. There are challenges to this though, like would we be able to extend parametric mixins? And if so how would that work? Assuming this was supported, let's say you extend a parametric mixin twice but use different variables each time, like this:

.transition(@transition) {
  -webkit-transition: @transition;
     -moz-transition: @transition;
       -o-transition: @transition;
          transition: @transition;
}
.navbar {
    &:extend(.transition(opacity .2s linear));
}
.banner {
    &:extend(.transition(opacity .3s linear));
}

I imagine it might create two copies of the mixin, which is no less code, and no advantage over regular mixins:

.navbar {
  -webkit-transition: opacity .2s linear;
     -moz-transition: opacity .2s linear;
       -o-transition: opacity .2s linear;
          transition: opacity .2s linear;
}
.banner {
  -webkit-transition: opacity .3s linear;
     -moz-transition: opacity .3s linear;
       -o-transition: opacity .3s linear;
          transition: opacity .3s linear;
}

However, you might use this particular mixin a lot, so when you use the mixin again on .dropdown with the same variables as .banner, it might result in this:

.navbar {
  -webkit-transition: opacity .2s linear;
     -moz-transition: opacity .2s linear;
       -o-transition: opacity .2s linear;
          transition: opacity .2s linear;
}
.banner,
.dropdown {
  -webkit-transition: opacity .3s linear;
     -moz-transition: opacity .3s linear;
       -o-transition: opacity .3s linear;
          transition: opacity .3s linear;
}

And this is what makes this interesting to me. it would be good to hear feedback from others too

@dmi3y

This comment has been minimized.

Show comment
Hide comment
@dmi3y

dmi3y Feb 13, 2013

@jonschlinkert yes, that's even better illustration, thank you. as i said both hands on that! but understand though it is adding another level of complicity, and needs to be done/not done thoughtfully

dmi3y commented Feb 13, 2013

@jonschlinkert yes, that's even better illustration, thank you. as i said both hands on that! but understand though it is adding another level of complicity, and needs to be done/not done thoughtfully

@krismeister

This comment has been minimized.

Show comment
Hide comment
@krismeister

krismeister Feb 14, 2013

Extension in the method you're reference can be achieved pretty easily with this pattern:

.transition(@transition) {
    -webkit-transition: @transition;
     -moz-transition: @transition;
       -o-transition: @transition;
          transition: @transition;
}

.quickOpacity1(){
    .transition(opacity .2s linear);
}

.quickOpacity2(){
    .transition(opacity .3s linear);
}

.navbar{
    .quickOpacity1();
}

.banner,
.dropdown{
    .quickOpacity2();
}

The above is injecting semi-extended mixins into the the 2 new declarations.

For the clearfix its also easy to use a similar pattern below, which will not only create the clearfix as a class, but inject those clearfix styles into a new declaration.

.clearfix{
  //clearfix stuff
}
.navbar,
.banner {
    .clearfix;
}

Extension in the method you're reference can be achieved pretty easily with this pattern:

.transition(@transition) {
    -webkit-transition: @transition;
     -moz-transition: @transition;
       -o-transition: @transition;
          transition: @transition;
}

.quickOpacity1(){
    .transition(opacity .2s linear);
}

.quickOpacity2(){
    .transition(opacity .3s linear);
}

.navbar{
    .quickOpacity1();
}

.banner,
.dropdown{
    .quickOpacity2();
}

The above is injecting semi-extended mixins into the the 2 new declarations.

For the clearfix its also easy to use a similar pattern below, which will not only create the clearfix as a class, but inject those clearfix styles into a new declaration.

.clearfix{
  //clearfix stuff
}
.navbar,
.banner {
    .clearfix;
}
@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert Feb 14, 2013

Contributor

@krismeister I think there might be confusion on this. The pattern you describe is really just nested mixins, or a mixin inheritance pattern. Extends work in the inverse of that.

Contributor

jonschlinkert commented Feb 14, 2013

@krismeister I think there might be confusion on this. The pattern you describe is really just nested mixins, or a mixin inheritance pattern. Extends work in the inverse of that.

@krismeister

This comment has been minimized.

Show comment
Hide comment
@krismeister

krismeister Feb 14, 2013

@jonschlinkert Mixin inheritence - a great name. It seemed that both of the examples above where trying to inherit output from the parent - which is a core feature of extension. You probably agree that the output of my example was your expected output.

I understand from rereading your original comment however- you'd like the output to be joined into one CSS rule. Though it was written as 2 originally.

@jonschlinkert Mixin inheritence - a great name. It seemed that both of the examples above where trying to inherit output from the parent - which is a core feature of extension. You probably agree that the output of my example was your expected output.

I understand from rereading your original comment however- you'd like the output to be joined into one CSS rule. Though it was written as 2 originally.

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert Feb 14, 2013

Contributor

Actually :extend is pretty awesome. I'm going to go full nerd, but it all comes down to "what gets moved where". Think of a mixin like "beaming the mixin's properties down to the selector that used it". And think of :extend as the inverse, "beaming the selector that used it up to the mixin itself." Not the _selector's properties, just the selector itself. So if you did this:

.some-mixin() {
    padding-top: 100px;
    background: #f7f7f7;
}


// a selector that is extending the mixin
.alert:extend( .some-mixin() ) {
    border: 1px solid #e5e5e5;
}
// another selector extending the mixin
section:extend(.some-mixin()) {
    margin: 20px 0;
}

It would result in this:

// The selectors that extended the mixin are now where the mixin used to be.
.alert,
section {
    padding-top: 100px;
    background: #f7f7f7;
}

// And the properties of the mixin did not get copied down below
// so we saved a line or two of code.
.alert {
    border: 1px solid #e5e5e5;
}
section {
    margin: 20px 0;
}

Hopefully that makes more sense. I'm happy to help anytime.

Contributor

jonschlinkert commented Feb 14, 2013

Actually :extend is pretty awesome. I'm going to go full nerd, but it all comes down to "what gets moved where". Think of a mixin like "beaming the mixin's properties down to the selector that used it". And think of :extend as the inverse, "beaming the selector that used it up to the mixin itself." Not the _selector's properties, just the selector itself. So if you did this:

.some-mixin() {
    padding-top: 100px;
    background: #f7f7f7;
}


// a selector that is extending the mixin
.alert:extend( .some-mixin() ) {
    border: 1px solid #e5e5e5;
}
// another selector extending the mixin
section:extend(.some-mixin()) {
    margin: 20px 0;
}

It would result in this:

// The selectors that extended the mixin are now where the mixin used to be.
.alert,
section {
    padding-top: 100px;
    background: #f7f7f7;
}

// And the properties of the mixin did not get copied down below
// so we saved a line or two of code.
.alert {
    border: 1px solid #e5e5e5;
}
section {
    margin: 20px 0;
}

Hopefully that makes more sense. I'm happy to help anytime.

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert Feb 14, 2013

Contributor

@agatronic, @matthewdl, @DesignByOnyx, just a thought, I know this is an unusual approach, but assuming there are no technical challenges to this, and assuming we allow a comma separated list of selectors, maybe extend should feel more like an array. What do you think about changing the syntax to: :extend[N].

I think it's easier on the eyes too when mixins are extended:

section:extend[.some-mixin(), .another-mixin()] {
    margin: 20px 0;
}

I'm fine either way, but something just feels right about the square brackets.

Contributor

jonschlinkert commented Feb 14, 2013

@agatronic, @matthewdl, @DesignByOnyx, just a thought, I know this is an unusual approach, but assuming there are no technical challenges to this, and assuming we allow a comma separated list of selectors, maybe extend should feel more like an array. What do you think about changing the syntax to: :extend[N].

I think it's easier on the eyes too when mixins are extended:

section:extend[.some-mixin(), .another-mixin()] {
    margin: 20px 0;
}

I'm fine either way, but something just feels right about the square brackets.

@lukeapage

This comment has been minimized.

Show comment
Hide comment
@lukeapage

lukeapage Feb 14, 2013

Member

@jonschlinkert - [] means attribute in css, not array, where as :extend() was chosen because of its link to pseudo selectors, so I strongly think normal brackets should stay.

Member

lukeapage commented Feb 14, 2013

@jonschlinkert - [] means attribute in css, not array, where as :extend() was chosen because of its link to pseudo selectors, so I strongly think normal brackets should stay.

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert Feb 14, 2013

Contributor

good point, I agree.

Contributor

jonschlinkert commented Feb 14, 2013

good point, I agree.

@DesignByOnyx

This comment has been minimized.

Show comment
Hide comment
@DesignByOnyx

DesignByOnyx Feb 14, 2013

I agree that the brackets looks and reads nice, but yeah we have to stick with syntax we have already chosen.

I agree that the brackets looks and reads nice, but yeah we have to stick with syntax we have already chosen.

@dmi3y

This comment has been minimized.

Show comment
Hide comment
@dmi3y

dmi3y Feb 14, 2013

thumb up for extend(N) syntax, more feels like nature CSS, same reason as @agatronic

dmi3y commented Feb 14, 2013

thumb up for extend(N) syntax, more feels like nature CSS, same reason as @agatronic

@matthew-dean

This comment has been minimized.

Show comment
Hide comment
@matthew-dean

matthew-dean Feb 14, 2013

Member

Extending mixins is not a bad idea. Not sure about the example syntax, @jonschlinkert. Not that I don't like it; I just actually don't understand what you've written.

I think what you mean is that you want to define classes that "pull in" the same mixin content, but don't actually repeat in the resulting CSS. I wouldn't call that extending mixins. That is, you're not altering the mixin definition (in the same way that the extend definition would do to selectors), you're actually altering (extending) the resulting classes.

So, correct me if I'm wrong, but wouldn't your navbar / banner / dropdown example be supported by:

.navbar {
  .transition(opacity .2s linear);
}
.banner {
  .transition(opacity .3s linear);
}
.dropdown:extend(.banner) { }

That is, extending the classes as you normally would? I'm just trying to wrap my head around your usage pattern, and the use of extend for mixins seems at odds with its use and nomenclature for extending selectors. Can you provide further details on why you would need / want to reference the mixin in an extend call, and not extend a selector that referenced the mixin?

Member

matthew-dean commented Feb 14, 2013

Extending mixins is not a bad idea. Not sure about the example syntax, @jonschlinkert. Not that I don't like it; I just actually don't understand what you've written.

I think what you mean is that you want to define classes that "pull in" the same mixin content, but don't actually repeat in the resulting CSS. I wouldn't call that extending mixins. That is, you're not altering the mixin definition (in the same way that the extend definition would do to selectors), you're actually altering (extending) the resulting classes.

So, correct me if I'm wrong, but wouldn't your navbar / banner / dropdown example be supported by:

.navbar {
  .transition(opacity .2s linear);
}
.banner {
  .transition(opacity .3s linear);
}
.dropdown:extend(.banner) { }

That is, extending the classes as you normally would? I'm just trying to wrap my head around your usage pattern, and the use of extend for mixins seems at odds with its use and nomenclature for extending selectors. Can you provide further details on why you would need / want to reference the mixin in an extend call, and not extend a selector that referenced the mixin?

@dmi3y

This comment has been minimized.

Show comment
Hide comment
@dmi3y

dmi3y Feb 14, 2013

That's how I get it

DESIRED FINAL CSS OUTPUT

.sometingShared,
.anotherClass,
.anotherYetClass,
.yetClass {
    // amount of shared code here
}

.anotherClass,
.anotherYetClass {
    // did something dynamic with a
}

.yetClass {
    // did something dynamic with b
}

.anotherClass {
    // native another class code
}

.anotherYetClass {
    // native another yet class code
}

.yetClass {
    // native yet class code
}

THE WAY YOU HAS TO GO WITH CURRENT VERSION OF LESS TO GET DESIRED OUTPUT

.somethingShared,
.anotherClass,
.anotherYetClass,
.yetClass {
    // amount of shared code here
}

.someMixin(@val) {
    // do something dynamic with val
}

.anotherClass,
.anotherYetClass {
    .someMixin(a);
}

.yetClass {
    .someMixin(b);
}

.anotherClass {
    // native another class code
}

.anotherYetClass {
    // native another yet class code
}

.yetClass {
    // native yet class code
}

SUGESSTED LESS SYNTAX

.somethingShared {
    // amount of shared code here
}

.someMixin(@val) {
    // do something dynamic with val
}

.anotherClass:extend(.sometingShared, .someMixin(a)) {
    // native another class code
}

.anotherYetClass:extend(.sometingShared, .someMixin(a)) {
    // native another yet class code
}

.yetClass:extend(.sometingShared, .someMixin(b)) {
    // native yet class code
}

While the extends could be useful only when you have really amount of shared code, in other cases ordinary mixins usage have favor.

And just somewhat, live dummy sample, aimed to just playaround

http://jsbin.com/opekon/1/edit
http://jsbin.com/opekon/2/edit
http://jsbin.com/opekon/3/edit
http://jsbin.com/opekon/4/edit

as said, there could be really performance boost in certain circumstances for people who lazy like me:) to optimize LESS code just because it is affected further flexibility

dmi3y commented Feb 14, 2013

That's how I get it

DESIRED FINAL CSS OUTPUT

.sometingShared,
.anotherClass,
.anotherYetClass,
.yetClass {
    // amount of shared code here
}

.anotherClass,
.anotherYetClass {
    // did something dynamic with a
}

.yetClass {
    // did something dynamic with b
}

.anotherClass {
    // native another class code
}

.anotherYetClass {
    // native another yet class code
}

.yetClass {
    // native yet class code
}

THE WAY YOU HAS TO GO WITH CURRENT VERSION OF LESS TO GET DESIRED OUTPUT

.somethingShared,
.anotherClass,
.anotherYetClass,
.yetClass {
    // amount of shared code here
}

.someMixin(@val) {
    // do something dynamic with val
}

.anotherClass,
.anotherYetClass {
    .someMixin(a);
}

.yetClass {
    .someMixin(b);
}

.anotherClass {
    // native another class code
}

.anotherYetClass {
    // native another yet class code
}

.yetClass {
    // native yet class code
}

SUGESSTED LESS SYNTAX

.somethingShared {
    // amount of shared code here
}

.someMixin(@val) {
    // do something dynamic with val
}

.anotherClass:extend(.sometingShared, .someMixin(a)) {
    // native another class code
}

.anotherYetClass:extend(.sometingShared, .someMixin(a)) {
    // native another yet class code
}

.yetClass:extend(.sometingShared, .someMixin(b)) {
    // native yet class code
}

While the extends could be useful only when you have really amount of shared code, in other cases ordinary mixins usage have favor.

And just somewhat, live dummy sample, aimed to just playaround

http://jsbin.com/opekon/1/edit
http://jsbin.com/opekon/2/edit
http://jsbin.com/opekon/3/edit
http://jsbin.com/opekon/4/edit

as said, there could be really performance boost in certain circumstances for people who lazy like me:) to optimize LESS code just because it is affected further flexibility

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert Feb 15, 2013

Contributor

Here is a nice blog post about extends that covers several things regarding how SASS handles extends, and it's probably wise for us to learn from how others have done this. http://designshack.net/articles/css/semantic-grid-class-naming-with-placeholder-selectors-in-sass-3-2/

In particular, I believe my proposal for extending mixins would essentially achieve the same end result as SASS "placeholders", but without having to create useless, superfluous placeholder-only classes.

EDIT: yes, here is another post that sums up placeholders nicely. It's exactly what I'm proposing with extending mixins http://maximilianhoffmann.com/article/placeholder-selectors

I personally would prefer this above all other extend-related features. Without question. This is a strong statement, but I think I'm not doing a good job of explaining it if others don't agree. This is quite powerful stuff.

Contributor

jonschlinkert commented Feb 15, 2013

Here is a nice blog post about extends that covers several things regarding how SASS handles extends, and it's probably wise for us to learn from how others have done this. http://designshack.net/articles/css/semantic-grid-class-naming-with-placeholder-selectors-in-sass-3-2/

In particular, I believe my proposal for extending mixins would essentially achieve the same end result as SASS "placeholders", but without having to create useless, superfluous placeholder-only classes.

EDIT: yes, here is another post that sums up placeholders nicely. It's exactly what I'm proposing with extending mixins http://maximilianhoffmann.com/article/placeholder-selectors

I personally would prefer this above all other extend-related features. Without question. This is a strong statement, but I think I'm not doing a good job of explaining it if others don't agree. This is quite powerful stuff.

@dmi3y

This comment has been minimized.

Show comment
Hide comment
@dmi3y

dmi3y Feb 15, 2013

I feel that SASS

 %tile {
  width: 200px;
  height: 200px;
  margin-right: 20px;
}

is equal of the parametric mixin, designed for extends exclusively, what probably not such a bad in terms of separation of concerns. but yeah that's CSS, and is not it suppose to be as simple as possible?

dmi3y commented Feb 15, 2013

I feel that SASS

 %tile {
  width: 200px;
  height: 200px;
  margin-right: 20px;
}

is equal of the parametric mixin, designed for extends exclusively, what probably not such a bad in terms of separation of concerns. but yeah that's CSS, and is not it suppose to be as simple as possible?

@dmi3y

This comment has been minimized.

Show comment
Hide comment
@dmi3y

dmi3y Feb 15, 2013

@agatronic while we are talking about, what is this extend https://github.com/agatronic/less.js/blob/master/lib/less/tree/extend.js supposed to be? noted it is already in main less branch. sorry for noob question though.

dmi3y commented Feb 15, 2013

@agatronic while we are talking about, what is this extend https://github.com/agatronic/less.js/blob/master/lib/less/tree/extend.js supposed to be? noted it is already in main less branch. sorry for noob question though.

@lukeapage

This comment has been minimized.

Show comment
Hide comment
@lukeapage

lukeapage Feb 15, 2013

Member

@dmi3y it is the first version of extend which was pulled from a pull request ready for 1.4.0 - it represents the extend node

Member

lukeapage commented Feb 15, 2013

@dmi3y it is the first version of extend which was pulled from a pull request ready for 1.4.0 - it represents the extend node

@dmi3y

This comment has been minimized.

Show comment
Hide comment
@dmi3y

dmi3y Feb 15, 2013

thank you @agatronic, now I see how much I missed ;)

dmi3y commented Feb 15, 2013

thank you @agatronic, now I see how much I missed ;)

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert Feb 16, 2013

Contributor

@dmi3y please feel free to continue adding to the conversation, let's try to keep this issue at a higher level so that we can draw it to a conclusion. Also feel free to email me personally, I'm happy to discuss how mixins and extends work with you (my contact info is on my profile). Also a quick comment to avoid further confusion on this thread. Your example:

%tile {
    width: 200px;
    height: 200px;
    margin-right: 20px;
}

This is the syntax for a SCSS "placeholder", which was implemented in the SCSS spec to accomplish something similar to what I am proposing with extending mixins. But this has nothing to do with being parametric. Parametric mixins are simply mixins that accept parameters, meaning that their values can change each time they are used.

@matthewdl

I think what you mean is that you want to define classes that "pull in" the same mixin content, but don't actually repeat in the resulting CSS

and

wouldn't your navbar / banner / dropdown example be supported by...

No, the operative point is being missed, it's quite the other way around. Maybe the confusion was caused because I made the mistake of focusing on parametric mixins in my example.

So first, I think it's important to delineate that not all mixins are parametric, many are created to not accept parameters. Some mixins, like clearfix, are used over and over again without changing any variables when they are used. These are a perfect use case for why extending mixins would be advantageous.

Parametric or not, in all their glory mixins have a downside in that each time one is used, its properties get duplicated. So let me try to explain how extending mixins would work using only "regular mixins", and continuing with the example you used above.

Given your example, there are two completely independent and unrelated points that need to be made:

  1. the banner class would still show up in the compiled CSS whether is was extended or not, but if the banner class was a mixin it would only show up in the resulting CSS if was used (either extended or mixed in). This alone is valuable. And
  2. When you extend a mixin, rather than duplicating the same exact properties over and over again, we would copy the actual selectors themselves to the place of the mixin.

But this is just one example. Consider that at one point in Twitter Bootstrap the .clearfix() mixin alone was used more than 20 times inside other selectors, AND it was also nested inside 4 or 5 other structural mixins, such as .container-fixed(), .make-row(), and #grid > .core(). Meaning that those mixins were also duplicating the clearfix mixin's properties each time they were used. And this isn't unique to that framework.

Does this make more sense? So in instead of having the properties of the clearfix mixin duplicated more than 20 times, we would group selectors that use the clearfix mixin at the place of the mixin itself, and the properties would only be declared once. And again, this is just one mixin, imagine the net benefit from extending lost of regular mixins, versus having their properties duplicated. As I mentioned somewhere above, regular mixins will still need to be used without being extended sometimes, for specificity and overrides, but that doesn't diminish the value of extending the ones that don't. In fact, I would personally create additional mixins to be used specifically with extend, that would I wouldn't use otherwise.

And my second example above focused on how extend would work with parametric mixins, so hopefully this completes the picture and makes more sense now? If not, the articles I linked to above should clear up any confusion. Extending mixins is extremely powerful and useful and would allow you to achieve the same net result as extending nested selectors, but with mixins specifically instead of any nested selectors. This allows you to organize your selectors in a way that is most likely to provide the results you want, and avoid unintended consequences. @DesignByOnyx, @agatronic, @matthewdl, is there anything I'm missing or forgetting here? Anything we can do to clear up the confusion?

Contributor

jonschlinkert commented Feb 16, 2013

@dmi3y please feel free to continue adding to the conversation, let's try to keep this issue at a higher level so that we can draw it to a conclusion. Also feel free to email me personally, I'm happy to discuss how mixins and extends work with you (my contact info is on my profile). Also a quick comment to avoid further confusion on this thread. Your example:

%tile {
    width: 200px;
    height: 200px;
    margin-right: 20px;
}

This is the syntax for a SCSS "placeholder", which was implemented in the SCSS spec to accomplish something similar to what I am proposing with extending mixins. But this has nothing to do with being parametric. Parametric mixins are simply mixins that accept parameters, meaning that their values can change each time they are used.

@matthewdl

I think what you mean is that you want to define classes that "pull in" the same mixin content, but don't actually repeat in the resulting CSS

and

wouldn't your navbar / banner / dropdown example be supported by...

No, the operative point is being missed, it's quite the other way around. Maybe the confusion was caused because I made the mistake of focusing on parametric mixins in my example.

So first, I think it's important to delineate that not all mixins are parametric, many are created to not accept parameters. Some mixins, like clearfix, are used over and over again without changing any variables when they are used. These are a perfect use case for why extending mixins would be advantageous.

Parametric or not, in all their glory mixins have a downside in that each time one is used, its properties get duplicated. So let me try to explain how extending mixins would work using only "regular mixins", and continuing with the example you used above.

Given your example, there are two completely independent and unrelated points that need to be made:

  1. the banner class would still show up in the compiled CSS whether is was extended or not, but if the banner class was a mixin it would only show up in the resulting CSS if was used (either extended or mixed in). This alone is valuable. And
  2. When you extend a mixin, rather than duplicating the same exact properties over and over again, we would copy the actual selectors themselves to the place of the mixin.

But this is just one example. Consider that at one point in Twitter Bootstrap the .clearfix() mixin alone was used more than 20 times inside other selectors, AND it was also nested inside 4 or 5 other structural mixins, such as .container-fixed(), .make-row(), and #grid > .core(). Meaning that those mixins were also duplicating the clearfix mixin's properties each time they were used. And this isn't unique to that framework.

Does this make more sense? So in instead of having the properties of the clearfix mixin duplicated more than 20 times, we would group selectors that use the clearfix mixin at the place of the mixin itself, and the properties would only be declared once. And again, this is just one mixin, imagine the net benefit from extending lost of regular mixins, versus having their properties duplicated. As I mentioned somewhere above, regular mixins will still need to be used without being extended sometimes, for specificity and overrides, but that doesn't diminish the value of extending the ones that don't. In fact, I would personally create additional mixins to be used specifically with extend, that would I wouldn't use otherwise.

And my second example above focused on how extend would work with parametric mixins, so hopefully this completes the picture and makes more sense now? If not, the articles I linked to above should clear up any confusion. Extending mixins is extremely powerful and useful and would allow you to achieve the same net result as extending nested selectors, but with mixins specifically instead of any nested selectors. This allows you to organize your selectors in a way that is most likely to provide the results you want, and avoid unintended consequences. @DesignByOnyx, @agatronic, @matthewdl, is there anything I'm missing or forgetting here? Anything we can do to clear up the confusion?

@matthew-dean

This comment has been minimized.

Show comment
Hide comment
@matthew-dean

matthew-dean Feb 17, 2013

Member

Thanks. I think I understand the use case, and I think this line says it best:

the banner class was a mixin it would only show up in the resulting CSS if was used (either extended or mixed in)

That makes sense to me. Probably what I'm getting hung up is that the overall :extend syntax isn't final yet. But, you make persuasive cases.

I'd say that once we finalize for selector blocks, if the behavior of extending mixins ends up matching the behavior of extending selectors (with the key difference being that line that you just said, that no selector is output in the CSS for an extended UNLESS there is an initial usage), then that's intuitive to me.

That is, if I could also do something like this(or equivalent syntax):

.facebook-button:extend( .button() all ) {
    border: 1px solid #e5e5e5;
}

... then thumbs up from me. But, for me, all of that depends on what/how/if we resolve :extend for selectors. But, syntax aside, as a feature idea, you're right, it's sound.

Member

matthew-dean commented Feb 17, 2013

Thanks. I think I understand the use case, and I think this line says it best:

the banner class was a mixin it would only show up in the resulting CSS if was used (either extended or mixed in)

That makes sense to me. Probably what I'm getting hung up is that the overall :extend syntax isn't final yet. But, you make persuasive cases.

I'd say that once we finalize for selector blocks, if the behavior of extending mixins ends up matching the behavior of extending selectors (with the key difference being that line that you just said, that no selector is output in the CSS for an extended UNLESS there is an initial usage), then that's intuitive to me.

That is, if I could also do something like this(or equivalent syntax):

.facebook-button:extend( .button() all ) {
    border: 1px solid #e5e5e5;
}

... then thumbs up from me. But, for me, all of that depends on what/how/if we resolve :extend for selectors. But, syntax aside, as a feature idea, you're right, it's sound.

@dmi3y

This comment has been minimized.

Show comment
Hide comment
@dmi3y

dmi3y Feb 18, 2013

@jonschlinkert thank you, do much appreciate your endorsement, and surely will try my best with putting my thoughts as clearly as I can. I think it is pretty much exiting to hear what's going on with future development and yes, to be heard. You guys all, do awesome work with that.

Yes, this example, I had to be explicit with my previous post.

%tile {
   width: 200px;
   height: 200px;
   margin-right: 20px;
 }

is taken from SASS tutorials provided by Jon, and the main goal of it to avoid trashing output in CSS from classes that would not be in use. So in this particular angle it could be seen like empty parametric mixin in LESS. When you want use it but do not want it was output into end stylesheet.

dmi3y commented Feb 18, 2013

@jonschlinkert thank you, do much appreciate your endorsement, and surely will try my best with putting my thoughts as clearly as I can. I think it is pretty much exiting to hear what's going on with future development and yes, to be heard. You guys all, do awesome work with that.

Yes, this example, I had to be explicit with my previous post.

%tile {
   width: 200px;
   height: 200px;
   margin-right: 20px;
 }

is taken from SASS tutorials provided by Jon, and the main goal of it to avoid trashing output in CSS from classes that would not be in use. So in this particular angle it could be seen like empty parametric mixin in LESS. When you want use it but do not want it was output into end stylesheet.

@DesignByOnyx

This comment has been minimized.

Show comment
Hide comment
@DesignByOnyx

DesignByOnyx Feb 18, 2013

I am jumping in on this discussion and would like to bring clarity for myself on the following comment:

if the banner class was a mixin it would only show up in the resulting CSS if was used (either extended or mixed in)

So, going with a more generic clearfix example, is this the LESS and resulting CSS?:

.clearfix() {
    &:before,
    &:after { content: " "; display: table; }

    &:after { clear: both; }
}
.something:extend( .clearfix() ) { }

/*
.clearfix:before,
.clearfix:after,
.something:before,
.something:after {
    content: " ";
    display: table;
}
.clearfix:after,
.something:after {
    clear: both;
}
*/

I originally expected for the .clearfix class to remain omitted from the compiled CSS. Personally, I would not need the class in the compiled CSS, as I would not be using it in markup and it's extra bytes in my CSS. I don't really have a strong opinion either way, but clarification on this point would help me make better comments moving forward. Thanks.

I am jumping in on this discussion and would like to bring clarity for myself on the following comment:

if the banner class was a mixin it would only show up in the resulting CSS if was used (either extended or mixed in)

So, going with a more generic clearfix example, is this the LESS and resulting CSS?:

.clearfix() {
    &:before,
    &:after { content: " "; display: table; }

    &:after { clear: both; }
}
.something:extend( .clearfix() ) { }

/*
.clearfix:before,
.clearfix:after,
.something:before,
.something:after {
    content: " ";
    display: table;
}
.clearfix:after,
.something:after {
    clear: both;
}
*/

I originally expected for the .clearfix class to remain omitted from the compiled CSS. Personally, I would not need the class in the compiled CSS, as I would not be using it in markup and it's extra bytes in my CSS. I don't really have a strong opinion either way, but clarification on this point would help me make better comments moving forward. Thanks.

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert Feb 18, 2013

Contributor

is this the ... resulting CSS?:

I'm glad you're asking, but no, only the .something class would show up in the resulting CSS. So you were correct in your original expectation.

Contributor

jonschlinkert commented Feb 18, 2013

is this the ... resulting CSS?:

I'm glad you're asking, but no, only the .something class would show up in the resulting CSS. So you were correct in your original expectation.

@lukeapage

This comment has been minimized.

Show comment
Hide comment
@lukeapage

lukeapage Feb 18, 2013

Member

just read the placeholders link and yes I think extending mixins is a better and more less way to do things and get the same functionality.

To calrify your above point

.clearfix() {
    &:before,
    &:after { content: " "; display: table; }
    &:after { clear: both; }
}
.something:extend( .clearfix() ) { }

/*
.something:before,
.something:after {
    content: " ";
    display: table;
}
.something:after {
    clear: both;
}
*/

and presumably if .clearfix() { definition is .clearfix { then calling it with or without brackets inside the extend definition will make no difference to the output..

Member

lukeapage commented Feb 18, 2013

just read the placeholders link and yes I think extending mixins is a better and more less way to do things and get the same functionality.

To calrify your above point

.clearfix() {
    &:before,
    &:after { content: " "; display: table; }
    &:after { clear: both; }
}
.something:extend( .clearfix() ) { }

/*
.something:before,
.something:after {
    content: " ";
    display: table;
}
.something:after {
    clear: both;
}
*/

and presumably if .clearfix() { definition is .clearfix { then calling it with or without brackets inside the extend definition will make no difference to the output..

@hax

This comment has been minimized.

Show comment
Hide comment
@hax

hax May 3, 2013

Using pseudo class syntax for extend feature is totally WRONG,
because "extend sth" is NOT equal to "match sth", it means nothing about DOM structure which a selector should.

You LESS guys have "invented" many bad ideas. The most famous one is "reuse' .xxx (class selector) as mixin notation. At least it ease the migration from plain CSS to preprocessor. But :extend syntax is worst idea I ever heard.

hax commented May 3, 2013

Using pseudo class syntax for extend feature is totally WRONG,
because "extend sth" is NOT equal to "match sth", it means nothing about DOM structure which a selector should.

You LESS guys have "invented" many bad ideas. The most famous one is "reuse' .xxx (class selector) as mixin notation. At least it ease the migration from plain CSS to preprocessor. But :extend syntax is worst idea I ever heard.

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert May 3, 2013

Contributor

I don't want to dignify this kind of rant on our Issues, but this isn't the first time I've heard these things so let's talk about CSS and clear the air.

You LESS guys have "invented" many bad ideas. The most famous one is "reuse' .xxx (class selector) as mixin notation. .... :extend syntax is worst idea I ever heard.

.xxx is called an implicit mixin. It works, and it's easy to understand. In fact, this syntax is not as "invasive" on the CSS spec as, say, using at-rules for styling actual. @keyframes come the closest to what would be described as styling and could maybe be considered an exception to what I'm saying since identifiers are used which match the identifier production in CSS syntax. Beyond keyframes, in general CSS at-rules are reserved mostly for higher-level configuration and style- or stylesheet manipulation based on "external" information, meaning outside of the styles themselves, like character encoding (@charset), or responding to device-specific conditions (@media).

Besides, I can think of worse ideas. Like using at-rules for styling is one of them, using two at-rules for the same feature is another. Of course, it all depends on your goals, if you want to programmatically manipulate styles without touching them personally, then there are probably advantages to using more obtuse and obvious grammar constructs that might be easier for a parser to pick up. Looks like you use Stylus, so I'm interested in hearing your point of view on why other syntaxes are advantageous.

"extend sth" is NOT equal to "match sth", it means nothing about DOM structure which a selector should.

Correct. Pseudo-classes with nth something are described as "structural" pseudo-classes by the CSS specification. However, there are 6 other types of pseudo-classes: "dynamic", "negation", "target", "blank", "UI element states" and "language". If the CSS specification did in fact describe an "extend" feature, it could sit quite elegantly as a category between the "negation" and "target" pseudo-classes.

Pseudo-classes allow selection based on information in the document tree, but this is probably not optimal use of the extend feature.

totally WRONG

A community that is larger than all the other preprocessors combined can't be wrong. What else is there to say?

Contributor

jonschlinkert commented May 3, 2013

I don't want to dignify this kind of rant on our Issues, but this isn't the first time I've heard these things so let's talk about CSS and clear the air.

You LESS guys have "invented" many bad ideas. The most famous one is "reuse' .xxx (class selector) as mixin notation. .... :extend syntax is worst idea I ever heard.

.xxx is called an implicit mixin. It works, and it's easy to understand. In fact, this syntax is not as "invasive" on the CSS spec as, say, using at-rules for styling actual. @keyframes come the closest to what would be described as styling and could maybe be considered an exception to what I'm saying since identifiers are used which match the identifier production in CSS syntax. Beyond keyframes, in general CSS at-rules are reserved mostly for higher-level configuration and style- or stylesheet manipulation based on "external" information, meaning outside of the styles themselves, like character encoding (@charset), or responding to device-specific conditions (@media).

Besides, I can think of worse ideas. Like using at-rules for styling is one of them, using two at-rules for the same feature is another. Of course, it all depends on your goals, if you want to programmatically manipulate styles without touching them personally, then there are probably advantages to using more obtuse and obvious grammar constructs that might be easier for a parser to pick up. Looks like you use Stylus, so I'm interested in hearing your point of view on why other syntaxes are advantageous.

"extend sth" is NOT equal to "match sth", it means nothing about DOM structure which a selector should.

Correct. Pseudo-classes with nth something are described as "structural" pseudo-classes by the CSS specification. However, there are 6 other types of pseudo-classes: "dynamic", "negation", "target", "blank", "UI element states" and "language". If the CSS specification did in fact describe an "extend" feature, it could sit quite elegantly as a category between the "negation" and "target" pseudo-classes.

Pseudo-classes allow selection based on information in the document tree, but this is probably not optimal use of the extend feature.

totally WRONG

A community that is larger than all the other preprocessors combined can't be wrong. What else is there to say?

@DesignByOnyx

This comment has been minimized.

Show comment
Hide comment
@DesignByOnyx

DesignByOnyx May 3, 2013

@hax - Mindless trolling could turn into an educated discussion if you proposed your own solution like everybody else on the :extend threads. After weeks of different suggestions and deliberation between very experienced front-end devs and heavy users of LESS, we came to a satisfactory solution with the :extend syntax. If you have a better suggestion, believe me - we are all ears.

@hax - Mindless trolling could turn into an educated discussion if you proposed your own solution like everybody else on the :extend threads. After weeks of different suggestions and deliberation between very experienced front-end devs and heavy users of LESS, we came to a satisfactory solution with the :extend syntax. If you have a better suggestion, believe me - we are all ears.

@matthew-dean

This comment has been minimized.

Show comment
Hide comment
@matthew-dean

matthew-dean May 3, 2013

Member

To add to @jonschlinkert, .this:not(.that) { } and .this:matches(.that) { } and .this:extend(.that) { } are categorically similar. That is: "Given selector 'this', relate it to selector 'that' in a particular way." Since LESS often extends concepts and syntax introduced in CSS, it's a pretty logical extension of the language. We pay close attention to the CSS spec, and as a result, mirror its idiosyncrasies. If there's oddness in the concept, it hopefully starts in CSS first. That's why in our mixin guards, "AND" is represented by the word "and", and "OR" is represented by a comma: because that's the way it is in media queries. Our goal is not to fix or change CSS, but make CSS far easier to work with, and to make LESS completely familiar for CSS authors. :extend is an example of that. If you know how to use :not, you know how to use :extend.

Member

matthew-dean commented May 3, 2013

To add to @jonschlinkert, .this:not(.that) { } and .this:matches(.that) { } and .this:extend(.that) { } are categorically similar. That is: "Given selector 'this', relate it to selector 'that' in a particular way." Since LESS often extends concepts and syntax introduced in CSS, it's a pretty logical extension of the language. We pay close attention to the CSS spec, and as a result, mirror its idiosyncrasies. If there's oddness in the concept, it hopefully starts in CSS first. That's why in our mixin guards, "AND" is represented by the word "and", and "OR" is represented by a comma: because that's the way it is in media queries. Our goal is not to fix or change CSS, but make CSS far easier to work with, and to make LESS completely familiar for CSS authors. :extend is an example of that. If you know how to use :not, you know how to use :extend.

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert May 19, 2013

Contributor

What if we used a more "implicit" syntax for this to avoid nesting parens and to make it easier to extend parametric mixins?

Today, we use a parametric mixin like this:

.square {
  .border-radius(9px);
}

Rather than extending the mixin like this (as you might extend a normal class):

.square {
  &:extend(.border-radius);
}

We could extend like this:

.box {
  .border-radius:extend(9px);
}
.square {
  .border-radius:extend(9px);
}
.rectangle {
  .border-radius:extend(4px);
}

The distinction is that the "extended mixin" ends in a semicolon and declares a value or values inside the parens, .border-radius:extend(9px);, rather than listing the classes to extend inside the parens and beginning a new selector block with curly braces, .border-radius:extend(.some-class) {}. IMHO, this is no less subtle than implicit mixins (.border-radius;), which is one of LESS's coolest features, again IMHO.

In the rendered output, any "extended parametric mixin" would be rendered at the place of the original mixin, like this:

.box, 
.square {
    -webkit-border-radius: 9px;
    -moz-border-radius: 9px;
    border-radius: 9px;
}
.rectangle {
    -webkit-border-radius: 4px;
    -moz-border-radius: 4px;
    border-radius: 4px;
}
.some-other-class, 
.another-class, 
.and-another {
    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;
}

So I personally like this because it's enough of a departure from the "normal" extend syntax inside selector blocks to make it obvious enough what's happening, and it goes along with the subtlety of existing less conventions where there is no need to over-explain what you're trying to accomplish in the code. This feature is definitely at the top of my personal wishlist.

Contributor

jonschlinkert commented May 19, 2013

What if we used a more "implicit" syntax for this to avoid nesting parens and to make it easier to extend parametric mixins?

Today, we use a parametric mixin like this:

.square {
  .border-radius(9px);
}

Rather than extending the mixin like this (as you might extend a normal class):

.square {
  &:extend(.border-radius);
}

We could extend like this:

.box {
  .border-radius:extend(9px);
}
.square {
  .border-radius:extend(9px);
}
.rectangle {
  .border-radius:extend(4px);
}

The distinction is that the "extended mixin" ends in a semicolon and declares a value or values inside the parens, .border-radius:extend(9px);, rather than listing the classes to extend inside the parens and beginning a new selector block with curly braces, .border-radius:extend(.some-class) {}. IMHO, this is no less subtle than implicit mixins (.border-radius;), which is one of LESS's coolest features, again IMHO.

In the rendered output, any "extended parametric mixin" would be rendered at the place of the original mixin, like this:

.box, 
.square {
    -webkit-border-radius: 9px;
    -moz-border-radius: 9px;
    border-radius: 9px;
}
.rectangle {
    -webkit-border-radius: 4px;
    -moz-border-radius: 4px;
    border-radius: 4px;
}
.some-other-class, 
.another-class, 
.and-another {
    -webkit-border-radius: 2px;
    -moz-border-radius: 2px;
    border-radius: 2px;
}

So I personally like this because it's enough of a departure from the "normal" extend syntax inside selector blocks to make it obvious enough what's happening, and it goes along with the subtlety of existing less conventions where there is no need to over-explain what you're trying to accomplish in the code. This feature is definitely at the top of my personal wishlist.

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert May 19, 2013

Contributor

Using the clearfix example I gave in my original request, this is what it would look like with my revised syntax:

.clearfix() {
    // ...
}
.navbar {
    .clearfix:extend(); // instead of &:extend(.clearfix());
}
.banner {
    .clearfix:extend();
    &:extend(.some-class); // "implicit mixin" being extended
}
Contributor

jonschlinkert commented May 19, 2013

Using the clearfix example I gave in my original request, this is what it would look like with my revised syntax:

.clearfix() {
    // ...
}
.navbar {
    .clearfix:extend(); // instead of &:extend(.clearfix());
}
.banner {
    .clearfix:extend();
    &:extend(.some-class); // "implicit mixin" being extended
}
@DesignByOnyx

This comment has been minimized.

Show comment
Hide comment
@DesignByOnyx

DesignByOnyx May 20, 2013

I like where you are going with this. I think a more friendly approach is to use an :extend on the end of existing mixin syntax as such this:

.box {
  .border-radius(9px):extend;
}
.square {
  .border-radius(9px):extend;
}
.rectangle {
  .border-radius(4px):extend;
}

Something about omitting the parens after the :extend makes if feel like it serves a different purpose than the existing extend syntax.

I like where you are going with this. I think a more friendly approach is to use an :extend on the end of existing mixin syntax as such this:

.box {
  .border-radius(9px):extend;
}
.square {
  .border-radius(9px):extend;
}
.rectangle {
  .border-radius(4px):extend;
}

Something about omitting the parens after the :extend makes if feel like it serves a different purpose than the existing extend syntax.

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert May 20, 2013

Contributor

I could go any way with this, but I prefer .border-radius:extend(9px); because it's consistent with extend syntax, IMO it's still obvious that it's a mixin, but it also implies that the parameters/values are being extended - which will help explain why the output is "grouped".

Contributor

jonschlinkert commented May 20, 2013

I could go any way with this, but I prefer .border-radius:extend(9px); because it's consistent with extend syntax, IMO it's still obvious that it's a mixin, but it also implies that the parameters/values are being extended - which will help explain why the output is "grouped".

@DesignByOnyx

This comment has been minimized.

Show comment
Hide comment
@DesignByOnyx

DesignByOnyx May 20, 2013

@jonschlinkert - by this point I hold your opinions in very high regard and will support any decision you think is best. I will say that your method feels as though the 9px is being passed to "extend" as opposed to being passed to the mixin itself... but I am cool with either.

@jonschlinkert - by this point I hold your opinions in very high regard and will support any decision you think is best. I will say that your method feels as though the 9px is being passed to "extend" as opposed to being passed to the mixin itself... but I am cool with either.

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert May 21, 2013

Contributor

@DesignByOnyx thanks for the kind words. What you're saying makes a lot of sense, my "lens" of extends (in Less) has been something like:

.this:extend(.that) {}

so you're point is consistent with my own view. @matthewdl or @lukeapage do either of you have any view/opinion on this? I think both syntaxes could work (and probably others), but admittedly I haven't focused on "future-proofing" with either syntax, so there could be some gotchas on either. I'd just love to see this happen, I think extending mixins is an exciting feature for Less, it will do more for generating DRY code than any other feature I can think of at the moment

Contributor

jonschlinkert commented May 21, 2013

@DesignByOnyx thanks for the kind words. What you're saying makes a lot of sense, my "lens" of extends (in Less) has been something like:

.this:extend(.that) {}

so you're point is consistent with my own view. @matthewdl or @lukeapage do either of you have any view/opinion on this? I think both syntaxes could work (and probably others), but admittedly I haven't focused on "future-proofing" with either syntax, so there could be some gotchas on either. I'd just love to see this happen, I think extending mixins is an exciting feature for Less, it will do more for generating DRY code than any other feature I can think of at the moment

@bdkjones

This comment has been minimized.

Show comment
Hide comment
@bdkjones

bdkjones May 21, 2013

Why can't the Less compiler just automatically "do the right thing"? In other words, if I have this mixin declared in my code:

.someMixin {
    color: red;
}

And then later I use it like this:

#someElement {
    .someMixin;
}

Why can't the compiler just be smart enough to optimize this Less code into this CSS:

.someMixin,
#someElement
{
    color:red;
}

Why should I, as the user, have to manually add an :extends keyword to get this behavior? The compiler should be smart enough to realize that this optimization can be done and then do it.

Personally, I think this :extends idea is confusing. The whole notion of an "extends" keyword means: "Take this thing X and add A, B, and C to it." But in this context, you propose to re-define extends to: "This thing X is actually the same as Y, so you can just declare Y and X to be equal and write it once." This goes against the standard notion of "extending" something.

Why can't the Less compiler just automatically "do the right thing"? In other words, if I have this mixin declared in my code:

.someMixin {
    color: red;
}

And then later I use it like this:

#someElement {
    .someMixin;
}

Why can't the compiler just be smart enough to optimize this Less code into this CSS:

.someMixin,
#someElement
{
    color:red;
}

Why should I, as the user, have to manually add an :extends keyword to get this behavior? The compiler should be smart enough to realize that this optimization can be done and then do it.

Personally, I think this :extends idea is confusing. The whole notion of an "extends" keyword means: "Take this thing X and add A, B, and C to it." But in this context, you propose to re-define extends to: "This thing X is actually the same as Y, so you can just declare Y and X to be equal and write it once." This goes against the standard notion of "extending" something.

@jonschlinkert

This comment has been minimized.

Show comment
Hide comment
@jonschlinkert

jonschlinkert May 21, 2013

Contributor

Yeah, I was thinking that same exact thing earlier and was going to post it, but after thinking about it decided that automatically applying "extend behavior" to mixins is too opinionated for Less.js. Specifically, even though selector inheritance (extend) is an awesome concept that is super beneficial for code reduction, the vast majority of the complaints I've read about the feature is that it adds a layer of abstraction that makes it difficult to comb through code and debug when there are problems.

So great minds think alike, but I down-vote the idea personally because a) we shouldn't mess with "normal" mixins at all until the extend feature is completely stable and the spec is more complete, b) I think many developers want to make this call for themselves, and c) oftentimes things seem so obvious and cut-and-dried, when the fact of the matter is that we're forgetting about many of the eccentricities about mixins that would make your suggestion difficult to implement at minimum, and probably impossible to implement whilst still enabling developers to use all of the "mixin hacks" we've... ahem, they've come to know and love.

Contributor

jonschlinkert commented May 21, 2013

Yeah, I was thinking that same exact thing earlier and was going to post it, but after thinking about it decided that automatically applying "extend behavior" to mixins is too opinionated for Less.js. Specifically, even though selector inheritance (extend) is an awesome concept that is super beneficial for code reduction, the vast majority of the complaints I've read about the feature is that it adds a layer of abstraction that makes it difficult to comb through code and debug when there are problems.

So great minds think alike, but I down-vote the idea personally because a) we shouldn't mess with "normal" mixins at all until the extend feature is completely stable and the spec is more complete, b) I think many developers want to make this call for themselves, and c) oftentimes things seem so obvious and cut-and-dried, when the fact of the matter is that we're forgetting about many of the eccentricities about mixins that would make your suggestion difficult to implement at minimum, and probably impossible to implement whilst still enabling developers to use all of the "mixin hacks" we've... ahem, they've come to know and love.

@josh18

This comment has been minimized.

Show comment
Hide comment
@josh18

josh18 Sep 26, 2014

I'm trying to find more info about this but it's like a maze reading through everything. Did this ever get implemented? If so can someone kindly point me to the appropriate area in the docs.

josh18 commented Sep 26, 2014

I'm trying to find more info about this but it's like a maze reading through everything. Did this ever get implemented? If so can someone kindly point me to the appropriate area in the docs.

@seven-phases-max

This comment has been minimized.

Show comment
Hide comment
@seven-phases-max

seven-phases-max Sep 26, 2014

Member

@josh18 No, when a feature request is still open this usually means it's not implemented.

Member

seven-phases-max commented Sep 26, 2014

@josh18 No, when a feature request is still open this usually means it's not implemented.

@josh18

This comment has been minimized.

Show comment
Hide comment
@josh18

josh18 Sep 26, 2014

Ok thanks, thought I'd just double check just in case I was missing something.

josh18 commented Sep 26, 2014

Ok thanks, thought I'd just double check just in case I was missing something.

@matthew-dean

This comment has been minimized.

Show comment
Hide comment
@matthew-dean

matthew-dean Sep 26, 2014

Member

I'm planning at some point to summarize open / to-be-implemented features in the Wiki, but haven't had the time yet.

Member

matthew-dean commented Sep 26, 2014

I'm planning at some point to summarize open / to-be-implemented features in the Wiki, but haven't had the time yet.

@mahnunchik

This comment has been minimized.

Show comment
Hide comment
@mahnunchik

mahnunchik Oct 5, 2014

I'm planning at some point to summarize open / to-be-implemented features in the Wiki, but haven't had the time yet.

@matthew-dean +1

I'm planning at some point to summarize open / to-be-implemented features in the Wiki, but haven't had the time yet.

@matthew-dean +1

@dunerunner

This comment has been minimized.

Show comment
Hide comment
@dunerunner

dunerunner Nov 4, 2014

Hi guys! As far as I understand this feature will be somewhat similar to SASS placeholders. Just wanted to know when will this be implemented?

Hi guys! As far as I understand this feature will be somewhat similar to SASS placeholders. Just wanted to know when will this be implemented?

@lukeapage

This comment has been minimized.

Show comment
Hide comment
@lukeapage

lukeapage Nov 4, 2014

Member

Hi,
I find it difficult to predict my time and other contributors just
implement things they are interested in, so im not sure. All i can say is
that we do consider it high priority, its the next big thing on my list.

Member

lukeapage commented Nov 4, 2014

Hi,
I find it difficult to predict my time and other contributors just
implement things they are interested in, so im not sure. All i can say is
that we do consider it high priority, its the next big thing on my list.

@dunerunner

This comment has been minimized.

Show comment
Hide comment
@dunerunner

dunerunner Nov 4, 2014

Thank you for your answer. Looking forward to seeing this implemented and working. :)

Thank you for your answer. Looking forward to seeing this implemented and working. :)

@Justineo

This comment has been minimized.

Show comment
Hide comment
@Justineo

Justineo Feb 5, 2015

Contributor

+1 for this feature. It's extremely helpful in reducing CSS size.

Contributor

Justineo commented Feb 5, 2015

+1 for this feature. It's extremely helpful in reducing CSS size.

@yankun01

This comment has been minimized.

Show comment
Hide comment
@yankun01

yankun01 Feb 10, 2015

+1 for this feature.

+1 for this feature.

@elielmiller

This comment has been minimized.

Show comment
Hide comment
@elielmiller

elielmiller Feb 13, 2015

+1 for this feature.

+1 for this feature.

@ptim

This comment has been minimized.

Show comment
Hide comment
@ptim

ptim Feb 25, 2015

+1 watching with interest, thanks!

ptim commented Feb 25, 2015

+1 watching with interest, thanks!

@Grawl

This comment has been minimized.

Show comment
Hide comment

Grawl commented Apr 7, 2015

👍

@Grawl

This comment has been minimized.

Show comment
Hide comment
@Grawl

Grawl Apr 7, 2015

it's TWO YEARS passed since this issue was created. High Priority tag since Nov 2014. Milestone is 1.6.0 or 2.0.0. Great. Less is 2.5 now.

Grawl commented Apr 7, 2015

it's TWO YEARS passed since this issue was created. High Priority tag since Nov 2014. Milestone is 1.6.0 or 2.0.0. Great. Less is 2.5 now.

@seven-phases-max

This comment has been minimized.

Show comment
Hide comment
@seven-phases-max

seven-phases-max Apr 7, 2015

Member

@Grawl

You mean you're ready to make a PR?

Member

seven-phases-max commented Apr 7, 2015

@Grawl

You mean you're ready to make a PR?

@kitsunde

This comment has been minimized.

Show comment
Hide comment
@kitsunde

kitsunde Apr 7, 2015

@seven-phases-max That's pretty much what I thought. Such a display of entitlement. ;)

kitsunde commented Apr 7, 2015

@seven-phases-max That's pretty much what I thought. Such a display of entitlement. ;)

@Grawl

This comment has been minimized.

Show comment
Hide comment
@Grawl

Grawl Apr 7, 2015

@seven-phases-max lol no I'm just frontend/designer.
@CelC looks really bad 😅

Grawl commented Apr 7, 2015

@seven-phases-max lol no I'm just frontend/designer.
@CelC looks really bad 😅

@matthew-dean

This comment has been minimized.

Show comment
Hide comment
@matthew-dean

matthew-dean Apr 7, 2015

Member

it's TWO YEARS passed since this issue was created.

Yeah, what am I paying you people for, anyway? ;-)

Member

matthew-dean commented Apr 7, 2015

it's TWO YEARS passed since this issue was created.

Yeah, what am I paying you people for, anyway? ;-)

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Jul 20, 2015

Sadly can't help with participation, but i highly upvote this request!

This is extremely important functionality for building complex and effective frameworks

ghost commented Jul 20, 2015

Sadly can't help with participation, but i highly upvote this request!

This is extremely important functionality for building complex and effective frameworks

@stevenvachon

This comment has been minimized.

Show comment
Hide comment
@stevenvachon

stevenvachon Mar 2, 2016

3 years and counting. Fortunately, Sass v4 is coming (with sass-* prefixed functions) and I can get rid of Less.

3 years and counting. Fortunately, Sass v4 is coming (with sass-* prefixed functions) and I can get rid of Less.

@SomMeri

This comment has been minimized.

Show comment
Hide comment
@SomMeri

SomMeri Mar 4, 2016

Member

@stevenvachon We hold no grudge against Sass. Of course they are competitors in a sense, but projects have different philosophy and trying to hurt us by invoking them is senseless.

Of course, pull requests are welcome, from anyone. We will gladly merge in functional pull request with this feature.

Member

SomMeri commented Mar 4, 2016

@stevenvachon We hold no grudge against Sass. Of course they are competitors in a sense, but projects have different philosophy and trying to hurt us by invoking them is senseless.

Of course, pull requests are welcome, from anyone. We will gladly merge in functional pull request with this feature.

@stevenvachon

This comment has been minimized.

Show comment
Hide comment
@stevenvachon

stevenvachon Mar 7, 2016

I'm not trying to hurt anyone, in fact probably trying to prevent such. I think it's better to express how one may feel and the new directions they may be taking as a result. I think that it's better to know sooner than later; before everyone leaves. For example, Bootstrap v4 will not use Less.js and I'm sure that will put a big dent on your user base. You can ignore such politics all you want, of course.

I'm not trying to hurt anyone, in fact probably trying to prevent such. I think it's better to express how one may feel and the new directions they may be taking as a result. I think that it's better to know sooner than later; before everyone leaves. For example, Bootstrap v4 will not use Less.js and I'm sure that will put a big dent on your user base. You can ignore such politics all you want, of course.

@krismeister

This comment has been minimized.

Show comment
Hide comment
@krismeister

krismeister Mar 7, 2016

@stevenvachon why so offtopic? Sass and Less are both great. I love pure JS-ness of less. node-sass needs a c compiler to get installed, which can be a pain depending on the environment. I've used the :extend feature that is already built in LESS and meets all my needs. I don't even know why this issue is still open.

Heck, I'm a rails developer and use gulp+LESS when it's not a ruby project.

@stevenvachon why so offtopic? Sass and Less are both great. I love pure JS-ness of less. node-sass needs a c compiler to get installed, which can be a pain depending on the environment. I've used the :extend feature that is already built in LESS and meets all my needs. I don't even know why this issue is still open.

Heck, I'm a rails developer and use gulp+LESS when it's not a ruby project.

@stevenvachon

This comment has been minimized.

Show comment
Hide comment
@stevenvachon

stevenvachon Mar 7, 2016

Off topic? This feature has not been implemented in 3 years and it'd be very useful.

I'd prefer if Sass were written in JS, but it isn't, and that isn't what's most important. Its features are. Sass allows us to extend placeholders but Less does not allow us to extend mixins.

Off topic? This feature has not been implemented in 3 years and it'd be very useful.

I'd prefer if Sass were written in JS, but it isn't, and that isn't what's most important. Its features are. Sass allows us to extend placeholders but Less does not allow us to extend mixins.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Mar 7, 2016

Dude it's not offtopic at all, but highly anticipated feature! (Even though i'd prefer less anyway, for various reasons)

It just beggs to be made.

P.S. In my case, i'am actually designer with just some knowledge of js, mostly dom related stuff, really far from developer that can contribute to less.js codebase..Which is sad story anyway)

Just an extremely interested supporter of project)

ghost commented Mar 7, 2016

Dude it's not offtopic at all, but highly anticipated feature! (Even though i'd prefer less anyway, for various reasons)

It just beggs to be made.

P.S. In my case, i'am actually designer with just some knowledge of js, mostly dom related stuff, really far from developer that can contribute to less.js codebase..Which is sad story anyway)

Just an extremely interested supporter of project)

@matthew-dean

This comment has been minimized.

Show comment
Hide comment
@matthew-dean

matthew-dean Mar 7, 2016

Member

Public Service Announcement

At any point in time, you may submit a pull request, or work with a developer to get one in, and it's very likely this feature be merged in. The Less.js library needs more regular contributions from individuals like the people in this thread. It's not any one person's responsibility. It's entirely dependant on one individual seeing this thread, or needing this feature, and taking the time to make it happen.

If your response is that you're not a developer, then there are many OTHER ways you can support this project in non-developmental roles, be it providing needed documentation for new features, or design support on the website, running tests, providing feedback on issues, project managing, answering questions on Stack Overflow, writing blog posts, tweeting about Less, contributing to CSS and web communities, and writing Less libraries.

Many of these tasks are being done by individuals who are developers, so the time they could be contributing to development is spent on these other tasks.

If you are a developer, and your response is, "I don't have the time," then that's the exact reason for why this issue has sat open. It's 100% up to you if a feature is completed, so asking why it hasn't been completed by "someone" is not useful. You are that someone. It will happen, I guarantee it will happen, if and when you get involved in this project. You can become involved in one of the most popular open source tools on the web. You can make a difference in the lives of... thousands? Hundreds of thousands? Millions? And as a side benefit, you can make sure that your favorite features happen sooner rather than later.

If you want this or any feature to happen, make it happen. We would love to have you. We would love to work with you! Less can keep getting better and better the larger this community grows!

And, listen, I appreciate that sometimes people really have absolutely no time to contribute and yet still would really like a particular feature to happen. That's fine. I would just say that if you're in that scenario, that you aim for empathy and gratitude for people donating their time (and sometimes money) to help you, and I'm sure other people in the Less community will do their best to continue to do so, as they are able.

Sincerely,
Matthew Dean, Member of Less.js Core Team

Member

matthew-dean commented Mar 7, 2016

Public Service Announcement

At any point in time, you may submit a pull request, or work with a developer to get one in, and it's very likely this feature be merged in. The Less.js library needs more regular contributions from individuals like the people in this thread. It's not any one person's responsibility. It's entirely dependant on one individual seeing this thread, or needing this feature, and taking the time to make it happen.

If your response is that you're not a developer, then there are many OTHER ways you can support this project in non-developmental roles, be it providing needed documentation for new features, or design support on the website, running tests, providing feedback on issues, project managing, answering questions on Stack Overflow, writing blog posts, tweeting about Less, contributing to CSS and web communities, and writing Less libraries.

Many of these tasks are being done by individuals who are developers, so the time they could be contributing to development is spent on these other tasks.

If you are a developer, and your response is, "I don't have the time," then that's the exact reason for why this issue has sat open. It's 100% up to you if a feature is completed, so asking why it hasn't been completed by "someone" is not useful. You are that someone. It will happen, I guarantee it will happen, if and when you get involved in this project. You can become involved in one of the most popular open source tools on the web. You can make a difference in the lives of... thousands? Hundreds of thousands? Millions? And as a side benefit, you can make sure that your favorite features happen sooner rather than later.

If you want this or any feature to happen, make it happen. We would love to have you. We would love to work with you! Less can keep getting better and better the larger this community grows!

And, listen, I appreciate that sometimes people really have absolutely no time to contribute and yet still would really like a particular feature to happen. That's fine. I would just say that if you're in that scenario, that you aim for empathy and gratitude for people donating their time (and sometimes money) to help you, and I'm sure other people in the Less community will do their best to continue to do so, as they are able.

Sincerely,
Matthew Dean, Member of Less.js Core Team

@stevenvachon

This comment has been minimized.

Show comment
Hide comment
@stevenvachon

stevenvachon Mar 7, 2016

I already support my own projects and I listen to their feature requests. I honestly don't have time to dig into Less.js core.

I already support my own projects and I listen to their feature requests. I honestly don't have time to dig into Less.js core.

@stevenvachon

This comment has been minimized.

Show comment
Hide comment
@stevenvachon

stevenvachon Aug 9, 2016

For those coming here for sass placeholder (or "silent class") support, read this comment. It won't get you all the way there (due to #1851 and having such classes not in a "referenced" file), but it's better than nothing.

stevenvachon commented Aug 9, 2016

For those coming here for sass placeholder (or "silent class") support, read this comment. It won't get you all the way there (due to #1851 and having such classes not in a "referenced" file), but it's better than nothing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment