0

I'm trying to make a library of react components that's external to an application. This will be an npm module, loaded with Webpack. I'm styling the component using CSS Modules, and I'm trying to see how to make some of its properties customizable. For instace, background color.

I would like to use css variables for this to have for instance this syntax in the css file:

.myClass {
    backgrond-color: var(--backgroundColor, red);
}

Where --backgroundColor is a variable I can set, and red is the default. My question is, is there a way I can pass variables to the .css file when loading it from the .jsx file? So I could pass a variables object to the component, which then would influence how it loads it style? Could I use PostCSS for this?

Thanks.

PS: I know this could be solved by using inline JS styles, but I'm trying to give CSS a shot first.

Pablo Barría Urenda
  • 5,703
  • 5
  • 20
  • 32

4 Answers4

0

You cannot inject javascript into a css file and PostCSS can only transform your css files, but not inject/replace variables.

However, one way of doing this would be to create .scss (sass) files with default variables, e.g. $background-color: red; One could then import your module and .scss files to their .scss files and overwrite any variables like $background-color with their own variables if they wish.

Deividas
  • 6,437
  • 2
  • 26
  • 27
  • 1
    @PabloBarríaUrenda Please check this post: http://stackoverflow.com/questions/17089717/how-to-overwrite-scss-variables-when-compiling-to-css. However, I do not have a working example to point you to. You should check how bootstrap or other frameworks are doing this (they do allow to set variables). – Deividas Mar 02 '17 at 18:27
0

I'm not sure I understood you right, but here what I'm thinking of:

When you are requiring .css file with Webpack it adds this css as a string to the <head> element of the page behind the scene.

Why don't you do what Webpack does using your own function, like so.

Your module:

import $ from 'jquery';

/* this function builds string like this:
   :root {
      --bg: green;
      --fontSize: 25px;
   }

   from the options object like this:
   {
      bg: 'green',
      fontSize: '25px'
   }
*/
function buildCssString(options) {
    let str = ':root {\n'
   
    for(let key in options) {
        str += '\t--' + key + ': ' + options[key] + ';\n'
    }

    str += '}';

    return str;
}

/* this function adds css string to head element */
export const configureCssVariables = function(options) {
    $(function() {
        var $head = $('head'),
            $style = $('<style></style>');

        $style.text(buildCssString(options));
        $style.appendTo($head)
    });
}

Usage:

import {configureCssVariables} from './your-module';

configureCssVariables({
  bg: 'green',
  fontSize: '25px'
});

And your css is simple

/* default variables that will be overwritten
   by calling configureCssVariables()
*/
:root {
  --bg: yellow;
  --fontSize: 16px;
}

.myClass {
    backgrond-color: var(--bg);
    font-size: var(--fontSize);
}
disstruct
  • 673
  • 3
  • 8
0

It can be acheived by adding PostCSS and the postcss-custom-properties plugin in your pipeline. It has a variables option which will inject JS defined variables (properties) to any file being processed.
This eliminate the need to @import anything inside every CSS module file.

const theme = {
  'color-primary': 'green',
  'color-secondary': 'blue',
  'color-danger': 'red',
  'color-gray': '#ccc',
};

require('postcss-custom-properties')({
  variables: theme,
});

See how to use it with babel-plugin-css-modules-transform https://github.com/pascalduez/react-module-boilerplate/blob/master/src/theme/index.js and https://github.com/pascalduez/react-module-boilerplate/blob/master/.babelrc#L21 but that works with Webpack as well.

Pascal Duez
  • 671
  • 5
  • 7
  • My problem is (and this may be an architectural problem on my end) is that these are components already built, being consumed as an external package. Their CSS was already compiled, so using custom-properties will not work on them. – Pablo Barría Urenda Mar 04 '17 at 16:36
-1

I actually found a solution that already does this and takes advantage of the latest standardized JavaScript features

https://github.com/styled-components/styled-components

It may just be what I was looking for.

Pablo Barría Urenda
  • 5,703
  • 5
  • 20
  • 32