Skip to main content

Next.js Sass Integration

Introduction

Sass (Syntactically Awesome Style Sheets) is a powerful CSS preprocessor that extends the capabilities of standard CSS. It allows you to use variables, nested rules, mixins, functions, and more, making your stylesheets more maintainable and organized. Next.js provides built-in support for Sass, making it easy to integrate into your projects.

In this guide, we'll explore how to set up Sass in a Next.js application, understand the different types of Sass implementations (global vs. module-based), and look at some practical examples to enhance your styling workflow.

Prerequisites

Before we begin, ensure you have:

  • A working Next.js project
  • Basic understanding of CSS and Next.js
  • Node.js and npm installed on your machine

Setting Up Sass in Next.js

Step 1: Install the Required Dependencies

First, we need to install the sass package which Next.js will use to compile our Sass files to CSS:

bash
npm install sass

That's it! Next.js has built-in support for Sass, so once you've installed the sass package, you can start using Sass files in your project.

Step 2: Create Your First Sass File

Let's create a simple Sass file to test our setup. We'll start with a global style file:

  1. Create a file named globals.scss in your styles directory:
scss
// styles/globals.scss
$primary-color: #0070f3;
$background-color: #f5f5f5;

body {
font-family: 'Arial', sans-serif;
background-color: $background-color;
color: #333;
margin: 0;
padding: 0;
}

.container {
max-width: 1200px;
margin: 0 auto;
padding: 1rem;
}

h1, h2, h3 {
color: $primary-color;
}
  1. Import this file in your pages/_app.js file:
jsx
// pages/_app.js
import '../styles/globals.scss'

function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}

export default MyApp

Now, these styles will be applied globally across your application.

Component-Level Styling with Sass Modules

Next.js also supports CSS Modules, which allow you to scope your styles to specific components. This works with Sass as well, through .module.scss files.

Creating a Sass Module

Let's create a button component with its own Sass module:

  1. Create a file named Button.module.scss in your styles directory:
scss
// styles/Button.module.scss
$primary-color: #0070f3;
$hover-color: darken($primary-color, 10%);

.button {
background-color: $primary-color;
color: white;
border: none;
border-radius: 4px;
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease;

&:hover {
background-color: $hover-color;
}

&.secondary {
background-color: #f0f0f0;
color: #333;

&:hover {
background-color: darken(#f0f0f0, 10%);
}
}
}
  1. Use this module in a component:
jsx
// components/Button.js
import styles from '../styles/Button.module.scss';

const Button = ({ children, variant = 'primary' }) => {
return (
<button
className={`${styles.button} ${variant === 'secondary' ? styles.secondary : ''}`}
>
{children}
</button>
);
};

export default Button;
  1. Now you can use this Button component in any page:
jsx
// pages/index.js
import Button from '../components/Button';

export default function Home() {
return (
<div>
<h1>Welcome to My Next.js App</h1>
<Button>Primary Button</Button>
<Button variant="secondary">Secondary Button</Button>
</div>
);
}

Advanced Sass Features in Next.js

Using Sass Variables Across Files

One of the advantages of Sass is the ability to share variables across multiple files. Let's create a variables file:

  1. Create a file named _variables.scss:
scss
// styles/_variables.scss
$primary-color: #0070f3;
$secondary-color: #ff6b6b;
$text-color: #333333;
$light-color: #f8f9fa;
$dark-color: #212529;

// Breakpoints
$breakpoint-sm: 576px;
$breakpoint-md: 768px;
$breakpoint-lg: 992px;
$breakpoint-xl: 1200px;
  1. Import these variables in your other Sass files:
scss
// styles/Card.module.scss
@import './variables';

.card {
background-color: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border: 1px solid lighten($text-color, 70%);

.title {
color: $primary-color;
font-size: 1.5rem;
margin-bottom: 10px;
}

.content {
color: $text-color;
}

@media (min-width: $breakpoint-md) {
padding: 30px;

.title {
font-size: 2rem;
}
}
}

Creating a Mixins Library

Mixins allow you to define reusable style blocks:

  1. Create a file named _mixins.scss:
scss
// styles/_mixins.scss
@mixin flex-center {
display: flex;
align-items: center;
justify-content: center;
}

@mixin responsive($breakpoint) {
@if $breakpoint == sm {
@media (min-width: 576px) { @content; }
} @else if $breakpoint == md {
@media (min-width: 768px) { @content; }
} @else if $breakpoint == lg {
@media (min-width: 992px) { @content; }
} @else if $breakpoint == xl {
@media (min-width: 1200px) { @content; }
}
}

@mixin card-shadow {
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.08);
transition: box-shadow 0.3s ease;

&:hover {
box-shadow: 0 10px 15px rgba(0, 0, 0, 0.1), 0 4px 6px rgba(0, 0, 0, 0.05);
}
}
  1. Use these mixins in your component styles:
scss
// styles/Hero.module.scss
@import './variables';
@import './mixins';

.hero {
@include flex-center;
flex-direction: column;
min-height: 70vh;
background-color: $light-color;
padding: 20px;

.title {
font-size: 2rem;
margin-bottom: 1rem;

@include responsive(md) {
font-size: 3rem;
}

@include responsive(lg) {
font-size: 4rem;
}
}

.card {
background-color: white;
padding: 20px;
border-radius: 8px;
max-width: 500px;
width: 100%;
@include card-shadow;
}
}

