Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Less border-radius shorthand mixin, disable variable

I am trying to write a mixin for border-radius than only outputs when the values, set by a variable, are >= 0. I set the base value in a variable as 3px, so if I enter -1 or no for example, the border-radius mixin would not create any properties in the final stylesheet. I can get this to work for if I want to have the same value for every corner. But I can't workout how to get it working if I want to use the shorthand i.e 3px 3px 0 0. I think it is an issue with the 3px being changed by a variable and 0 in both scenarios. My code at the moment is

.border-radius(@r) when not (@r = no), (@r = 0) {
    -webkit-border-radius: @r;
       -moz-border-radius: @r;
            border-radius: @r;
}
.border-radius(@r) when (@r = no), (@r = 0) {}

@baseBorderRadius: 3px;
.class1 { .border-radius(@baseBorderRadius); }
// This outputs fine: 3px 3px 3px 3px
.class2 { .border-radius(@baseBorderRadius @baseBorderRadius 0 0); }
// This outputs fine 3px 3px 0 0

@baseBorderRadius: no; // If I change the variable to try and disable/not run the mixin
.class1 { .border-radius(@baseBorderRadius); }
// This does what I want and doesn't run the mixin
.class2 { .border-radius(@baseBorderRadius @baseBorderRadius 0 0); }
// THIS IS THE PROBLEM! This outputs: no no 0 0

So I need a way to disable/not run the mixin if it contains a certain value or word defined from a global variable. I am doing this for a theme variables file where, based on the branding, companies might want rounded corners or not and I would prefer not to have loads of 0 values unnecessarily included in the final stylesheet.

I would really appreciate any help with this, even if it is just to find out that what I want to do isn't possible within LESS. Thank you

like image 702
AndyD Avatar asked Apr 18 '13 10:04

AndyD


2 Answers

You could try something like this, with multi-parametric mixins ... and check with the guards for each parameter separately, I wrote the mixin in two steps to do the guards separately

  • for values nonnumeric entries (in your case 'no') with isnumber() and
  • for value = 0

here is the LESS code (note the use od and in the guards):

.border-r-not-0 (@a, @b, @c, @d) when not (@a = 0), not (@b = 0), not (@c = 0), not (@d = 0){
      -webkit-border-radius: @a @b @c @d;
       -moz-border-radius: @a @b @c @d;
            border-radius: @a @b @c @d;
}
.border-radius(@a, @b, @c, @d) when (isnumber(@a)) and (isnumber(@b)) and (isnumber(@c)) and (isnumber(@d)){
    .border-r-not-0(@a, @b, @c, @d);
}

.border-radius(@r) when (isnumber(@r)) and not (@r = 0) {
    -webkit-border-radius: @r;
       -moz-border-radius: @r;
            border-radius: @r;
}

now for

@baseBorderRadius: 3px;
.class1 { .border-radius(@baseBorderRadius); }
.class2 { .border-radius(@baseBorderRadius, @baseBorderRadius, 0, 0); }

the CSS output is:

.class1 {
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.class2 {
  -webkit-border-radius: 3px 3px 0 0;
  -moz-border-radius: 3px 3px 0 0;
  border-radius: 3px 3px 0 0;
}

and there is no output if

@baseBorderRadius: no;

because it does not pass the isnumber() test,

or if

@baseBorderRadius: 0;

because then all arguments equal 0.

Note: For doing more complex stuff, like using the slash / with the parameters, you have to define a slightly different mixin, that takes additional atributes, but I hope you can get the idea.

like image 58
Martin Turjak Avatar answered Nov 18 '22 10:11

Martin Turjak


Treating "no" as 0

This revamped mixin treats "no" as 0 and then looks to see if everything is set at 0 or not. I don't know if that is exactly the functionality you sought, but that is what I have provided here (see the .class14 output below for how it works with other valid values).

.border-radius(@r) {
  .check-no(@r) {
    @rad: `'@{r}'.replace(/no/gi, 0).replace(/\b0px|\b0%|\b0em/gi, 0).replace(/[,\[\]]/g, '')`;
  }
  .check-no(@r);

  .set-radius(@rad) when not (@rad = "0") and not (@rad = "0 0") and not (@rad = "0 0 0") and not (@rad = "0 0 0 0") {
    @finalRad: e(@rad);
    -webkit-border-radius: @finalRad;
       -moz-border-radius: @finalRad;
            border-radius: @finalRad;    
  }

  .set-radius(@rad) {}
  .set-radius(@rad);
}

To be fully compatible, the string replacement /\b0px|\b0%|\b0em/gi would have to be set up for all types of lengths allowed (I was not going to take time to do that).

So this LESS test code:

@b1: 3px;
.class1 { .border-radius(@b1); }
.class2 { .border-radius(@b1 @b1 0 0); }
.class3 { .border-radius(0 0); }
.class4 { .border-radius(0px 0); }
.class5 { .border-radius(0% 0); }
.class6 { .border-radius(0em 0); }
.class7 { .border-radius(10px 0); }
.class8 { .border-radius(10% 0); }
.class9 { .border-radius(10em 0); }
.class10 { .border-radius(no); }
.class11 { .border-radius(no no); }
.class12 { .border-radius(no no 0); }
.class13 { .border-radius(no no 0 0); }
.class14 { .border-radius(no no 5px 5px); }

Produces this CSS output (ignoring all instances where it evaluates to a net 0):

.class1 {
  -webkit-border-radius: 3px;
  -moz-border-radius: 3px;
  border-radius: 3px;
}
.class2 {
  -webkit-border-radius: 3px 3px 0 0;
  -moz-border-radius: 3px 3px 0 0;
  border-radius: 3px 3px 0 0;
}
.class7 {
  -webkit-border-radius: 10px 0;
  -moz-border-radius: 10px 0;
  border-radius: 10px 0;
}
.class8 {
  -webkit-border-radius: 10% 0;
  -moz-border-radius: 10% 0;
  border-radius: 10% 0;
}
.class9 {
  -webkit-border-radius: 10em 0;
  -moz-border-radius: 10em 0;
  border-radius: 10em 0;
}
.class14 {
  -webkit-border-radius: 0 0 5px 5px;
  -moz-border-radius: 0 0 5px 5px;
  border-radius: 0 0 5px 5px;
}
like image 4
ScottS Avatar answered Nov 18 '22 09:11

ScottS