Can I use css-modules with LESS + nesting?

13,833

Solution 1

I am also using less with css modules, but I don't think they way you are using the '&' fits with the goal of css modules. From my understanding 'composes' is more analogous to @import than &, and I only find myself using the & for psuedo-classes.

You can definitely do things the way you have here, but don't you find it a bit strange that you have to specify both the 'common' and 'normal' classes in the HTML? Much better in my opinion to just specify 'normal', and let normal inherit the shared styles using 'compose'.

Solution 2

.common {
    /* font-sizes, padding, border-radius */
    :global {
        &.normal { /* blue color, light blue background */ }
        &.error { /* red color, light red background */ }
    }
}

That's my solution. If you use styles.common, the css will be:

.ramdomStrings {
    /* I'm not sure if this exists, but it doesn't matter */
}
.ramdomStrings.normal { /* blue color, light blue background */ }
.randomStrings.error { /* red color, light red background */ }

Solution 3

If you're using a webpack loader for css-modules you can use the postcss loader and add various plugins to get your desired behaviour.

There is for example the "postcss-nested" plugin, which allows you to write nested rules.

Share:
13,833
mpen
Author by

mpen

Updated on June 06, 2022

Comments

  • mpen
    mpen almost 2 years

    The documentation on css-modules is pretty sparse, so I'm not sure if I can do this or not.

    This article says the way I'd style a button with normal and error states would look like this:

    .common { /* font-sizes, padding, border-radius */ }
    .normal { composes: common; /* blue color, light blue background */ }
    .error { composes: common; /* red color, light red background */ }
    

    But I'd prefer to write it like this:

    .common {
        /* font-sizes, padding, border-radius */
        &.normal { /* blue color, light blue background */ }
        &.error { /* red color, light red background */ }
    }
    

    Like I've always done, without introducing this new composes syntax. I think it's more clear which styles build on top of other styles if I can actually nest them in code.

    But I don't know what this would be exported as by css-modules? The only examples they give are simple class name selectors. I have no idea what about .common.normal will be exported as, or what .common > .normal ~ .strange? Do I basically have to not use any kind of CSS selector if I use css-modules?

  • mpen
    mpen over 8 years
    You're right, I'd prefer not to specify both class names in the HTML. I suppose composes is more like a mixin, which needs to be written with more-or-less the same syntax anyway. I guess I'd prefer a new operator then so that I could nest them the way I'd like, but oh well. I'll try composes; maybe I'll get used to it :D Thanks for answering.
  • JabbyPanda
    JabbyPanda almost 5 years
    css-loader does not seem to like & LESS selector used in :global scope Getting the following error on compile with Webpack 4 / css-loader 2.1.1 Module build failed (from ./node_modules/css-loader/dist/cjs.js):Error: Missing whitespace after :global