Question

I use a @mixin to add different transition properties to elements. Let's say I have this in my .scss:

@mixin transition($prop, $sec){
  -webkit-transition: $prop $sec;
  -moz-transition: $prop $sec;
  -ms-transition: $prop $sec;
  -o-transition: $prop $sec;
  transition: $prop $sec;
}

then I call:

.sample{
  @include transition(background-color, 0.2s);
  @include transition(margin, 0.3s)
}

.sample has only got margin transition, but I also want background-color transition: is there any simple way to get it working?

It's important that I have different calls

Was it helpful?

Solution

There is no way in SASS to concatenate properties and I don't know if exists a CSS external tool to do this task. Sass was created to improve CSS capabilities and not to allow programmers to develop bad programming practices. I don't really know the purpose of create multiple CSS declaration statements when you can keep them all in a single statement. Keeping all your transitions in one statement improves considerably your structure, your workflow and the performance of your Sass code.

Ok, that said, and as you have mentioned before "let the horrible kludge be".

Here are two different mixins for you one for shorthand transition declaration and another for the long form, differences between them in processing and even load time are negligible, the only noticeable difference is in the style of your code.

Long form mixin

@mixin transition($properties, $durations, $timing-function: null, $delay: null) {
  $declarations: (property, $properties),
                 (duration, $durations),
                 (timing-function, $timing-function),
                 (delay, $delay);
  
  @each $declaration in $declarations {
    @if nth($declaration, 2) {
      $output: ();
        @each $val in nth($declaration, 2) {
          $output: append($output, $val, comma);
        }
      @each $prefix in '-webkit-', '-moz-', '-ms-', '-o-', '' {
        #{$prefix}transition-#{nth($declaration, 1)}: $output;
      }
    }
  } 
}

It's similar to @LeBen mixin but you can use the include with comma separated arguments without quotes:

@include transition(background-color margin, 0.2s 0.3s);

Shorthand form

@mixin transition($declarations...) {
  @each $prefix in '-webkit-', '-moz-', '-ms-', '-o-', '' {
    #{$prefix}transition: $declarations;
  }
}

Here's the way to implement it in your code

@include transition(background-color 0.2s, margin 0.3s);

And now, to solve your problem with "different calls" the only way to deal with them, in my opinion, is using append() list function.

Let's go with the example. I'm going to use shorthand mixin form because it's easier to implement.

Imagine that you have four pages, three partials (_variables.scss, _page1.scss, _page2.scss, _page3.scss) and a style.scss file which imports the other:

_VARIABLES.SCSS

// Here comes the variable declaration
$transition-list: color 1s;

_PAGE1.SCSS

// Using append($list, $val, $separator:auto) list function
// we can add some items to $transition-list
$transition-list: append($transition-list, margin 2s, comma);

_PAGE2.SCSS

// You can add also the output of a function
@function example(){
  @return unquote("background-color 1s")
}

$transition-list: append($transition-list, example(), comma);

STYLE.SCSS

// You can add new values into the same page
$transition-list: append($transition-list, padding 4s, comma);

$transition-list: append($transition-list, border 10s, comma);

// And finally you only need to use the include to generate the final transition
example {
  @include transition($transition-list);
}

As I've said before, I don't recommend to use this method, it's not a good practice.

OTHER TIPS

Your mixin is too rigid and don't feel like natural CSS. Personally, I recommend using the mixins provided by Compass, especially since it should handle prefixed values as well. If you just want a simple mixin, you want to use variable arguments like so:

@mixin transition($values...) {
    -webkit-transition: $values;
    // other prefixes
    transition: $values;
}

@mixin transition-property($values...) {
    -webkit-transition-property: $values;
    // other prefixes
    transition-property: $values;
}
@mixin transition-delay($values...) {
    -webkit-transition-delay: $values;
    // other prefixes
    transition-delay: $values;
}

// etc

.foo {
    @include transition(background-color, margin); // or transition-property
    @include transition-delay(0.2s);
}

Output:

.foo {
  -webkit-transition: background-color, margin;
  transition: background-color, margin;
  -webkit-transition-delay: 0.2s;
  transition-delay: 0.2s;
}

Alternate Usage:

.foo {
    @include transition(background-color 0.2s, margin 0.3s);
}

Output:

.foo {
  -webkit-transition: background-color 0.2s, margin 0.3s;
  transition: background-color 0.2s, margin 0.3s;
}

Here is the mixin you could use:

@mixin transition($properties, $durations, $timing-function: null, $delay: null) {
  $props: unquote($properties);
  $durs: unquote($durations);

  -webkit-transition-property: $props;
     -moz-transition-property: $props;
      -ms-transition-property: $props;
       -o-transition-property: $props;
          transition-property: $props;

  -webkit-transition-duration: $durs;
     -moz-transition-duration: $durs;
      -ms-transition-duration: $durs;
       -o-transition-duration: $durs;
          transition-duration: $durs;

  @if ($timing-function) {
    -webkit-transition-timing-function: $timing-function;
       -moz-transition-timing-function: $timing-function;
        -ms-transition-timing-function: $timing-function;
         -o-transition-timing-function: $timing-function;
            transition-timing-function: $timing-function;
  }

  @if ($delay) {
    -webkit-transition-delay: $delay;
       -moz-transition-delay: $delay;
        -ms-transition-delay: $delay;
         -o-transition-delay: $delay;
            transition-delay: $delay;
  }
}

With the following call

@include transition("background-color, margin", 0.2s);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top