Configuring Sass in Next.js

If you need to customize the Sass compilation, you can do so in the Next.js configuration file:

js
// next.config.js
const path = require('path');

module.exports = {
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
// You can add other sass options here
},
}

This configuration allows you to:

  • Set include paths for imports
  • Configure other Sass options like output style, precision, etc.

Practical Example: Building a Responsive Layout

Let's create a complete example of a responsive layout using Sass in Next.js:

1. Setup the Variables and Mixins

scss
// styles/_variables.scss
$primary-color: #0070f3;
$text-color: #333;
$light-bg: #f9f9f9;

$breakpoints: (
'sm': 576px,
'md': 768px,
'lg': 992px,
'xl': 1200px
);
scss
// styles/_mixins.scss
@import './_variables';

@mixin respond-to($breakpoint) {
@if map-has-key($breakpoints, $breakpoint) {
@media (min-width: map-get($breakpoints, $breakpoint)) {
@content;
}
} @else {
@warn "Unknown breakpoint: #{$breakpoint}.";
}
}

2. Create a Layout Component

scss
// styles/Layout.module.scss
@import './_variables';
@import './_mixins';

.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}

.header {
padding: 1rem 0;
border-bottom: 1px solid darken($light-bg, 10%);

nav {
display: flex;
flex-direction: column;

@include respond-to('md') {
flex-direction: row;
align-items: center;
justify-content: space-between;
}
}

.logoContainer {
margin-bottom: 1rem;

@include respond-to('md') {
margin-bottom: 0;
}
}

.navLinks {
display: flex;
flex-direction: column;
gap: 1rem;

@include respond-to('md') {
flex-direction: row;
}

a {
color: $text-color;
text-decoration: none;
font-weight: 500;

&:hover {
color: $primary-color;
}
}
}
}

.main {
padding: 2rem 0;
}

.footer {
padding: 2rem 0;
text-align: center;
background-color: $light-bg;
margin-top: 2rem;
}
jsx
// components/Layout.js
import styles from '../styles/Layout.module.scss';
import Link from 'next/link';

export default function Layout({ children }) {
return (
<>
<header className={styles.header}>
<div className={styles.container}>
<nav>
<div className={styles.logoContainer}>
<Link href="/">
<a><h1>My Next.js App</h1></a>
</Link>
</div>
<div className={styles.navLinks}>
<Link href="/">Home</Link>
<Link href="/about">About</Link>
<Link href="/blog">Blog</Link>
<Link href="/contact">Contact</Link>
</div>
</nav>
</div>
</header>

<main className={styles.main}>
<div className={styles.container}>
{children}
</div>
</main>

<footer className={styles.footer}>
<div className={styles.container}>
© {new Date().getFullYear()} My Next.js App. All rights reserved.
</div>
</footer>
</>
);
}

3. Use the Layout in _app.js

jsx
// pages/_app.js
import '../styles/globals.scss';
import Layout from '../components/Layout';

function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
);
}

export default MyApp;

Common Issues and Solutions

1. Global Styles Not Applying

Issue: You've imported your Sass file but styles aren't showing up.

Solution: Make sure you're importing the global styles in _app.js, not in individual pages.

2. Module Styles Not Applying Correctly

Issue: Your class names from Sass modules aren't working.

Solution: Check that you're using the correct syntax:

jsx
// Correct usage
import styles from './Button.module.scss';
<div className={styles.myClass}> ... </div>

// Incorrect usage
<div className="myClass"> ... </div>

3. Can't Access Sass Variables in JS

Issue: You're trying to use Sass variables in your JavaScript code.

Solution: Sass variables are compiled away. For sharing values between JS and CSS, consider using CSS custom properties:

scss
:root {
--primary-color: #0070f3;
}

.button {
background-color: var(--primary-color);
}

Then in your JS:

jsx
// Now you can access the CSS variable
const primaryColor = getComputedStyle(document.documentElement)
.getPropertyValue('--primary-color');

Summary

In this guide, we've explored how to integrate Sass with Next.js to enhance your styling capabilities:

  1. Setup: Installing the sass package and creating Sass files
  2. Global Styles: Applying styles across your entire application
  3. Component-Level Styling: Using Sass modules to scope styles to specific components
  4. Advanced Features: Leveraging variables, mixins, and other Sass features
  5. Configuration: Customizing Sass options in Next.js
  6. Practical Examples: Building responsive layouts using Sass

Sass integration with Next.js provides a powerful way to organize and manage your styles while maintaining the benefits of component-based architecture. By using variables, mixins, and modules, you can create more maintainable and scalable stylesheets for your Next.js applications.

Additional Resources

Exercises

  1. Create a theme system using Sass variables that supports both light and dark modes
  2. Build a responsive grid system using Sass mixins
  3. Create a reusable component library with styled buttons, cards, and form elements
  4. Implement a navigation menu that transforms into a hamburger menu on mobile screens using Sass mixins
  5. Create a Sass function that generates color variants (lighter and darker shades) from a base color


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)