Controlling the specificity of CSS Modules in a Next.js App
Asked Answered
F

2

12

I'm trying to figure out a good workflow of how to use Tailwind together with CSS Modules in Next.js, but I'm running into some tricky problems regarding specificity and the order in which styles are inserted by Webpack.

Consider the following use case: I want to create a reusable Button component whose styles can be overridden with utility classes. Option 1 is to extract the component, as mentioned in the Tailwind Docs:

/* button.jsx */

export const Button = props => <button {...props} className={`btn {props.className}`} />

and in my tailwind.css file I'd add the classname in the @layer directive:

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer components {
  .btn { @apply ... }
}

This is nice because I can override any of the buttons styles with utility classes, since they have higher specificity. However, I see a few minor problems here:

  • the class is now global, so it's included in every page even if I don't use the component
  • the style and component are no longer colocated - this might get messy if I create many such classes

Option 2 would be to use a CSS Module and apply the classes like this:

/* button.module.css */

.btn { @apply ...}
/* button.jsx */

import styles from "./button.module.css";

export const Button = props => <button {...props} className={`${styles.btn} {props.className}`} />

This way the CSS only gets loaded when the component is used, and the styles are colocated. Problem here is that in Next.js CSS Modules are inserted after global CSS, so they have higher specificity. Which totally makes sense, usually I'd want my CSS Modules to be able to override global styles. However, in this case I'd like them to be inserted before my global styles so that I can override them with utility classes.

I assume this should be possible by adjusting the Webpack config? Does anyone proficient with Webpack know how to achieve this?

Foredo answered 16/3, 2021 at 15:20 Comment(0)
F
1

I actually found a nice solution in tailwind v3.0, which is using the new important option. In your tailwind.config.js you can now add this line:

module.exports = {
  // ...
  important: '#__next'
}

This way, all your utilities are getting prefixed with #__next (the root element in Next.js), which increases their specificity above that of CSS Modules.

Foredo answered 12/3, 2022 at 9:27 Comment(0)
L
0

Go for the second option and simply add ! to the property to make that important.

/* button.module.css */

.btn { @apply !mb-0 }
Logical answered 24/11, 2021 at 8:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.