lessmixinsredundancyless-mixinscoding-efficiency

Making this LESS Mixin more efficient and less redundant?


so for a website project I had to create a LESS Mixin which I had never done before. I have the feeling that it is not as efficient as it could be and may be a little redundant. I looked through it but couldnt think of a better way to do it. Maybe you can give me some advice? Dont get me wrong, its working perfectly fine but as mentioned I guess I could do it a little easier when it comes to the LESS code.

So here it is:

http://jsfiddle.net/T2Xe9/747/

Example HTML:

<style media="screen">
  div {
    background: crimson;
    width: 200px;
    height: 100px;
    position: relative;
    float: left;
    margin-right: 20px;
  }
</style>
<div class="example-1"></div>
<div class="example-2"></div>
<div class="example-3"></div>
<div class="example-4"></div>

Mixin with examples:

.clipping(@colorOne; @colorTwo; @width; @direction; @position; @side) {
  display: inline-block;
  width: @width;
  height: 20%;
  position: absolute;
  content: " ";

  & when (@direction = 'up') {
    background: linear-gradient(to top left, @colorOne 0%, @colorOne 50%, @colorTwo 50%, @colorTwo 100%);
  }

  & when (@direction = 'down') {
    background: linear-gradient(to top right, @colorOne 0%, @colorOne 50%, @colorTwo 50%, @colorTwo 100%);
  }

  & when (@position = top) {
    top: 0;
  }

  & when (@position = bottom) {
    bottom: 0;
  }

  & when (@side = 'left') {
    left: 0;
  }

  & when (@side = 'right') {
    right: 0;
  }
}

.clipping-single(@colorOne; @colorTwo; @direction; @position) {
  &:before {
    .clipping(@colorOne; @colorTwo; 100%; @direction; @position; 'left');
  }
}

.clipping-double(@colorOne; @colorTwo; @direction; @position) {
  & when (@direction = 'up') {
    &:before {
      .clipping(@colorOne; @colorTwo; 50%; 'up'; @position; 'left');
    }
    &:after {
      .clipping(@colorOne; @colorTwo; 50%; 'down'; @position; 'right');
    }
  }

  & when (@direction = 'down') {
    &:before {
      .clipping(@colorOne; @colorTwo; 50%; 'down'; @position; 'left');
    }
    &:after {
      .clipping(@colorOne; @colorTwo; 50%; 'up'; @position; 'right');
    }
  }
}

.example-1 {
  .clipping-double(crimson, #fff, 'up', top);
}

.example-2 {
  .clipping-double(#fff, crimson, 'down', bottom);
}

.example-3 {
  .clipping-single(#fff, crimson, 'down', bottom);
}

.example-4 {
  .clipping-single(crimson, #fff, 'up', top);
}

Solution

  • I have two suggestions for you. Both will reduce the redundancy and produce the same CSS as the original version. If more efficient means less lines of SASS code then this is also the case.

    & when (@position = top) {
      top: 0;
    }
    
    & when (@position = bottom) {
      bottom: 0;
    }
    

    can be replace with

    @{position}: 0;
    

    and the same for @{side}: 0; but you would have to pass left instead of 'left' as an argument.

    The second suggestion is to refactor the line where you set the linear-gradient. The only variable is the direction so I would make this a SASS variable to avoid the redundancy of the other linear-gradient parameters.

    & when (@direction = 'up') {
      background: linear-gradient(to top left, @colorOne 0%, @colorOne 50%, @colorTwo 50%, @colorTwo 100%);
    }
    
    & when (@direction = 'down') {
      background: linear-gradient(to top right, @colorOne 0%, @colorOne 50%, @colorTwo 50%, @colorTwo 100%);
    }
    

    becomes

    .define-gradient-direction(@direction);
    .define-gradient-direction('up') { @gradientDir: to top left; }
    .define-gradient-direction('down') { @gradientDir: to top right; }
    background: linear-gradient(@gradientDir, @colorOne 0%, @colorOne 50%, @colorTwo 50%, @colorTwo 100%);
    

    Full code

    .clipping(@colorOne; @colorTwo; @width; @direction; @position; @side) {
      .define-gradient-direction(@direction);
      .define-gradient-direction('up') { @gradientDir: to top left; }
      .define-gradient-direction('down') { @gradientDir: to top right; }
      
      display: inline-block;
      width: @width;
      height: 20%;
      position: absolute;
      content: " ";
      background: linear-gradient(@gradientDir, @colorOne 0%, @colorOne 50%, @colorTwo 50%, @colorTwo 100%);
      
      @{position}: 0;
      @{side}: 0;
    }
    
    .clipping-single(@colorOne; @colorTwo; @direction; @position) {
      &:before {
        .clipping(@colorOne; @colorTwo; 100%; @direction; @position; left);
      }
    }
    
    .clipping-double(@colorOne; @colorTwo; @direction; @position) {
      & when (@direction = 'up') {
        &:before {
          .clipping(@colorOne; @colorTwo; 50%; 'up'; @position; left);
        }
        &:after {
          .clipping(@colorOne; @colorTwo; 50%; 'down'; @position; right);
        }
      }
    
      & when (@direction = 'down') {
        &:before {
          .clipping(@colorOne; @colorTwo; 50%; 'down'; @position; left);
        }
        &:after {
          .clipping(@colorOne; @colorTwo; 50%; 'up'; @position; right);
        }
      }
    }
    
    .example-1 {
      .clipping-double(crimson, #fff, 'up', top);
    }
    
    .example-2 {
      .clipping-double(#fff, crimson, 'down', bottom);
    }
    
    .example-3 {
      .clipping-single(#fff, crimson, 'down', bottom);
    }
    
    .example-4 {
      .clipping-single(crimson, #fff, 'up', top);
    }

    Edit: thanks to seven-phases-max for pointing out an improvement in the comments. It's now part of the snippet.