简体   繁体   中英

Dynamic scss variable meteor

I have a scss variable $tint-color that is used in about 100 places.

Once the user logs in, I would like to load a color based on their profile and replace all the usages of $tint-color.

So far I have found two non-ideal solutions:

1) Iterate through all elements and replace the relevant properties.

I am constantly generating new elements -- so this would need to happen repeatedly.

2) Create an override stylesheet, that targets each element.

This will require a lot of duplicate code.

Is there a better / simpler way? I have thought about adding a class to an element in scss, but I am not sure this is possible. Thank you for your help in advance!

What I am doing now, is loading a theme css file after the profile is loaded.

On the server I expose an iron-router route that dynamically replaces any occurrence of the color and returns the theme css.

The issue is that I am not replacing the scss variables, instead I am replacing any occurrence of the color. This is because when the code is executed the .scss files have already been bundled into a .css file on the server.

// return a theme based on the tintColor parameter
this.route('theme', {
    where: 'server',

    action: function () {
        var files = fs.readdirSync('../client');

        // find the css file (not the .map file)
        var cssFile = _(files).find(function (fileName) {
            return fileName.indexOf('.css') > 0 && fileName.indexOf('.map') < 0;
        });

        var style = fs.readFileSync('../client/' + cssFile, 'utf8');

        // remove comments (cannot have them for minification)
        style = style.replace(/(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm, '');

        // replace the default tint-color with the dynamic color
        style = style.replace(/8cb850/g, this.params.tintColor);

        // minify css
        if (Settings.isProduction()) {
            // from the minifiers package
            style = CssTools.minifyCss(style);
        }

        this.response.writeHead(200, {'Content-Type': 'text/css'});
        this.response.end(style);
    }
});

Update: I got it to generate with scss variables.

Theme.compile = function (tintColor) {
    var dirName = path.dirname(styleFile);

    var styles = fs.readFileSync(styleFile, 'utf8');

    //replace default theme with dynamic theme
    var theme = '$tint-color: #' + tintColor + ';' + '\n';
    styles = styles.replace('@import "app/theme.scssimport";', theme);

    var options = {
        data: styles,
        sourceComments: 'map',
        includePaths: [dirName] // for @import
    };

    var css = sass.renderSync(options);

    // minify css
    if (Settings.isProduction()) {
        // remove comments -- cannot have them for minification
        css = css.replace(/(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm, '');

        // Use CssTools from the minifiers package
        css = CssTools.minifyCss(css);
    }

    return css;
};

If you do this make sure you add the scss files as assets in the package, example here .

Set a basic $tint-color in your original css.

Then use meteor to send inline CSS with the selected user-tint.

Example:

.tint {
  background-color: USER-TINT;
  color: USER-TINT;
}

That way you can cache the original css file and save loads of transfer!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM