Reputation: 838
I've been trying to get the following guarded mixins to work correctly in our LESS stylesheets:
#font {
.body( @size: 15px, @lineHeight: 18px, @weight: normal ) {
font: @weight @size~"/"@lineHeight Arial, sans-serif;
}
.marginLeft( @margin ) when ( @margin = 0 ) { }
.marginLeft( @margin ) when not ( @margin = 0 ) {
margin-left: @margin;
}
.marginTop( @margin ) when ( @margin = 0 ) { }
.marginTop( @margin ) when not ( @margin = 0 ) {
margin-top: @margin;
}
.DinBold( @size: 14px, @lineHeight: 20px, @offsetTop: 0, @offsetLeft: 0 ) {
#font > .marginLeft( @offsetLeft );
#font > .marginTop( @offsetTop );
font: @size~"/"@lineHeight 'DINBold', Arial, sans-serif;
}
}
The idea here being that if any of the font offsets are zero, I don't want the margin style to be set. Now, it works fine when the two parameters are non-zero, like:
#font > .DinBold( 42px, 42px, -7px, -3px );
But the moment @offsetLeft is 0, either explicitly or implicitly:
#font > .DinBold( 42px, 42px, -7px );
or
#font > .DinBold( 42px, 42px, -7px, 0 );
it seems that even the margin-top won't be exposed. The same thing happens if you flip it around, putting the marginTop mixin before the marginLeft mixin, and passing in 0 for @offsetTop instead, which seems to suggest to me that the first time an empty mixin is hit, all subsequent mixin calls might be ignored - any insights on this?
Upvotes: 4
Views: 358
Reputation: 707
I've just been struggling with the same issue, reworking some LESS that compiled fine with lessphp, but not with lessjs. Seems empty mixins prevent all following mixins in the same ruleset or containing mixin from rendering. But put any content in the empty mixin and everything works fine.
So the simple solution was to put a LESS comment (//) in the empty mixin, to my surprise this worked fine. Just two simple forward slashes on their own line with nothing else, LESS comments won't render in the output CSS, so you have your empty mixin.
Upvotes: 1
Reputation: 72271
I scrapped the previous answers, since they were not working for you. I am rather surprised that they don't work, since the LESS information would seem to indicate that it should be able to handle a non-zero case.
I have a new idea, however, based on pattern matching. Try the following. It is designed to allow you to pass in only two parameters if no margin is to be set, or four parameters, but the third parameter could be "top" or "left" to allow the fourth parameter to only set one or the other, or you can pass two numbers and set both top and left (in that order). This avoids calling the .marginLeft/Top
if not needed, and accepts a 0
if you choose to pass one in.
#font {
.body( @size: 15px, @lineHeight: 18px, @weight: normal ) {
font: @weight @size~"/"@lineHeight Arial, sans-serif;
}
.marginLeft( @margin ) when isnumber(@margin) {
margin-left: @margin;
}
.marginTop( @margin ) when isnumber(@margin) {
margin-top: @margin;
}
.DinBold( @size: 14px, @lineHeight: 20px) {
font: @size~"/"@lineHeight 'DINBold', Arial, sans-serif;
}
.DinBold( @size: 14px, @lineHeight: 20px, top, @offsetTop: 0 ) {
#font > .marginTop( @offsetTop );
font: @size~"/"@lineHeight 'DINBold', Arial, sans-serif;
}
.DinBold( @size: 14px, @lineHeight: 20px, left, @offsetLeft: 0 ) {
#font > .marginLeft( @offsetLeft );
font: @size~"/"@lineHeight 'DINBold', Arial, sans-serif;
}
.DinBold( @size: 14px, @lineHeight: 20px, @offsetTop: 0, @offsetLeft: 0 ) {
#font > .marginLeft( @offsetLeft );
#font > .marginTop( @offsetTop );
font: @size~"/"@lineHeight 'DINBold', Arial, sans-serif;
}
}
Upvotes: 0