0

I usually write SASS, but for a particular project I have to use LESS.

How do I achieve something like the below using less? Using sass the mixin can be called like @include align(hcenter top) to position an element horizontally in the middle and to the top.

@mixin align($styles) {
  position: absolute;
  content: '';
  display: block;

  @each $style in $styles {

      @if ($style == center) {
          margin-left: auto;
          margin-right: auto;
          margin-top: auto;
          margin-bottom: auto;
          left: 0;
          right: 0;
          top: 0;
          bottom: 0;
      }
      @if ($style == hcenter) {
          margin-left: auto;
          margin-right: auto;
          left: 0;
          right: 0;
      }
      @if ($style == vcenter) {
          margin-top: auto;
          margin-bottom: auto;
          top: 0;
          bottom: 0;
      }
      @if ($style == top) {
          top: 0;
      }
      @if ($style == bottom) {
          bottom: 0;
      }
      @if ($style == right) {
          right: 0;
      }
      @if ($style == left) {
          left: 0;
      }

    }

}
tolborg
  • 612
  • 4
  • 21
  • Related question - http://stackoverflow.com/questions/26163660/converting-a-sass-if-else-block-to-its-equivalent-in-less/26164200#26164200 – Harry Oct 27 '14 at 10:43
  • Previous one is for SASS to Less conversion. Refer to [this](http://stackoverflow.com/questions/21440789/loop-through-array-of-values-in-less/21441220#21441220) for looping in Less. – Harry Oct 27 '14 at 10:44

2 Answers2

2

See Mixin Arguments, List Functions and Loops.

With a thing like "for" the snippet can be converted to something like:

@import "loops/for";

#usage {
    .align(hcenter, top, bottom, etc);
}

.align(@styles...) {
    position: absolute;
    content:  '';
    display:  block;

    .for(@styles); .-each(@style) {
        & when (@style = center) {
            margin-left:   auto;
            margin-right:  auto;
            margin-top:    auto;
            margin-bottom: auto;
            left:   0;
            right:  0;
            top:    0;
            bottom: 0;
        }
        & when (@style = hcenter) {
            margin-left:   auto;
            margin-right:  auto;
            left:   0;
            right:  0;
        }
        & when (@style = vcenter) {
            margin-top:    auto;
            margin-bottom: auto;
            top:    0;
            bottom: 0;
        }
        & when (@style = top) {
            top:    0;
        }
        & when (@style = bottom) {
            bottom: 0;
        }
        & when (@style = right) {
            right:  0;
        }
        & when (@style = left) {
            left:   0;
        }
    }
}

---

Actually above code can be optimized to more compact:

.align(@styles...) {
    position: absolute;
    content:  '';
    display:  block;

    .center(@pos) {
        margin-@{pos}: auto;
        @{pos}: 0;
    }

    .for(@styles);
        .-each(center)  {.-each(hcenter); .-each(vcenter)}
        .-each(hcenter) {.center(left); .center(right)}
        .-each(vcenter) {.center(top); .center(bottom)}
        .-each(@style)  when (default()) {@{style}: 0}
}

Though this way it may look more confusing for one not too familiar with Less.

seven-phases-max
  • 11,765
  • 1
  • 45
  • 57
  • I like the second version a lot. Though as you rightly said, a beginner will take time to understand. – Harry Oct 31 '14 at 07:31
0

I'm not sure about your each loop. For instance (center, top;) will set top: 0; twice? But you can try:

.align(@styles){
.setproperties(@iterator:1) when (@iterator <= length(@styles)) {

    @style: extract(@styles,@iterator);

    & when (@style = center) {
        margin-left: auto;
        margin-right: auto;
        margin-top: auto;
        margin-bottom: auto;
        left: 0;
        right: 0;
        top: 0;
        bottom: 0;
    }
    & when (@style = hcenter)
    {
        margin-left: auto;
        margin-right: auto;
        left: 0;
        right: 0;
    }
    // add more & when 's here

    .setproperties((@iterator + 1));
}
position: absolute;
content: '';
display: block;
.setproperties();
}

The above can be called with:

selector1 {
    .align(center;);
}
selector2 {
    .align(center hcenter;);
}
Bass Jobsen
  • 48,736
  • 16
  • 143
  • 224
  • Btw., Bass, I noticed recently you stopped to apply any intends for your Less code. Is there some specific reason for this or it's just some copy-paste problem? (Those are quite hard to read). – seven-phases-max Oct 27 '14 at 12:58
  • @seven-phases-max, thanks for the feedback. I promise to behave better and pay more attention to it – Bass Jobsen Oct 27 '14 at 19:05