23

I'm new with Sass stuff and I've been reading about different ways to use variables, this principle I'm trying to apply is just for colors, some of the solutions I've found were something like this (map-get):

$colors: (
    lighestGray: #F8F8FA,
    lightGray: #A5ACBA,
    light: #FFFFFF,
    dark: #000000,
    link: #428bca,
    linkHover: #555,
    navBlue: #7AC243,
    navGreen: #009CDC,
);

Then you use it on your class like this:

.my-class {
    color: map-get($colors, dark);
}

And the other way is to use:

$color-black: #000000;

Then you use it like this:

.my-class {
    color: $color-black;
}

My question is, which option is better? or map-getfunction has another purpose?, has Sass a pattern for this or it depends on each web-developer?.

Thanks for helping me out!.

Regards.

Alex
  • 859
  • 2
  • 9
  • 19
  • 1
    They both produce the same CSS, so it's more of a preference than anything else. – André Dion Aug 31 '16 at 16:21
  • But what happend in case you are styling each border side color? ex. `.border-color { map-get($colors, color1); map-get($colors, color2); map-get($colors, color3); map-get($colors, color4); } `isn't this inefficient? – Alex Aug 31 '16 at 16:24
  • @Alex - you're supposed to wrap that in a SASS utility function, which is specific to colors, to avoid messy code such as the one you put. – vsync Nov 07 '16 at 14:55

4 Answers4

30

The differences is that when you use $map variables, they are best designed for using through iterations or using @each.

Sample case:

SCSS

// Map variable
$icons: (
  facebook   : "\f0c4",
  twitter    : "\f0c5",
  googleplus : "\f0c6",
  youtube    : "\f0c7"
);

// Mixin doing the magic
@mixin icons-list($map) {
  @each $icon-name, $icon in $map {
    @if not map-has-key($map, $icon-name) {
      @warn "'#{$icon-name}' is not a valid icon name";
    }

    @else {
      &--#{$icon-name}::before {
        content: $icon;
      }
    } 
  }
}

// How to use it
.social-link {
    background-color: grey;
    @include icons-list($icons);
}

CSS

// CSS Output

.social-link {
  background-color: grey;
}
.social-link--facebook::before {
  content: "";
}
.social-link--twitter::before {
  content: "";
}
.social-link--googleplus::before {
  content: "";
}
.social-link--youtube::before {
  content: "";
}

This code was taken from my own answer in the following post but the answer is a case use of @each :)

Hope this help you

Community
  • 1
  • 1
Héctor León
  • 1,879
  • 1
  • 21
  • 36
  • Isn't `@if not map-has-key($map, $icon-name) {` a bit redundant? – goonerify Feb 03 '21 at 08:47
  • @goonerify maybe now its is, some compilers complain if you try to use a $map variable with a wrong key, others just ignore that entire line. So i added as a terminal warning. No really neccessary – Héctor León Feb 03 '21 at 09:07
3

Example making a theme with css variables with fallback color see codepen css variables

// VARS (FOR FALLBACK)
// -------------------
$theme-base: #70c1ac;
$theme-base-aa: adjust-color($theme-base, $blue: 125);

// PROCESSED THEME
$theme-color: $theme-base;
$theme-color-dark: darken($theme-color, 20%);
$theme-color-light: lighten($theme-color, 20%);
$theme-color-mixed: mix(#fff, $theme-color, 75%);
$theme-color-trans: transparentize($theme-color, .4);

// PROCESSED SECONDARY
$theme-color-aa: $theme-base-aa;
$theme-color-aa-dark: darken($theme-color-aa, 20%);
$theme-color-aa-light: lighten($theme-color-aa, 20%);
$theme-color-aa-mixed: mix(#fff, $theme-color-aa, 75%);
$theme-color-aa-trans: transparentize($theme-color-aa, .4);

$theme-colors: (
  "aa-dark": $theme-color-aa-dark,
  "aa-light": $theme-color-aa-light,
  "aa-mixed": $theme-color-aa-mixed,
  "aa-trans": $theme-color-aa-trans,
  aa: $theme-color-aa,
  dark: $theme-color-dark,
  light: $theme-color-light,
  mixed: $theme-color-mixed,
  theme: $theme-color,
  trans: $theme-color-trans,
);

@mixin themeColor ($prop, $color: null) {
  @if ($color) {
    #{$prop}: map-get($theme-colors, $color);
    #{$prop}: var(--theme-color-#{$color})
  } @else {
    #{$prop}: map-get($theme-colors, theme);
    #{$prop}: var(--theme-color);
  }
}

@mixin setThemeColors($base1: "", $base2: "") {
  // BASE THEME COLORS
  $color-base: $theme-base;
  $color-aa: $theme-base-aa;

  @if ($base1) {
    $color-base: $base1;
    $color-aa: $base2;
  }

  // PROCESSED THEME COLORS
  $color-aa-dark: darken($color-aa, 20%);
  $color-aa-light: lighten($color-aa, 20%);
  $color-aa-mixed: mix(#fff, $color-aa, 75%);
  $color-aa-trans: transparentize($color-aa, .5);
  $color-aa: $color-aa;
  $color-dark: darken($color-base, 20%);
  $color-light: lighten($color-base, 20%);
  $color-mixed: mix(#fff, $color-base, 75%);
  $color-trans: transparentize($color-base, .5);

  // CSS VARIABLES
  --theme-color-aa-dark: #{$color-aa-dark};
  --theme-color-aa-light: #{$color-aa-light};
  --theme-color-aa-trans: #{$color-aa-trans};
  --theme-color-aa: #{$color-aa};
  --theme-color-dark: #{$color-dark};
  --theme-color-light: #{$color-light};
  --theme-color-mixed: #{$color-mixed};
  --theme-color-trans: #{$color-trans};
  --theme-color: #{$color-base};
}

:root {
  @include setThemeColors($theme-base, $theme-base-aa);
}

body {
  @include themeColor("background","mixed");
  font-size: 2rem;
}

ul {
  list-style: none; /* Remove default bullets */
}

ul li::before {
  content: "\2022";  /* Add content: \2022 is the CSS Code/unicode for a bullet */
  @include themeColor("color","dark");

  font-weight: bold; /* If you want it to be bold */
  display: inline-block; /* Needed to add space between the bullet and the text */ 
  width: 1.2em; /* Also needed for space (tweak if needed) */
  margin-left: -.8em; /* Also needed for space (tweak if needed) */
}

li {
  @include themeColor("color", "light");
  @include themeColor("background", "aa-dark");
}
Ron Jonk
  • 570
  • 4
  • 13
2

Why pick one when you can have them both.

_variables.scss

$color0 : white;
$color1 : red;
$color2 : green;
$color3 : blue;

_lists.scss

@use "variables";
@use "sass:map";
@use "sass:meta";
@use "sass:list";

@function dynamic($variable){
    $i: 0;
    $list: ();
    @while(variable-exists($variable + $i)){
        $list: list.append($list, map.get(meta.module-variables(variables), $variable + $i));
        $i: $i + 1;
    }
    @return $list;
}

$colors: dynamic('color'); // white red green blue

Import both into your scss files and use the list when you need to loop and the variables for shorthand when applying styles.

Mike Mellor
  • 1,264
  • 16
  • 22
0

map-get is used for getting css value from more kind of object.

suppose you have $param where you have defined multiple properties and now you want to assign. you can use it in following ways -

color: map-get($params, "color");

Where else simple variable holds only single value

map-get to get css value from object holding multiple values whereas variable to hold single value

Samyak Jain
  • 790
  • 1
  • 8
  • 12