Search code examples
cssfunctionsassmixins

Combine two SCSS background @mixin into the one style rule


I have two SCSS @mixins that I would like to combine into the one CSS background rule when called together:

@mixin linear-gradient($color-stop-1, $color-stop-2) {
    background: linear-gradient($color-stop-1, $color-stop-2);
}

@mixin bg-img($img, $bg-repeat: no-repeat, $bg-pos: 0 0, $bg-color: transparent) {
    background: url('#{$path--rel}/#{$img}') $bg-repeat $bg-pos $bg-color;
}

I could combine them into one long @mixin but they both will be reused in the project separately.

I want to have this CSS produced:

background: linear-gradient(#009fe1, #3acec2), url(../img/bg.jpg) no-repeat center bottom transparent;

enter image description here

Currently I am calling the two @mixins:

@include linear-gradient($cerulean, $turquoise);
@include bg-img('bg.jpg', no-repeat, center bottom);

Output CSS produced (as expected):

background: linear-gradient(#009fe1, #3acec2);
background: url(../img/bg.jpg) no-repeat center bottom transparent;

enter image description here

Can a function be used to combine the two @mixins or any other simple method to join?


Solution

  • Why don't you create 1 background mixin which can output all 3 scenarios depending on the input you give it?

    https://codepen.io/esr360/pen/LLKKvR?editors=1102

    $path--rel: '..';
    
    @mixin background($custom: ()) {
    
      $options: map-merge((
        'gradient': null,
        'image': null,
        'bg-repeat': no-repeat,
        'bg-position': 0 0,
        'bg-color': transparent
      ), $custom);
    
      // we have passed both gradient and image
      @if map-get($options, 'gradient') and map-get($options, 'image') {
        background: 
          linear-gradient(map-get($options, 'gradient')), 
          url('#{$path--rel}/#{map-get($options, 'image')}') 
          map-get($options, 'bg-repeat')  
          map-get($options, 'bg-position') 
          map-get($options, 'bg-color');
      }
    
      // we have passed just gradient
      @else if map-get($options, 'gradient') {
        background: linear-gradient(map-get($options, 'gradient'));
      }
    
      // we have passed just image
      @else if map-get($options, 'image') {
          background: 
            url('#{$path--rel}/#{map-get($options, 'image')}') 
            map-get($options, 'bg-repeat')  
            map-get($options, 'bg-position') 
            map-get($options, 'bg-color');
      }
    }
    
    
    // USAGE
    
    
    // Gradient
    .foo {
      @include background((
        'gradient': (#009fe1, #3acec2)
      ));
      // OUTPUT: background: linear-gradient(#009fe1, #3acec2);
    }
    
    // Image
    .bar {
      @include background((
        'image': 'bg.jpg'
      ));
      // OUTPUT: background: url("../bg.jpg") no-repeat 0 0 transparent;
    }
    
    // Both
    .fizz {
      @include background((
        'gradient': (#009fe1, #3acec2),
        'image': 'bg.jpg',
        'bg-position': center bottom
      ));
      // OUTPUT: background: linear-gradient(#009fe1, #3acec2), url("../bg.jpg") no-repeat center bottom transparent;
    }