Skip to content

Instantly share code, notes, and snippets.

@itsmunim
Last active May 4, 2023 06:52
Show Gist options
  • Save itsmunim/07895456c4809a9b41b7d457b9772182 to your computer and use it in GitHub Desktop.
Save itsmunim/07895456c4809a9b41b7d457b9772182 to your computer and use it in GitHub Desktop.

Using scss in NextJS components/modules, the traditional way e.g. by passing the actual classname like a-b-c instead of styles['a-b-c'] might seem a bit harder than expected. But actually it's supported out of the box. Just the next.config.js requires a bit of tweaking.

next.config.js changes

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  webpack(config) {
    const rules = config.module.rules.find((rule) => typeof rule.oneOf === 'object').oneOf.filter((rule) => Array.isArray(rule.use));

    rules.forEach((rule) => {
      rule.use.forEach((loader) => {
        // To prevent classname hashing, so that using styles[rootClassName] allows us to
        // pick all the other classes embedded under it in the dom, without really doing
        // styles[className] everytime.
        if (loader.loader?.includes('css-loader') && !loader.loader?.includes('postcss-loader')) {
          loader.options.modules.getLocalIdent = (context, _, exportName) => exportName;
        }
      });
    });

    return config;
  },
};

module.exports = nextConfig;

Example of usage in a component

The example component here is called Agent which renders a person's name and avatar.

Folder structure-

agent
  - agent.tsx
  - agent.module.scss
  - index.ts

The scss file content-

// Sample scss
// agent.module.scss
.agent-root {
    .agent__name {
       font-size: 16px;
       line-height: 22px;
       color: var(--app-clr-primary-text);
    }
    
    .agent__avatar {
       border-radius: 50%;
       object-fit: contain;
       border: 2px solid var(--app-clr-primary-border);
    }
    ...
}

The component code-

// Sample Component
// agent.tsx
import styles from 'agent.module.scss';

const Agent = (props) => {
   return (
     <div className={styles['agent-root']}>
       <p className="agent__name">{props.agentName}</p>
       <img className="agent__avatar" src={props.agentAvatar.src}/>
     </div>
   );
}

As you can see with this simple change in config, now you can only refer the style class root from the scss module style object, and it can refer to all the child classnames automatically - like you would have wanted!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment