How to ignore passing parameter in mixin

235 views Asked by At

I want to use Less mixin for borders in a project, but often I need to use different sides of border, not all.

I have written a simple mixin:

.border-all (@border; @border-type; @border-color) {
  border-top: @border @border-type @border-color;
  border-right: @border @border-type @border-color;
  border-bottom: @border @border-type @border-color;
  border-left: @border @border-type @border-color;
}

Is it possible for example to pass arguments only to border-top and border-bottom ?

So:

.class {
  .border-all (3px; double; @border-color);
}

Would output in:

.class {
  border-top: 3px double #333;
  border-bottom: 3px double #333;
}

Can I ignore passing parameters to different CSS properties in the mixin?

2

There are 2 answers

0
Harry On

As it is, your current mixin cannot be modified to send parameters only to specific CSS properties. However, you can modify the mixin to be like the below snippet and pass the sides as arguments.

.border-all (@border; @border-type; @border-color; @sides...) {
    & when not (@sides = all){ /* if border is not needed on all sides */
        .border-side(@index) when (@index > 0){
            @side: extract(@sides, @index); /* extract the side specified for each iteration */
            border-@{side}: @border @border-type @border-color; /* create property */
            .border-side(@index - 1);
        }
        .border-side(length(@sides)); /* loop as many times as the no. of sides provided */
    }
    & when (@sides = all){ /* if border is needed for all sides */
        border: @border @border-type @border-color; /* combined because there is no need for 4 separate properties. */
    }
}

.demo{
    .border-all(1px; solid; black; top, right);
}
.demo2{
    .border-all(1px; solid; black; all);
}

You just have to pass the required sides as the last argument to the mixin and only the corresponding properties would be generated in output CSS.

1
seven-phases-max On

First of all I would ask why you need that mixin at all. How is it better than just border: 3px double @border-color;?

Same way instead of making a quite bloating and confusing conditional logic for a mixin I would rather stick to a temporary variable, e.g.:

.class {
   @border: 3px double @border-color;
    border-top: @border;
    border-bottom: @border;
}

Yep, it's three lines of code instead of one but it's no doubt more easy to maintain.

---

Either way if I had to use such mixin I'd probably simplify it to something like:

// usage:

.c1 {
    .border(top right, 1px solid black);
}

.c2 {
    .border(1px solid black);
}

// impl:

.border(@sides, @value) {
    .side(length(@sides));
    .side(@i) when (@i > 0) {
        @side: extract(@sides, @i);
        border-@{side}: @value;
        .side(@i - 1);
    }
}

.border(@value) {
    border: @value;
}

As I really can't see any point in using all those redundant commas and/or semicolons in this case.