How to pass multiple content blocks as arguments to a mixin?

Viewed 716

I wanna be able to do something like so:

.myTransitionableElement {
  transition: all .5s;

  .subChild { transition: all 1s }

  @include transitionKeyframes(
    start: {
      opacity: 0;
      transform: tranlsate(50px);

      .subChild {
        transform: rotate(45deg);
      }
    },
    end: {
      opacity: 1;
      transform: tranlsate(0);

      .subChild {
        transform: rotate(0);
      }
    }
  )
}


@mixin transitionKeyframes($args) {
  &.transitionStartKeyframe {
    @include map_get($args, "start");
  }
  &.transitionEndKeyframe {
    @include map_get($args, "end");
  }
}

Which should at the end be equivalent to:

.myTransitionableElement {
  transition: all .5s;

  .subChild { transition: all 1s }

  &.transitionStartKeyframe {
    opacity: 0;
    transform: tranlsate(50px);

    .subChild {
      transform: rotate(45deg);
    }
  }
  &.transitionEndKeyframe {
    opacity: 1;
    transform: tranlsate(0);

    .subChild {
      transform: rotate(0);
    }
  }
}

The reason behind this is that I wanna find a way to not have to remember those classes names every time I use a JS abstraction that uses those classes.

2 Answers

You can't pass different content as arguments in SASS mixins. Below is example of what you can achieve using SASS. Can you specify what you want to achieve here?

@mixin rtl() {
  &.ltr {
    @content;
    direction: ltr;
  }
  &.rtl {
    @content;
    direction: rtl;
  }
}

.parent {
  @include rtl {
   display: flex;
  }
}

You can try different approaches here. In this particular one I'm using map to hold the data for me. But if attributes and class names are fixed; you can even simplify it.

$map: (Start: (self: (opacity: '0', transform: 'tranlsate(50px)'), child: (transform: rotate(45deg))), End: (self: (opacity: '1', transform: 'tranlsate(0)'), child: (transform: rotate(0))));
$prefix: transition; $postfix: Keyframe;

@mixin transitionKeyframes($map) {
    @each $key, $val in $map {
    &.#{$prefix}#{$key}#{$postfix} {
      @each $attr, $prop in map-get($val, self) {
        #{$attr}: #{$prop};
      }

      .subChild {
        @each $attr, $prop in map-get($val, child) {
          #{$attr}: #{$prop};
        }
      }
    }
  }
}


.myTransitionableElement  {
  @include transitionKeyframes($map);
  transition: all .5s;
  .subChild { transition: all 1s }
}

Use mixins for a repetitive task. Modify the mixin or $frames if you have many variations. Breakdown opacity and transistion further to smaller mixins and invoke them conditionally.

$prefix: transition; $postfix: Keyframe;
$frames: 'Start', 'End';
$opcity-main: ('Start': 0, 'End': 1);
$translate-main: ('Start': 50, 'End': 0);

@mixin transitionKeyframes($frame) {
    @each $key in $frame {
    &.#{$prefix}#{$key}#{$postfix} {
      $opacity: map-get($opcity-main, $key);
      $translate: map-get($translate-main, $key);
      opacity: $opacity;
      transform: tranlsate($translate + px);
    }
  }
}


.myTransitionableElement  {
  @include transitionKeyframes($frames);
  transition: all .5s;
  .subChild { transition: all 1s }
}
Related