Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reference variables in a map, before the whole map is defined?

Tags:

sass

map

I’ll start with my code, as it should be easier to understand what I want to do:

@function get-color($color, $lightness) {
  @return map-get(map-get($colors, $color), $lightness);
}

$colors: (
  green: (
    light: #A4EDE1,
    mid: darken(get-color(green, light), 20%),
    dark: darken(get-color(green, mid), 20%)
  ),

  red: (
    light: complement(get-color(green, light)),
    mid: complement(get-color(green, mid)),
    dark: complement(get-color(green, dark))
  )
);

As you can see, I have created a multidimensional map, with my color values.
At the moment, I want to create the other colors, through the darken() and the complement() functions. The problem with that is, that I need to reference variables inside of the $colors variable, before it is completely filled. This results in an error for my get-color() function, which tells me, there is no $colors variable.

I know it would be possible to alter the colors outside of my $colors map, but the benefit of doing it this way is, that I can always come back and define color values, that are not generated. This would be a huge benefit in maintaining the project.

So here my question: Is there any way to reference another variable in map, before the whole map is defined?

like image 868
Afterlame Avatar asked Oct 31 '22 18:10

Afterlame


1 Answers

No. The mapping isn't defined until you reach that semicolon at the end. So you cannot reference any portion of it until then.

$base-color: #A4EDE1;
$colors: (
  green: (
    light: $base-color,
    mid: darken($base-color, 20%),
    dark: darken($base-color, 40%)
  ),
);

$colors: map-merge($colors, (
  red: (
    light: complement(get-color(green, light)),
    mid: complement(get-color(green, mid)),
    dark: complement(get-color(green, dark))
  )));

.foo {
  color: get-color(red, mid);
}

Unless you're looping over the mapping, I would recommend not using mappings to store your color variables. Rather, it would be better to simply write a function that will do the manipulation for you:

$base-color: #A4EDE1;

@function get-color($lightness, $variation: null, $color: $base-color) {
  $color: if($variation, call($variation, $color), $color);

  @if $lightness == medium {
    @return darken($color, 20%);
  } @else if $lightness == dark {
    @return darken($color, 40%);
  }
  @return $color;
}

.foo {
  color: get-color(mid);
  border: 1px solid get-color(mid, complement);
}
like image 90
cimmanon Avatar answered Nov 09 '22 11:11

cimmanon