intermediate
CSS Modules
Scope class names per component while keeping regular CSS, composition, and build-time integration.
CSS Modules compile to locally scoped class names while keeping regular CSS syntax. Import styles as objects; the build rewrites selectors to unique hashes per module.
/* Button.module.css */
.root { padding: 0.5rem 1rem; }
.primary { composes: root; background: var(--accent); }
import styles from './Button.module.css';
<button className={styles.primary}>Save</button>
Composition (`composes`) shares declarations; `:global` escapes scope for resets or third-party hooks — use sparingly.
On interviews: trade-offs around scope, SSR, theming, shared tokens, and global utility layers.
Common pitfalls: local names do not fix cascade order; overusing :global erases the main benefit.
The trade-off is build-time safety versus explicit global token and layer strategy still required.
Checklist:
- Keep exported class APIs small and explicit.
- Share design tokens outside modules.
- Limit :global escapes.
- Verify SSR and code-split CSS loading.