Create-react-app: Non module css doesn't work with :local() in CRA 3.0

Created on 26 Apr 2019  路  15Comments  路  Source: facebook/create-react-app

Is this a bug report?

Yes

Did you try recovering your dependencies?

Yes

Environment

Environment Info:

  System:
    OS: Linux 4.14 Manjaro Linux
    CPU: (12) x64 Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz
  Binaries:
    Node: 10.15.1 - ~/.nvm/versions/node/v10.15.1/bin/node
    Yarn: 1.15.2 - /usr/bin/yarn
    npm: 6.4.1 - ~/.nvm/versions/node/v10.15.1/bin/npm
  Browsers:
    Chrome: Not Found
    Firefox: Not Found
  npmPackages:
    react: ^16.8.6 => 16.8.6 
    react-dom: ^16.8.6 => 16.8.6 
    react-scripts: 3.0.0 => 3.0.0 
  npmGlobalPackages:
    create-react-app: Not Found

Steps to Reproduce

(Write your steps here:)

  1. Have a non module css-file, e.g. MyStyle.css
  2. Have a class in said file as a :local scoped class, e.g. :local(.myClass) { ... }
  3. Import CSS file in a React-component, e.g. import css from './MyStyle.css'
  4. Observe that the classname is not exported

Expected Behavior

That the css class has been given a random name and is available as a property on the css object, e.g. { myClass: "_2uhJkdnDbAceZ0gQC-r3vz" }

Actual Behavior

Object was empty: {}

Reproducible Demo

Source:
https://github.com/almyy/local-classname-repro

Deployed example:
https://almyy.github.io/local-classname-repro/

needs investigation

Most helpful comment

@Maxou44 That is the approach they have recommended since CRA 2.0 but there is a very important distinction when using SCSS, it might not be applicable to you but to anyone else ending up here when googling. When you have a module.scss everythin is exported, even nested selectors.

Consider this component:

import style from './MyComponent.scss`

const MyComponent = ({ highlight }) => (
  <div className={style.myComponent}>
      <div className={highlight ? 'someSubClass' : undefined}></div>
  </div>
)

With this SCSS (the old way):

:local(.myComponent) {
  background-color: red;

  .someSubClass {
    background-color: blue;
  }
}

With `.module.scss this would be identical to:

.myComponent {
  background-color: red;

  :global(.someSubClass) {
    background-color: blue;
  }
}

Which of course is pretty poor form, as you might have CSS leakage further down in your component tree if you ever use .someSubClass, but for us this is how most of the older CSS was written, making the migration a bit heavy.

The "correct" way of doing the SCSS with sub-classes from the React component would look like this:

import style from './MyComponent.module.scss`

const MyComponent = ({ highlight }) => (
  <div className={style.myComponent}>
      <div className={highlight ? style.someSubClass : undefined}></div>
  </div>
)

Which doesn't look to bad, but if you use classnames you have to do this when working with conditional classes:

import classNames from 'classnames'
import style from './MyComponent.module.scss`

const MyComponent = ({ highlight }) => (
  <div className={style.myComponent}>
      <div className={classNames({ [style.someSubClass]: hightlight })}></div>
  </div>
)

All 15 comments

Looking at the built CSS:

.global-style {
  background-color: red
}

:local(.localizedStyle) {
  background-color: #ff69b4
}

.Module_moduleStyle__rQ__0 {
  background-color: #00f
}

.global-from-module {
  background-color: #7fff00
}

It seems that the :local is completely disregarded.

Having the same issue here.

We are having the same issue here as well.

Same issue here

I renamed my file styles.css to styles.module.css, changed the import and it works, I don't know why...

@Maxou44 That is the approach they have recommended since CRA 2.0 but there is a very important distinction when using SCSS, it might not be applicable to you but to anyone else ending up here when googling. When you have a module.scss everythin is exported, even nested selectors.

Consider this component:

import style from './MyComponent.scss`

const MyComponent = ({ highlight }) => (
  <div className={style.myComponent}>
      <div className={highlight ? 'someSubClass' : undefined}></div>
  </div>
)

With this SCSS (the old way):

:local(.myComponent) {
  background-color: red;

  .someSubClass {
    background-color: blue;
  }
}

With `.module.scss this would be identical to:

.myComponent {
  background-color: red;

  :global(.someSubClass) {
    background-color: blue;
  }
}

Which of course is pretty poor form, as you might have CSS leakage further down in your component tree if you ever use .someSubClass, but for us this is how most of the older CSS was written, making the migration a bit heavy.

The "correct" way of doing the SCSS with sub-classes from the React component would look like this:

import style from './MyComponent.module.scss`

const MyComponent = ({ highlight }) => (
  <div className={style.myComponent}>
      <div className={highlight ? style.someSubClass : undefined}></div>
  </div>
)

Which doesn't look to bad, but if you use classnames you have to do this when working with conditional classes:

import classNames from 'classnames'
import style from './MyComponent.module.scss`

const MyComponent = ({ highlight }) => (
  <div className={style.myComponent}>
      <div className={classNames({ [style.someSubClass]: hightlight })}></div>
  </div>
)

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

Not stale.

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

Not stale.

I renamed my file styles.css to styles.module.css, changed the import and it works, I don't know why...

HI @Maxou44. Can you explain in more details that help you to overcome this issue? How did you change the import? As I understood you renamed it to styles.whateverComponentName.css?

@cheburan no, he added the .module. to the name of the file. Read my explanation above, it goes into some of the caveats.

@cheburan no, he added the .module. to the name of the file. Read my explanation above, it goes into some of the caveats.

Yep, thanks for the explanation (this and one before, regarding the caveats).

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

Not stale.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

adrice727 picture adrice727  路  3Comments

ap13p picture ap13p  路  3Comments

rdamian3 picture rdamian3  路  3Comments

AlexeyRyashencev picture AlexeyRyashencev  路  3Comments

alleroux picture alleroux  路  3Comments