Streamline LESS mixin

2019-07-26 17:38发布

问题:

I have some LESS for making margins based on the side being passed (top, right, bottom, left or all):

   .margin(@px,@side) when (@side = top) {
      (){ margin-top: ~"@{px}px"; }
   }
   .margin(@px,@side) when (@side = right) {
      (){ margin-right: ~"@{px}px"; }
   }
   .margin(@px,@side) when (@side = bottom) {
      (){ margin-bottom: ~"@{px}px"; }
   }
   .margin(@px,@side) when (@side = left) {
      (){ margin-left: ~"@{px}px"; }
    }
   .margin(@px,@side) when (@side = all) {
      (){ margin-top: ~"@{px}px";
      margin-right: ~"@{px}px";
      margin-bottom: ~"@{px}px";
      margin-left: ~"@{px}px"; }
    }

My question is that if I have an ID like this:

#testfeature {
.margin(10px,l);
.margin(10px,r);
}

Then LESS compiles it like this:

#testfeature {
margin-left:10px;
}

#testfeature {
margin-right:10px;
}

How do I get it to compile like this:

#testfeature {
margin-left:10px;
margin-right:10px;
}

回答1:

Get rid of the unnecessary () { ... }'s that are wrapping all of your mixin styles. They're causing the selectors to be interpreted oddly and separating them into different selections, rather than joining everything under one selection:

.margin(@px,@side) when (@side = top) {
    margin-top: ~"@{px}px";
}
.margin(@px,@side) when (@side = right) {
    margin-right: ~"@{px}px";
}
.margin(@px,@side) when (@side = bottom) {
    margin-bottom: ~"@{px}px";
}
.margin(@px,@side) when (@side = left) {
    margin-left: ~"@{px}px";
}
.margin(@px,@side) when (@side = all) {
    margin-top: ~"@{px}px";
    margin-right: ~"@{px}px";
    margin-bottom: ~"@{px}px";
    margin-left: ~"@{px}px";
}

You could probably also drop the ~"@{px}px" in favor of simply @px, also the last mixin should probably be:

.margin(@px, @side) when (@side = all) {
    margin: @px;
}


回答2:

To get them to "group" you need to create a nested and grouped mixin. Below is a grouped mixin function, "streamlined" for margin setting.

  1. It takes anywhere from 1 to 8 parameters; always in pairs of position then value (except as noted below; it can accept any order of position and values of auto or inherit are allowed).
  2. Passing a single "position" just sets a 0px margin on that position.
  3. Defaults non-unit numbers to px, but keeps explicitly set units as passed.
  4. Passing a single parameter that is number value will set all the margins to that number equally.

LESS Mixin

.setMargins(@s1: ~'', @v1: 0, @s2: ~'', @v2: 0, @s3: ~'', @v3: 0, @s4: ~'', @v4: 0) {

   .setPos(top, @T) {
        .setNum() when (isnumber(@T)) {
           margin-top: @T * 1px;
        }
        .setNum() when not (isnumber(@T)){
           margin-top: @T;
        }
        .setNum();
    }
   .setPos(right, @R) {
        .setNum() when (isnumber(@R)) {
           margin-right: @R * 1px;
        }
        .setNum() when not (isnumber(@R)) {
           margin-right: @R;
        }
        .setNum();
    }
   .setPos(bottom, @B) {
        .setNum() when (isnumber(@B)) {
           margin-bottom: @B * 1px;
        }
        .setNum() when not(isnumber(@B)) {
           margin-bottom: @B;
        }
        .setNum();
    }
   .setPos(left, @L) {
        .setNum() when (isnumber(@L)) {
           margin-left: @L * 1px;
        }
        .setNum() when not (isnumber(@L)) {
           margin-left: @L;
        }
        .setNum();
    }
   //allows all to be called with one number or value
   .setPos(@A, 0) when (isnumber(@A)) {
           margin: @A * 1px;
   }
   .setPos(auto, 0) {
           margin: auto;
   }
   .setPos(inherit, 0) {
           margin: inherit;
   }
   //default null if no valid side given
   .setPos(@other, 0) {}
   //call all possible positions
   .setPos(@s1, @v1);
   .setPos(@s2, @v2);
   .setPos(@s3, @v3);
   .setPos(@s4, @v4);
}

Examples

  1. .setMargins(right); produces margin-right: 0px;
  2. .setMargins(right, 15); produces margin-right: 15px;
  3. .setMargins(left, 10em); produces margin-left: 10em;
  4. .setMargins(top, 12, right, 10); produces: margin-top: 12px; margin-right: 10px;
  5. .setMargins(25); produces: margin: 25px;
  6. .setMargins(auto); produces: margin: auto;

So you use it in a selector:

LESS

#testfeature {
   .setMargins(left, 10, right, 10);
}

CSS Output

#testfeature {
  margin-left: 10px;
  margin-right: 10px;
}


标签: less