Using LESS, is it possible to extend parametric mixins? - css

I'm new to LESS and I'm just experimenting with it, using version 1.5. I discovered the useful extend command, but I was wondering if that could be applied to parametric mixins as well as static ones. Apparently, this doesn't seem possible, based on my experiments:
This works
.some-mixin {
}
.child {
&:extend(.some-mixin);
}
This doesn't work and throws an "unexpected token" error:
.some-mixin(#color, #bgcolor) {
color: #color;
background-color: #bgcolor;
}
.child1 {
&:extend(.some-mixin(red, blue));
border: 1px solid blue;
}
.child2 {
&:extend(.some-mixin(red, blue));
border: 1px solid green;
}
.child3 {
&:extend(.some-mixin(red, blue));
border: 1px solid red;
}
Is this a current limitation of LESS, or am I using it incorrectly? Thanks in advance for the answers.
Edit - Added expected output, as per request
What I would expect makes more sense when there are more children extending the parametric mixin:
.child1,
.child2,
.child3 {
color: red;
background-color: blue;
}
.child1 {
border: 1px solid blue;
}
.child2 {
border: 1px solid green;
}
.child3 {
border: 1px solid red;
}

I'm not sure what you are trying to achieve (that is, I am not sure what you expect the :extend() code to actually do if it were extending the parameteric mixin). If your desire is to define the colors of .child, then using it as a straight mixin works:
LESS
.some-mixin(#color, #bgcolor) {
color: #color;
background-color: #bgcolor;
}
.child {
.some-mixin(red, blue);
}
CSS Output
.child {
color: #ff0000;
background-color: #0000ff;
}
This also makes .child itself a mixin for the red and blue color combination, which I think would have been a net result of the extension working if it had worked. That is, I would expect your second set of code to have produced something like this (theoretically; this does not actually work nor is it actually produced in LESS):
.some-mixin(#color, #bgcolor),
.child(#color: red, #bgcolor: blue) {
color: #color;
background-color: #bgcolor;
}
But these two are nearly equivalent as mixins (one has the added parameters):
/* theoretical mixin if extension worked */
.child(#color: red, #bgcolor: blue) {
color: #color;
background-color: #bgcolor;
}
/* code from straight use of .some-mixin in .child */
.child {
color: #ff0000;
background-color: #0000ff;
}
So that either of the above used like so will get the result of mixing in the child values to the new selector:
LESS
.test {
.child; /* or using .child(); */
}
CSS Output
.test {
color: #ff0000;
background-color: #0000ff;
}

No, currently this is not supported. But it's planned to be implemented in future versions.

Related

why variables in css is not working although I had read a lot about it?

I have variables in my css but it isn't recognized.I have tried setting variable like the code below but when I run it in chrome it doesn't work.
li {
border: 2px solid red;
}
:special {
background: yellow;
--col: blue;
}
.completed {
text-decoration: line-through lime;
color: var(--col);
}
but when I set to blue directly it works like that
li {
border: 2px solid red;
}
:special {
background: yellow;
--col: blue;
}
.completed {
text-decoration: line-through lime;
color: blue;
}
I don't understand what is the problem.
:special isn't a recognised selector which is most likely causing your problem here. People tend to add global custom CSS property declarations to the :root {} selector. Or simply scope them to the parent selector that you're using.
:root {
--col: blue;
}
.class-name {
color: var(--col);
}
:special is an invalid selector. Rules in invalid selectors are ignored as per the specification, so your variable is never defined.

Property for specific selector

1. Summary
I have list of selectors, to which properties should always apply.
For some selectors must be additionally added another properties.
I can't find, how I can do it without duplicates.
2. MCVE
2.1. Expected CSS
.KiraFirst,
.KiraSecond,
.KiraThird {
color: red;
}
.KiraSecond {
background-color: yellow;
}
In example, I use class .KiraSecond 2 times. Can I get expected behavior without this duplicate?
2.2. Stylus
Live demo on stylus-lang.com
.KiraFirst
.KiraSecond
.KiraThird
color red
.KiraSecond
background-color yellow
This is compiled to expected CSS, but I still use .KiraSecond 2 times.
I don't understand, how I can not use duplicate. For example, syntax as this not compile to expected CSS:
.KiraFirst
.KiraSecond
background-color yellow
.KiraThird
color red
Result:
.KiraFirst,
.KiraSecond {
background-color: #ff0;
}
.KiraThird {
color: #f00;
}
3. Not helped
Stylus official documentation include Selectors section
Stack Overflow Stylus questions
Stylus GitHub issues
Maybe you can use basic class for all elements? For example - .Kira and if you need to specify something for other elements you can add extra class .KiraSecond or use .Kira:nth-child(2)
in your example it can be something like this
.Kira {
color: red;
}
.KiraSecond {
background-color: yellow;
}
or
.Kira {
color: red;
}
.Kira:nth-child(2) {
background-color: yellow;
}
You (can't)? and you shouldn't.
Duplicating that selector in that case is not a bad practice.
you are not duplicating the same property/value for many classes
you can clearly override specific property
you can clearly modify/change behaviour for specific class
e.g:
.class1, .class2, .class3 {
color: red;
background: yellow;
border: 1px solid;
}
.class1:hover {
color: blue;
}
.class2 {
border: 2px dotted;
}
.class3 {
color: pink;
}
What would be a bad practice in that case (with no selector duplication)
.class1 {
color: blue;
background: yellow;
border: 1px solid;
}
.class2 {
color: red;
background: yellow;
border: 2px dotted;
}
.class3 {
color: pink;
background: yellow;
border: 1px solid;
}

In Sass, what's the difference between the #mixin and #extend directives?

I just finished with the Sass guide.
The guide explains mixins:
..A mixin lets you make groups of CSS declarations that you want to
reuse throughout your site. You can even pass in values to make your
mixin more flexible.
and extend:
.. This is one of the most useful features of Sass. Using #extend lets
you share a set of CSS properties from one selector to another ..
It looks like 'extend' may be implemented in 'mixin' (it seems 'mixin' is extend of 'extend' :-) ).
// #extend
.message {
border: 1px solid #ccc;
padding: 10px;
color: #333;
}
.success {
#extend .message;
border-color: green;
}
.error {
#extend .message;
border-color: red;
}
.warning {
#extend .message;
border-color: yellow;
}
// #mixin
#mixin message($color) {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: $color;
}
.success { #include message(green); }
.error { #include message(red); }
.warning { #include message(yellow); }
and even more because mixins have params.
But on the other hand the processed CSS is not exactly the same. But it will be same style effect on the DOM.
/* extend processed */
.message, .success, .error, .warning {
border: 1px solid #ccc;
padding: 10px;
color: #333; }
.success {
border-color: green; }
.error {
border-color: red; }
.warning {
border-color: yellow; }
/* mixin processed */
.success {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: green; }
.error {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: red; }
.warning {
border: 1px solid #ccc;
padding: 10px;
color: #333;
border-color: yellow; }
My question is how do these features differ?
When should I use one over the other?
From http://blog.nakulrajput.com/mixins-extends-and-placeholders/:
#mixin
Here is how mixins work. Definition and usage:
#mixin awesome {
width: 100%;
height: 100%;
}
body {
#include awesome;
}
p {
#include awesome;
}
The snippets above produce the following CSS:
body {
width: 100%;
height: 100%;
}
p {
width: 100%;
height: 100%;
}
To make things a little bit more interesting, we could make our mixin accept parameters. Even better, we are able to define default values if the mixin is called without arguments.
#mixin awesome($w: 100%, $h: 100%) {
width: $w;
height: $h;
}
body {
#include awesome(960px);
}
p {
#include awesome;
}
The result will be similar, but the width of the body is different.
body {
width: 960px;
height: 100%;
}
p {
width: 100%;
height: 100%;
}
If you use mixins, the styles in them are duplicated for each selector.
Mixins are very helpful if you need to change or calculate something in the final output, for example if you need to apply border-radius to several elements.
However, in some other cases there is a lot of duplicative code, which could be avoided if you use #extend.
**#extend**
.awesome {
width: 100%;
height: 100%;
}
body {
#extend .awesome;
}
p {
#extend .awesome;
}
It's similar, isn't it. In Sass it looks almost identical, but the CSS the result is:
.awesome, body, p {
width: 100%;
height: 100%;
}
Shorter than the version using a mixin. You can't pass parameters during the extending, but that's not the idea actually.
#extend should be used in those places where you want to share properties between the elements.
Well, Mixin is like function that can do some work and output processed result while extend is like pre-defined cop-paste code
In programming terms:
 #include is like calling a function with or without parameters
 #extend is like Inheritance
Function means, every time we call the function, the body of the function gets duplicated as we might pass dynamic information in the form of parameters. so you would get a Copy of the body.
Inheritance means, there is no duplication and we get a Reference instead of copy. so who ever extends that reference would get the same body.

Less nested rules get parent properties

Hello I am wondering is it possible to do something like this in less. I have this css:
.parent{display: block; color: red; border: yellow 1px solid;}
.parent a, .parent a.special-link{color: blue; border-color: green;}
I would write it in less like this:
.parent{
display: block;
color: red;
border: yellow 1px solid;
a, a.special-link{
color: blue; border-color: green;
}
}
And rules are ok but what if in further developing I have to add something to :hover but only for it eg. padding: 20px; What is the best way to do this? My first thought is that if there is some kind of workaround/hack/selector that allows to inherit all properties of parent.
I doubt I clearly understand your exact needs (":hover" of what? "only" for what "it"?)
But in general it usually goes like this:
.parent {
display: block;
color: red;
border: yellow 1px solid;
a {
// <a> properties:
// ...
&, &.special-link {
// <a> and <a.special-link> properties:
// ...
color: blue;
border-color: green;
}
&.special-link {
// <a.special-link> properties:
// ...
}
&:hover {
// <a:hover> properties:
// ...
}
/// etc. etc. etc.
}
}

LESS - generate background and border classes for colors

I need to create classes for ~20 colors, but for each one i need to create two - one for background-color and second one for border. I know I can do it like this for every single color:
#green: #00A300;
.green-background {
background-color: #green;
}
.green-border {
border: 1px solid #green;
}
But I think there should be more effective way. Something like that I specify variables and then it loop all colors and generate CSS into pattern:
.[color]-background {
background-color: [#color];
}
.[color]-border {
border: 1px solid [#color];
}
Is this even possible?
This isn't too hard to do with a mixin using Selector interpolation:
LESS:
.color(#name, #value) {
//selector interpolation works when the entire
//variable is used as the selector
#bg-name: ~"#{name}-background";
#border-name: ~"#{name}-border";
.#{bg-name} {
background-color: #value;
}
.#{border-name} {
border: 1px solid #value;
}
}
//be sure to quote the first parameter in case your color name gets
//interpreted as a value, blue would pass #00F which you don't want
.color('blue', #0000FF);
CSS:
.blue-background {
background-color: #0000ff;
}
.blue-border {
border: 1px solid #0000ff;
}

Resources