Reputation: 143
Is there a way to use Sass’ @if
statement inside the value part of a property? I.e. make the following code work:
@mixin color-transition($color:true, $background:true, $border:true, $duration: 0.2s) {
transition:
@if ($color) {
color $duration linear,
}
@if ($background) {
background-color $duration linear,
}
@if ($border) {
border-color $duration linear,
}
;
}
I can’t move transition:
inside of the if clause because in that case the last of them would overwirte the former …
Upvotes: 1
Views: 81
Reputation: 10015
@mixin color-transition($color:true, $background:true, $border:true, $duration: 0.2s) {
$transition : '';
@if ($color) {
$transition : 'color #{$duration} linear,'
}
@if ($background) {
$transition : '#{$transition} background-color #{$duration} linear,'
}
@if ($border) {
$transition : '#{$transition} border-color #{$duration} linear,'
}
@if (str-length($transition) > 0) {
transition: unquote(str-slice($transition, 1, -2));
}
}
Then you can @include color-transition()
in any CSS rule. Tested.
Now the property isn't showed if there is no transition, and bugs fixed.
Upvotes: 2
Reputation: 17358
You could simply concatenate the answer and print it afterwards...
@mixin color-transition($color:true, $background:true, $border:true, $duration: 0.2s) {
$transition: '';
@if ($color) {
$transition: $transition + 'color #{$duration} linear';
}
@if ($background) {
@if ($transition != ''){ $transition: $transition + ','; }
$transition: $transition + 'background-color #{$duration} linear';
}
@if ($border) {
@if ($transition != ''){ $transition: $transition + ','; }
$transition: $transition + 'border-color #{$duration} linear ';
}
transition: unquote($transition);
}
But of course, you could just simply do it like this:
@mixin color-transition($color:0s, $background:0s, $border:0s){
transition: color $color linear, background $background linear, border $border linear;
}
Which allows you to call them all in one go:
@include color-transition(1s,1s,2s);
With an output like this:
transition: color 1s linear, background 1s linear, border 2s linear;
Since the default is 0s, technically you have no transition set for those values, although it might overwrite preset values somewhere else, so I see why it might not be ideal, just an idea.
Upvotes: 2
Reputation: 68339
You can't use a control directive in the middle of a statement like that. You have to append a string or list variable inside of your @if
statements and then write out the finished property at the very end.
Your specific use case would be best solved by passing in a list of the properties you want to modify:
@mixin color-transition($duration: 0.2s, $properties...) {
$collector: ();
// optional
@if length($properties) == 0 {
$properties: color, background-color, border-color;
}
@each $p in $properties {
$collector: append($collector, $p $duration linear, comma);
}
transition: $collector;
}
Usage:
.foo {
@include color-transition();
}
.bar {
@include color-transition(0.2s, color);
}
.buzz {
@include color-transition(0.2s, background-color, border-color);
}
Output:
.foo {
transition: color 0.2s linear, background-color 0.2s linear, border-color 0.2s linear;
}
.bar {
transition: color 0.2s linear;
}
.buzz {
transition: background-color 0.2s linear, border-color 0.2s linear;
}
Variation to allow for optional duration:
@mixin color-transition($properties...) {
// optional
@if length($properties) == 0 {
$properties: color, background-color, border-color;
}
$duration: 0.2s; // default value
$collector: ();
@each $p in $properties {
@if type-of($p) == number {
$duration: $p;
} @else {
$collector: append($collector, $p $duration linear, comma);
}
}
transition: $collector;
}
.foo {
@include color-transition(color);
}
As a quirky side-effect, you can specify different durations of each property:
.bar {
@include color-transition(color, 0.3, background);
}
Upvotes: 1