Using Javascript Variables in scss
Asked Answered
R

1

6

It's going to be awhile that I'm trying to find a solution to use javascript variables has scss value.

Let me explain my issue. I use VueJs/Vuetify and I've got two entry point for my theme.

The first one is a json file like that :

module.exports = {
  primary: { base: '#4d7cff', dark: '#2756d8', light: '#96b0fb' },
  secondary: { base: '#00bda5', dark: '#209284', light: '#cef1ec' },
  content: { base: '#37467a', dark: '#242c47', light: '#c3cbe6' },
  danger: { base: '#e43858', dark: '#d22545', light: '#E36d83' },
  success: { base: '#00c28d', dark: '#199c79', light: '#0bebae' },
  accent: '#f5f8fa',
  gradient: 'linear-gradient(45deg, #00bda5, #4d7cff)'
}

This file is required and use by vuetify two create custom color values and works perfectly.

The second one is a simple scss file :

// Theme colors
$color-primary-base: #4d7cff;
$color-primary-dark: #2756d8;
$color-primary-light: #96b0fb;

$color-secondary-base: #4d7cff;
$color-secondary-dark: #209284;
$color-secondary-light: #cef1ec;

$color-content-base: #37467a;
$color-content-dark: #242c47;
$color-content-light: #c3cbe6;

$color-danger-base: #e43858;
$color-danger-dark: #d22545;
$color-danger-light: #ff8097;

$color-success-base: #00c28d;
$color-success-dark: #199c79;
$color-success-light: #14e1a9;

$color-accent: #f5f8fa;

My goal would be to connect the json file with the scss variables to have one entry point for the entire app.

Why do this ? Vuetify offers a scss variable overload system to modify the style of the components.

the idea would be to control this overload from the javascript file

In addition to that, due to vuetify limits, there are certains points where I must to control the color in a responsive context (for example a white header on desktop and blue on mobile) and therefore am obliged to use scss variables.

I've find this article on medium who at first sight seems to answers my problem.

But when I try to test it I've got the following error :

in ./src/assets/styles/vuetify.scss

Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
ValidationError: Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
 - options has an unknown property 'options'. These properties are valid:
   object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }
    at validate (C:\Users\33770\Documents\Calimed\novalys-front\node_modules\schema-utils\dist\validate.js:96:11)
    at Object.loader (C:\Users\33770\Documents\Calimed\novalys-front\node_modules\sass-loader\dist\index.js:36:28)

Vuetify.scss

@import './novalys/map.scss';
@import '~vuetify/src/styles/main.sass';

vue.config.js

const sass = require('node-sass')
const sassUtils = require('node-sass-utils')(sass)
const sassVars = require(__dirname + '/src/theme/index.js')

module.exports = {
  css: {
    loaderOptions: {
      scss: {
        prependData: `@import "@/assets/styles/novalys/map.scss";`,
        options: {
          functions: {
            'get($keys)': function(keys) {
              keys = keys.getValue().split('.')
              let result = sassVars
              let i
              for (i = 0; i < keys.length; i++) {
                result = result[keys[i]]
              }
              result = sassUtils.castToSass(result)
              return result
            }
          }
        }
      }
    }
  },
  transpileDependencies: ['vuetify']
}

Can someone here would help me to find a possible solution ?

I've heard about an inverse solution by exporting a scss variable like that

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

But my idea is to have the entry point in json not a scss file.

Thank you in advance !

Ringworm answered 4/7, 2020 at 15:19 Comment(0)
T
0

Depending on the loader version the relevant option name differs (doc)

  • newest sass-loader uses additionalData
  • sass-loader version 8 uses prependData
  • sass-loader below version 8 uses data
{
  loader: 'sass-loader',
  options: {
    // you can also read from a file, e.g. `variables.scss`
    // use `prependData` here if sass-loader version = 8, or
    // `data` if sass-loader version < 8
    additionalData: `$color: red;`
  }
}

you can combine this with js-to-scss (npm) to turn your json file into a string that contains all the variables in scss syntax:

const const flattenObjSass = require("js-to-scss");
const colors = require("./colors.json");

// ...

{
  loader: 'sass-loader',
  options: {
    additionalData: flattenObjSass(colors, '$color-')
  }
}

so

{
  primary: { base: '#4d7cff', dark: '#2756d8', light: '#96b0fb' },
  secondary: { base: '#00bda5', dark: '#209284', light: '#cef1ec' },
}

will be turned into

$color-primary-base: #4d7cff;
$color-primary-dark: #2756d8;
$color-primary-light: #96b0fb;
$color-secondary-base: #00bda5;
$color-secondary-dark: #209284;
$color-secondary-light: #cef1ec;
Tangled answered 21/6, 2023 at 9:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.