CSS Modules - referencing classes from other modules
Asked Answered
W

2

25

I have understood the concept of CSS modules so much that I am convinced that I do not want to do anything else that that for the future.

Currently I am trying to refactor an existing app to use CSS modules, the app has used classic sass with BEM methodology since.

Before I describe my problem I want to make clear that I undestand that I am addressing an issue that is not really within the domain of CSS modules. One should apply styles solely for usage inside a single module. At the most one should compose CSS classes with other CSS classes of other modules. But basically: You build an (HTML-)module and you use CSS modules to style that module and that's that.

Here's the problem: In the process of refactoring there is one single issue that derives from having had a SASS-based style system. I can't find a valid method to work with a CSS class within a CSS modules environment when this class should work in combination of another class from another module.

Example in SASS:

[page.scss]

.wrapper {
    margin: 0;
}

[headline.scss]

.headline {
    color: green;
}
.wrapper {
    .headline {
        color: orange;
    }
}

As you can see: One module (page) defines a CSS class "wrapper", another module defines a CSS class "headline". And, additionally, the class "headline" should behave a bit differently when placed inside the class "wrapper".

Again, I know that this is not really the domain of CSS modules. But I really would like to know if this is somehow doable with CSS modules? The "composes"-feature of CSS modules does not really fit here...

Woe answered 3/3, 2017 at 20:3 Comment(3)
What exactly do you mean by "CSS Components"? And how does this relate to ReactJS and Webpack?Osvaldooswal
You are very much correct. I used the wrong terminology. I have edited the post. Thank you!Woe
You can import that css file @import 'page.scss', but that is not a good idea.Tal
O
10

This is a common issue when migrating to CSS Modules. In short, a css module cannot override a style from another css module, and this is by design. Styles are supposed to live with the components that render them, and nowhere else.

What you can do to refactor this is to create a component style variant and explicitly set the variant through a prop when rendered within your wrapper.

For example, suppose your headline component currently looks something like this:

CSS

.headline {
  color: green;
}

JSX

import styles from "Headline.css";
const Headline = () => {
  return (
    <div className={styles.headline} />
  );
}

Rather than trying to override the .headline class name from somewhere else, you can create a variant class name that you toggle through a prop:

CSS

.headline-green {
  color: green;
}

.headline-orange {
  color: orange;
}

JSX

import styles from "Headline.css";
const Headline = ({orange}) => {
  return (
    <div className={orange ? styles.headlineOrange : styles.headlineGreen} />
  );
}

And when you render it from your wrapper, set it to the orange variant:

<Headline orange />

Tip: you can use composes to eliminate duplicate common styles between your variants.

Osvaldooswal answered 3/3, 2017 at 21:44 Comment(5)
I dont like this approach, it leads t ocreating multiple classes when only a small change is need to be done.Flowage
@Flowage That's part of the philosophy behind CSS modules, that each class should have all the styles, however there is certainly a counter argument to be made. This is an interesting (and short) thread. CSS modules doesn't stop you from using multiple classes in any way, though, that's really up to you. This example is just the way CSS Modules would recommend doing it.Osvaldooswal
Philosophy is nice, and it even make sense in this case, however, I have a legacy codebase on my hand that was not built by philosophers, and it's be good to be able to move it to modules. Is there a way to actually reference classes from other modules?Wembley
@Wembley Only if you mark them as :global()Osvaldooswal
@AaronBeall, how can it handles contextual styling? i.e. .form .button { ... }. The button will have a different look within a form. That information should not be known by the component, but the CSS needs to know it.Manse
S
6

You could use :global, to change the .headline class inside the .wrapper class:

.wrapper {
    :global(.headline) {
        color: orange;
    }
}
Surprisal answered 14/7, 2023 at 18:19 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.