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:
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:
- Create a file named
globals.scss
in yourstyles
directory:
// 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;
}
- Import this file in your
pages/_app.js
file:
// 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:
- Create a file named
Button.module.scss
in yourstyles
directory:
// 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%);
}
}
}
- Use this module in a component:
// 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;
- Now you can use this Button component in any page:
// 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:
- Create a file named
_variables.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;
- Import these variables in your other Sass files:
// 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:
- Create a file named
_mixins.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);
}
}
- Use these mixins in your component styles:
// 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:
// 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
// styles/_variables.scss
$primary-color: #0070f3;
$text-color: #333;
$light-bg: #f9f9f9;
$breakpoints: (
'sm': 576px,
'md': 768px,
'lg': 992px,
'xl': 1200px
);
// 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
// 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;
}
// 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
// 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:
// 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:
:root {
--primary-color: #0070f3;
}
.button {
background-color: var(--primary-color);
}
Then in your JS:
// 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:
- Setup: Installing the
sass
package and creating Sass files - Global Styles: Applying styles across your entire application
- Component-Level Styling: Using Sass modules to scope styles to specific components
- Advanced Features: Leveraging variables, mixins, and other Sass features
- Configuration: Customizing Sass options in Next.js
- 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
- Create a theme system using Sass variables that supports both light and dark modes
- Build a responsive grid system using Sass mixins
- Create a reusable component library with styled buttons, cards, and form elements
- Implement a navigation menu that transforms into a hamburger menu on mobile screens using Sass mixins
- 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! :)