25

I'm porting an app from React to Next and I keep getting an error with my css: "ul" is not pure (pure selectors must contain at least one local class or id).

I'm using css modules and am not sure what the workaround is to keep everything in the css module.

for example:

index.js

<div className={styles.container}>
  <ul>
    <li>Person One</li>
  </ul>
</div>

index.module.css

.container{
  background-color: pink;
}
ul{
  list-style-type: none; //this throws an error
}
juliomalves
  • 42,130
  • 20
  • 150
  • 146
lernbr
  • 441
  • 2
  • 6
  • 13

3 Answers3

20

If you don't want to use classes as mentioned @Zeeshan's answer, you cannot use the module-based CSS. You will need to use a global stylesheet to target pure elements as selectors. They cannot be component-scoped.

Further, you can only import a global stylesheet in one place (_app.tsx/_app.jsx/_app.js), or you'll receive an error (explained here).

You may break your styles out across many stylesheets, but they all have to be global, so there's probably little benefit from doing so.

To quote directly from this Next.js GitHub discussion forum:

You are receiving this error because you are using html tags directly instead of classnames or ids in a file extension that is probably [filename].module.(css | scss | sass)

File extensions with *.module.(css | scss | sass) are css modules and they can only target elements using classnames or ids and not using tag names. Although this is possible in other frameworks like create-react-app, it is not possible in next-js.

My suggestion is using these html selector css in a separate file that doesn't contain the '.module' in it. Example: [filename].(css | scss | sass) --> styles.scss

And instead of importing like this

import styles from './styles.module.scss';

import like this

import './styles.scss';

Mir-Ismaili
  • 13,974
  • 8
  • 82
  • 100
tarrball
  • 2,123
  • 3
  • 23
  • 34
  • 2
    It gives a warning that such imports import './styles.scss'; has to be there in _app.tsx, not any other component. – Aniruddha Shevle Nov 16 '20 at 14:00
  • @AniruddhaShevle you're right. It needs to be in that one component. I will update my answer. – tarrball Nov 16 '20 at 15:19
  • 1
    This is a great answer! – Mark Good Nov 03 '21 at 21:25
  • Why in angular and svelte it is possible to have component-scoped pure selectors, but in nextjs not? – oleg gabureac Apr 18 '22 at 16:53
  • @oleggabureac Angular appears to take pure selectors and transforms them into more targeted selectors... If you put a style on an `h1` in an component's css file, then the selector that ends up scoped to the component with its unique identifier like `h1[ng_content-fmj-c345]`, for example. – tarrball Apr 19 '22 at 19:17
  • I understand, but why next can't do that? It is so hard to imlement it? It seems like an incomplete feature. – oleg gabureac Apr 21 '22 at 06:00
8

Try giving a className or id to ul tag and then write your styles accordingly.

for example:

index.js

<div className={styles.container}>
 <ul className={styles.container__list}>
  <li>Person One</li>
 </ul>
</div>

index.module.css

.container {
  background-color: pink;
}
.container__list{
  list-style-type: none;
}
Zeeshan
  • 413
  • 3
  • 6
8

This is actually extremely simple.

You can add a container class to the top element (just like you did), and then use combinators ( ,+,>, etc.) to target pure elements as you wish.

For example:

index.js:

<div className={styles.container}>
    <ul>
        <li>Person One</li>
    </ul>
</div>

index.module.css:

.container {
  background-color: pink;
}
.container ul {
  list-style-type: none;
}
Oz Heymann
  • 534
  • 5
  • 13