-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
Comments
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..
rather than
or have I misunderstood? |
I would love have both, parametric and usual mixins, to have
or
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
is shorter than
and for more complicated examples that could be critical, and I know some people switched to SASS just because of this shortage |
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 .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 |
@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 |
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;
} |
@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. |
@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. |
Actually .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. |
@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: 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. |
@jonschlinkert - |
good point, I agree. |
I agree that the brackets looks and reads nice, but yeah we have to stick with syntax we have already chosen. |
thumb up for extend(N) syntax, more feels like nature CSS, same reason as @agatronic |
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:
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? |
That's how I get it DESIRED FINAL CSS OUTPUT
THE WAY YOU HAS TO GO WITH CURRENT VERSION OF LESS TO GET DESIRED OUTPUT
SUGESSTED LESS SYNTAX
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 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 |
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. |
I feel that SASS
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? |
@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 it is the first version of extend which was pulled from a pull request ready for 1.4.0 - it represents the extend node |
thank you @agatronic, now I see how much I missed ;) |
@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.
and
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:
But this is just one example. Consider that at one point in Twitter Bootstrap the 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? |
Thanks. I think I understand the use case, and I think this line says it best:
That makes sense to me. Probably what I'm getting hung up is that the overall 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):
... then thumbs up from me. But, for me, all of that depends on what/how/if we resolve |
@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.
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. |
I am jumping in on this discussion and would like to bring clarity for myself on the following comment:
So, going with a more generic clearfix example, is this the LESS and resulting CSS?:
I originally expected for the |
I'm glad you're asking, but no, only the |
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
and presumably if |
Using pseudo class syntax for extend feature is totally WRONG, 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. |
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.
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.
Correct. Pseudo-classes with Pseudo-classes allow selection based on information in the document tree, but this is probably not optimal use of the extend feature.
A community that is larger than all the other preprocessors combined can't be wrong. What else is there to say? |
@hax - Mindless trolling could turn into an educated discussion if you proposed your own solution like everybody else on the |
Thank you for your answer. Looking forward to seeing this implemented and working. :) |
+1 for this feature. It's extremely helpful in reducing CSS size. |
+1 for this feature. |
1 similar comment
+1 for this feature. |
+1 watching with interest, thanks! |
👍 |
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. |
You mean you're ready to make a PR? |
@seven-phases-max That's pretty much what I thought. Such a display of entitlement. ;) |
@seven-phases-max lol no I'm just frontend/designer. |
Yeah, what am I paying you people for, anyway? ;-) |
Sadly can't help with participation, but i highly upvote this request! This is extremely important functionality for building complex and effective frameworks |
3 years and counting. Fortunately, Sass v4 is coming (with |
@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. |
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. |
@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. |
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. |
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) |
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, |
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. |
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. |
This feature request was proposed as a solution to this issue #1155
This is the synopsis
and the compiled result will be:
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.
The text was updated successfully, but these errors were encountered: