4

I have an SCSS map of colour names and values. I want to create CSS custom properties from them like so:

SCSS

$colours:(
  "gray-500":    #f7fafc,
  "red-500":     #f56565,
  "green-500":   #48bb78
);

Desired resultant CSS

--gray-500:  #f7fafc;
--red-500:   #f56565;
--green-500: #48bb78;

I know how to loop through the map, but where I'm getting caught up is how to use the key as a custom property name, and how to prepend -- to it. All the examples I can find related to this topic involve manually typing out the custom property name - not gleaning it from the key of a map.

This is what I have so far:

@each $colour, $value in $colours {
    --#{$colour}:$value;
}

That generates an error: expected "{" with the caret pointing to the end of this line:

--#{$colour}:$value;

I'm using Dart Sass 1.23.7

2 Answers 2

11

On SCSS to CSS you can use the following:

:root {
  $colours:(
    "gray-500": #f7fafc,
    "red-500": #f56565,
    "green-500": #48bb78
  );

  @each $key_name, $value in $colours {
    --#{$key_name}: #{$value};
  }
}

demo on jsfiddle.net

On SASS to CSS you have to use the @each inside a :root element (or defining an element inside):

$colours:(
  "gray-500": #f7fafc,
  "red-500": #f56565,
  "green-500": #48bb78
);

:root {
  @each $key, $value in $colours {
    --#{$key}: #{$value};
  }
}
Sign up to request clarification or add additional context in comments.

8 Comments

That's what I thought. I'm getting an error saying expected "{" at the end of that line. I'll update my question.
@Quasipickle because you need to place the variable inside an element: :root { @each $key_name, $value in $colours { --#{$key_name}: $value; } }
@TemaniAfif Wrapping that loop inside :root{ } had no affect.
@Quasipickle it worked for me using this: sassmeister.com
@AGoranov - fixed the SCSS code (value on @each): jsfiddle.net/vgwm2k9s
|
2

If you want to create CSS custom properties from nested sass map, you can do the following:

    @use "sass:meta";
    // create mixin
    @mixin map-scss-vars-into-css-vars($map, $prefix, $key: "") {
        @each $name, $value in $map {

            // copy the map key
            $key-copy: $key;
            // create name for CSS custom property that contains:
            // current key + child key from nested map
            $key: #{$key}-#{$name};
    
            @if meta.type-of($value) == "map" {
                // if value is a map, invoke it once more
                @include map-scss-vars-into-css-vars($value, $prefix, $key);
            } @else {
                --#{$prefix}#{$key}: #{$value};
            }
            // next iteration of loop should go with unchanged key
            $key: $key-copy;
        }
    }

How to use

// define your nested map

$config: (
    button: (
        primary: (
            color: red,
            background: blue,
        ),
        secondary: (
            color: yellow,
            background: green,
        ),
        tertiary: (
            color: white,
            background: black,
        ),
    ),
    input: (
        primary: (
            width: 100px,
        ),
    ),
);

// include magical mixin

:root {
    @include map-scss-vars-into-css-vars($config, 'my-cool-app');
}

// the result is astonishing

--my-cool-app-button-primary-color: red;
--my-cool-app-button-primary-background: blue;
--my-cool-app-button-secondary-color: yellow;
--my-cool-app-button-secondary-background: green;
--my-cool-app-button-tertiary-color: white;
--my-cool-app-button-tertiary-background: black;
--my-cool-app-input-primary-width: 100px;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.