jdsteinbach
9/23/2014 - 5:36 PM

Generated by SassMeister.com.

Generated by SassMeister.com.

<div class="box">I'm in a box.</div>
.box {
  font-weight: bold;
  font-size: 2em;
  padding: 1em;
  display: inline-block;
  background: #ffae68;
  color: #005cad;
}
// ----
// Sass (v3.4.4)
// Compass (v1.0.1)
// ----

// Store the main colors for the site:
$colors: (
  red: #ff4136,
  blue: #0074d9,
  yellow: #ffdc00,
  orange: #ff851b
);

// Store the different functions which could alter colors:
// 1 Key is shorthand to be used in partials, value is list. 
// 2-A First item in list is the function name, optional second item is list containing additional function values.
// 2-B Second item list only supports 2 values.
// With these limitations, this function does not support adjust-color, scale-color & change-color.
$variations: (
  light: (lighten, 15%),
  dark: (darken, 10%),
  fade: (rgba, .7),
  gray: (grayscale),
  shade: (mix, (black, 80%))
);

@function color-variant($color, $variation: false) {
  
  // Make sure $color param is in $colors map:
  @if not map-has-key($colors, $color) {
		@warn "Invalid color name: `#{$color}`.";
	} @else {
  
    // Make sure $variation param is in $variations map:
    @if not map-has-key($variations, $variation) {
      @warn "Invalid variation: `#{$variation}`.";
	  } @else {
	
	    // Color value from $colors map:
      $return_color: map-get($colors, $color);
  
      // Variation list from $variations map:
      $this_variation: map-get($variations, $variation);
  
      // Function name from variation list:
      $function: nth($this_variation, 1);

      // HELP: here's where I need help. I'm basically manually controlling 0|1|2 parameters,
      // but it feels hacky and I'd rather automate that. In a perfect world,
      // this might even support adjust-color, scale-color, change-color?
      // I tried:
      // 1 passing all the parameters as list: call($function, $return_color, $args);
      //   works for 0|1 arg, fails with 2 args
      //   error: $color2: (#000000, 80%) is not a color for `mix'
      // 2 passing the color & the params as a single list: call($function, $color_plus_args );
      //   works with 0 args, fails w/ 1|2 args
      //   error: wrong number of arguments (1 for 2) for `lighten'
      //   error: wrong number of arguments (1 for 2..3) for `mix'
      // 3 passing the function, color & args as a single list:
      //   fails with 0|1|2 args
      //   error: $name: ("grayscale", #0074d9) is not a string for `call'
      //   error: $name: ("lighten", #ff851b, 15%) is not a string for `call'
      //   error: $name: ("mix", #0074d9, #000000, 80%) is not a string for `call'
      // 4 interpolating lists
      //   fails: simply passes variables
      //   color: grayscale, #0074d9();
      
      
      // See if variation list has parameters (not just function):
      @if length($this_variation) > 1 {
        
        // Get variations parameters:
        $args: nth($this_variation, 2);
        
        // See if 2 variation parameters:
        @if length($args) > 1 {
          
          // Create call() with function, color, 2 parameters:
          $return_color: call($function, $return_color, nth($args, 1), nth($args, 2));

          // Only 1 variation parameter:
        } @else {
          
          // Create call() with function, color, 1 parameter:
          $return_color: call($function, $return_color, $args);
        }
      
      // Varation list only has a function name:
 	    } @else {
 	       
 	      // Create call() with function, color
        $return_color: call($function, $return_color);
 	    }
 	    
 	    // Return output:
  	  @return $return_color;
	  }
	}
}

// Alias function to make typing easier:
@function c($color, $variation) {
  @return color-variant($color, $variation);
}

.box {
  font-weight: bold;
  font-size: 2em;
  padding: 1em;
  display: inline-block;
  
  // Let's do this:
  background: c(orange, light);
  color: c(blue, shade);
}
<div class="box">I'm in a box.</div>