Ixonal
Ixonal

Reputation: 646

Sass/scss multiple mixins combining styles

I have a (well, really a few) Sass mixins to set gradient backgrounds (with backwards compatibility and what not). Now, I have an element that I want to have more than one gradient applied to. I can do this directly by setting the background property with a comma separated list, but I'd like it if I could use multiple applications of the gradient mixin to apply the multiple gradients and output the property as a common separated list.

An example of what I'd like to do:

div.needs-two-backgrounds {
  @include gradient-mixin(90deg, $color-one 0, $color-two 100%);
  @include gradient-mixin(180deg, $color-three 0, $color-four 20%, $color-five 100%);
}

Which would (essentially) emit this

div.needs-two-backgrounds {
  background-image: linear-gradient(90deg, $color-one 0, $color-two 100%),
                    linear-gradient(180deg, $color-three 0, $color-four 20%, $color-five 100%);
}

Is there some way to do this built into Sass, or would it require a separate library, or is it just impossible for the language?

Edit: I built a solution as per the answer and thought I'd share it.

@function linear-gradient-x($direction, $stops...) {
  @return linear-gradient($direction, $stops);
}

@function prefixed-background-image-list-x($prefix, $images) {
  $ret-val: ();

  @each $image in $images {
    $prefixed-image: #{$prefix}$image;
    $ret-val: append($ret-val, $prefixed-image, 'comma');
  }

  @return $ret-val;
}

@mixin background-image-x($backgrounds...) {
  background-image: prefixed-background-image-list-x("-moz-", $backgrounds);
  background-image: prefixed-background-image-list-x("-webkit-", $backgrounds);
  background-image: prefixed-background-image-list-x("-o-", $backgrounds);
  background-image: prefixed-background-image-list-x("ms-", $backgrounds);
  background-image: prefixed-background-image-list-x("", $backgrounds);
}

Which is used like how suggested in the answer:

div.needs-two-backgrounds {
  @include background-image-x(
    linear-gradient-x(90deg, $color-one 0, $color-two 100%),
    linear-gradient-x(180deg, $color-three 0, $color-four 20%, $color-five 100%)
  );
}

Hope this helps someone.

Upvotes: 1

Views: 8587

Answers (1)

Marijan
Marijan

Reputation: 1855

It is not possible in the way you described, but it is possible with something like this.

div.needs-two-backgrounds {
    @include background-image(
        gradient(90deg, $color-one 0, $color-two 100%),
        gradient(180deg, $color-three 0, $color-four 20%, $color-five 100%)
    );
}

You would then have to create a mixin background-image that supports variable arguments – pay attention to the three dots:

@mixin background-image($images...) {
    // do stuff here
}

The gradient-mixin should then be replaced by/extended with a gradient function. A good starting point on how this all can be done is the background-image mixin of the Compass project:

https://github.com/Compass/compass/blob/stable/core/stylesheets/compass/css3/_images.scss#L97

Upvotes: 2

Related Questions