42

UPDATE: If you plan to implement the export solution, you must place it in a separate file to prevent redundant exports in your compiled CSS code. See here.

I recently learned that you can export styles from SCSS into JS like so:

_variables.scss

:export {
    some-variable: 'some-value';
}

app.js

import styles from 'core-styles/brand/_variables.scss';

Based on this, my _variables.scss is formatted like so:

/* Define all colours */
$some-color:       #000;
$another-color:    #000;

// Export the color palette to make it accessible to JS
:export {
    some-color: $some-color;
    another-color: $another-color;
}

The issue with the above format is that I have to re-define each of my variables within export. Therefore, I am interested to know whether there is a way to loop though each of my variables automatically and export them to JS?

Ben Carey
  • 16,540
  • 19
  • 87
  • 169
  • 1
    What kind of loader setup is required to be able to use `:export`? I'm struggling to find any documentation online. – Maximo Mussini Jun 17 '19 at 22:02
  • 2
    @MaximoMussini - it is known as ICSS (Interoperable CSS), check this link out: https://glenmaddern.com/articles/interoperable-css. There are also various other articles online, just put interoperable CSS into Google :-D – Ben Carey Jun 17 '19 at 22:17

2 Answers2

41

Some improvements to the accepted answer:

  • Use camelCase so you will be able to individually export a variable.

  • Set the @each directive outside so it won't generate a new :export at-rule for each variable.


_variables.scss

$theme-colors: (
  'someColor': #000,
  'anotherColor': #FFF,
);

:export {
  @each $key, $value in $theme-colors {
    #{unquote($key)}: $value;
  }
}

app.js

import styles from './core-styles/brand/_variables.scss' // { anotherColor: "#FFF", someColor: "#000" }
import { someColor } from './core-styles/brand/_variables.scss' // #000

Note: I tend to include quotes within Sass Maps, but you can omit them.

Quentin Veron
  • 3,079
  • 1
  • 14
  • 32
  • 1
    That was really helpful. The only answer that works! – Ahmed Mahmoud Dec 09 '19 at 11:21
  • 3
    I don't know why, but this doesn't seem to work anymore for some reason :( https://codesandbox.io/s/cool-night-92rij – Sammy Oct 26 '20 at 19:37
  • 1
    One has to write: `@each $key, $value in $theme-colors { #{$key}: #{$value}; }` ie. must interpolate variables – chikamichi Dec 12 '20 at 21:20
  • i got stuck trying to `@use 'sass:string'` and then use `string.unquote` but turns out I just had to call `unquote` directly and it worked like this answer! – Akin Hwan May 10 '23 at 18:45
27

Taking a Cue from Bootstrap 4, you could combine a SASS map with a loop like below;

/* Define all colours */
$theme-colours: (
  some-color: #000,
  another-color: #000,
  third-color: #000,
  fourth-color: #000
)

@each $color, $value in $theme-colours {
  :export{
    $color: $value;
  }
}

Here's some examples from the Bootstrap 4 Docs

Lewis
  • 3,479
  • 25
  • 40
  • 5
    I thought about using this but I am not overly keen on using a map to reference all my colours. I will accept this as the answer though as I was going to post up the same because I am fairly confident this is the only way to achieve it... – Ben Carey Jun 10 '19 at 11:05