How to Integrate CSS and Sass in Next.js?

Farihatul Maria on 2024-08-05

Next.js is a powerful React framework that provides built-in support for CSS and Sass, making it easier to style your applications. This article will guide you through the steps to integrate CSS and Sass into your Next.js project, covering both global and component-scoped styles.

How to Integrate CSS and Sass in Next.js? Next.js is a powerful React framework that provides built-in support for CSS and Sass, making it easier to style your…tidewave.net

Setting Up a Next.js Project

Before we begin, let’s set up a new Next.js project. If you already have a project, you can skip this step.

npx create-next-app@latest my-nextjs-app
cd my-nextjs-app

Integrating Global CSS

Integrating global CSS into a Next.js project allows you to apply styles that affect your entire application consistently. Here’s a step-by-step guide on how to set up and use global CSS in Next.js:

1. Create a Global CSS File

First, create a CSS file for your global styles. Typically, this file is named globals.css and placed in the styles directory.

mkdir styles
touch styles/globals.css

Add your global styles to this globals.css file. For example:

/* styles/globals.css */
body {
  font-family: Arial, sans-serif;
  margin: 0;
  padding: 0;
  color: #333;
}

a {
  color: #0070f3;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

2. Import Global CSS in _app.js

Next, you need to import this CSS file into your custom App component, which is defined in pages/_app.js. This ensures that the global styles are applied across all pages.

// pages/_app.js
import '../styles/globals.css'; // Import global CSS

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

export default MyApp;

3. Ensure CSS Modules for Component-Level Styles

For component-level styles, you can still use CSS Modules. Create a CSS file with the .module.css extension for styles scoped to specific components.

touch components/MyComponent.module.css

In the CSS Module file, define styles specific to that component:

/* components/MyComponent.module.css */
.myComponent {
  background-color: #f0f0f0;
  padding: 10px;
}

Import and use the styles in your component:

// components/MyComponent.js
import styles from './MyComponent.module.css';

function MyComponent() {
  return <div className={styles.myComponent}>Hello World</div>;
}

export default MyComponent;

4. Avoid Importing CSS in Other Components

Do not import global CSS files in individual components. Instead, rely on the import in _app.js to ensure that global styles are applied universally.

5. Handle Vendor CSS Libraries

If you use third-party CSS libraries (e.g., Bootstrap), import these styles into _app.js as well, or within specific components if only needed for those parts:

// pages/_app.js
import '../styles/globals.css'; // Your global CSS
import 'bootstrap/dist/css/bootstrap.min.css'; // Example for Bootstrap

If you want to know about Vendor Splitting then this article is for you :

What is Code Splitting in Next.js? How Does It Improve Performance? Code splitting is a crucial performance optimization technique in modern web development, particularly in Next.js…tidewave.net

6. Ensure Build-Time CSS Optimization

Next.js automatically handles CSS optimization, including CSS tree-shaking and minification, when building your project for production. Ensure you run next build to optimize your styles for production.

Integrating Component-Scoped CSS

Integrating component-scoped CSS in a Next.js project allows you to apply styles that are specific to individual components without affecting others. This approach uses CSS Modules, which provide a way to scope CSS to a particular component. Here’s how you can set it up:

1. Create a CSS Module File

For each component that requires scoped styles, create a corresponding CSS Module file. These files use the .module.css extension to indicate that the styles are scoped locally.

For example, create a file named MyComponent.module.css in the same directory as your component:

touch components/MyComponent.module.css

Add your component-specific styles to this file:

/* components/MyComponent.module.css */
.container {
  background-color: #f9f9f9;
  padding: 20px;
  border-radius: 8px;
}

.title {
  color: #333;
  font-size: 24px;
}

2. Import CSS Module in Your Component

Import the CSS Module file into your component and use the styles as an object. Each class name is accessible via the styles object.

// components/MyComponent.js
import styles from './MyComponent.module.css';

function MyComponent() {
  return (
    <div className={styles.container}>
      <h1 className={styles.title}>Hello, World!</h1>
    </div>
  );
}

export default MyComponent;

3. Use Component in Your Application

Now you can use MyComponent throughout your application, and the styles defined in MyComponent.module.css will be applied only to this component.

// pages/index.js
import MyComponent from '../components/MyComponent';

export default function Home() {
  return (
    <div>
      <MyComponent />
    </div>
  );
}

4. Avoid Global CSS Interference

CSS Modules help prevent style conflicts and unintended overrides because the class names are automatically scoped locally. Avoid mixing CSS Modules with global CSS to maintain separation of concerns.

5. Combining CSS Modules with Global CSS

If you need to combine global styles with component-scoped styles, ensure that global styles are imported in _app.js and component styles are used within individual components:

// pages/_app.js
import '../styles/globals.css'; // Global CSS for application-wide styles

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

export default MyApp;

6. Handling Vendor and External Libraries

For third-party libraries that provide CSS, you can import their styles directly into _app.js or use them within specific components as needed. This ensures that component-scoped styles remain isolated.

// pages/_app.js
import '../styles/globals.css'; // Global CSS
import 'bootstrap/dist/css/bootstrap.min.css'; // Third-party library styles

7. CSS Module Features

CSS Modules support advanced features like local scoping, composition, and dynamic class names. For example, you can compose styles from other CSS Modules:

/* components/MyComponent.module.css */
.container {
  composes: baseContainer from './BaseStyles.module.css';
  background-color: #f9f9f9;
  padding: 20px;
}

By following these steps, you can efficiently integrate and manage component-scoped CSS in your Next.js project, ensuring modular and maintainable styles for your application.

Integrating Sass

Integrating Sass into a Next.js project allows you to use Sass features such as variables, nesting, and mixins to enhance your styling. Here’s how you can set up and use Sass in a Next.js project:

1. Install Sass

First, you need to install the sass package, which enables Sass support in your Next.js project.

Using npm:

npm install sass

or using yarn:

yarn add sass

2. Create Sass Files

You can create .scss or .sass files to use Sass in your project. Typically, these files are placed in the styles directory or alongside components if you are using component-scoped styles.

For example, create a file named globals.scss for global styles:

mkdir styles
touch styles/globals.scss

Add your Sass styles to globals.scss:

/* styles/globals.scss */
$primary-color: #0070f3;
$font-stack: Arial, sans-serif;

body {
  font-family: $font-stack;
  color: $primary-color;
}

a {
  color: $primary-color;
  text-decoration: none;

  &:hover {
    text-decoration: underline;
  }
}

3. Import Sass Files in _app.js

To ensure that the global styles are applied throughout your application, import the globals.scss file in your custom App component located in pages/_app.js.

// pages/_app.js
import '../styles/globals.scss'; // Import global Sass styles

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

export default MyApp;

4. Use Sass in Component Styles

If you want to use Sass for component-specific styles, create a Sass file with the .module.scss extension for CSS Modules.

For example, create a file named MyComponent.module.scss:

touch components/MyComponent.module.scss

Add your Sass styles to this file:

/* components/MyComponent.module.scss */
.container {
  background-color: #f0f0f0;
  padding: 20px;
  border-radius: 8px;
}

.title {
  color: $primary-color;
  font-size: 24px;
}

5. Import Sass Module in Your Component

Import the Sass module into your component and use the styles as an object.

// components/MyComponent.js
import styles from './MyComponent.module.scss';

function MyComponent() {
  return (
    <div className={styles.container}>
      <h1 className={styles.title}>Hello, Sass!</h1>
    </div>
  );
}

export default MyComponent;

6. Using Sass with Third-Party Libraries

If you need to include Sass files from third-party libraries, you can import them in your pages/_app.js or specific component files:

// pages/_app.js
import '../styles/globals.scss'; // Your global Sass styles
import 'bootstrap/scss/bootstrap.scss'; // Example for Bootstrap Sass

7. Handling Build-Time Optimization

Next.js will handle Sass compilation and optimization automatically during the build process. Ensure you run next build to apply these optimizations for production.

By following these steps, you can effectively integrate Sass into your Next.js project, enabling advanced styling capabilities and enhancing the maintainability of your styles.

Dynamic and Conditional Styling

With Next.js, you can dynamically apply styles based on conditions. For example, you can conditionally apply classes using template literals.

// pages/index.js
import styles from "../styles/Home.module.scss";

export default function Home({ isDarkMode }) {
  return (
    <div className={`${styles.container} ${isDarkMode ? styles.dark : ""}`}>
      <h1 className={styles.title}>Welcome to Next.js</h1>
    </div>
  );
}
/* styles/Home.module.scss */
$primary-color: #0070f3;
$dark-bg: #333;
$dark-color: #fff;

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background-color: #f0f0f0;
}

.title {
  color: $primary-color;
  font-size: 2rem;
}

.dark {
  background-color: $dark-bg;
  color: $dark-color;
}

Benefit of integrating CSS and Sass in Next.js project

Integrating CSS and Sass into a Next.js project offers several key benefits that enhance both the development experience and the quality of your application’s styling:

  1. Enhanced Styling Capabilities : —

2. Improved Maintainability : —

3. Increased Development Efficiency : —

4. Seamless Integration with Next.js : —

5. Better Performance : —

6. Flexibility and Extensibility : —

By integrating CSS and Sass in a Next.js project, you not only enhance the styling capabilities and maintainability of your application but also benefit from streamlined development processes and improved performance.

Advanced Tips for Integrating CSS and Sass in Next.js Projects

Integrating CSS and Sass into Next.js projects can be optimized with several advanced techniques to improve performance, maintainability, and scalability. Here are some advanced tips for integrating CSS and Sass in Next.js:

1. Utilize Sass Partials and Imports

Organize Sass Code: Break your Sass code into smaller, reusable partials (files prefixed with _) and import them into a main stylesheet. This makes it easier to manage and maintain your styles.

// styles/_variables.scss
$primary-color: #0070f3;
$font-stack: Arial, sans-serif;

// styles/_mixins.scss
@mixin border-radius($radius) {
  border-radius: $radius;
}

// styles/globals.scss
@import 'variables';
@import 'mixins';

body {
  font-family: $font-stack;
  color: $primary-color;
}

2. Use CSS Modules with Sass for Scoped Styles

Component-Level Styling: For component-scoped styles, use CSS Modules with Sass by naming your files with .module.scss extension. This ensures styles are scoped locally to components.

// components/MyComponent.module.scss
.container {
  background-color: $primary-color;
  @include border-radius(8px);
}

// components/MyComponent.js
import styles from './MyComponent.module.scss';

function MyComponent() {
  return <div className={styles.container}>Hello</div>;
}

3. Optimize Global Styles with CSS-in-Js

Combine with CSS-in-JS: Use CSS-in-JS libraries (e.g., styled-components) for component-level styles while keeping global styles in Sass. This provides flexibility and avoids style conflicts.

// components/StyledComponent.js
import styled from 'styled-components';

const StyledDiv = styled.div`
  background-color: ${props => props.theme.primaryColor};
`;

function StyledComponent() {
  return <StyledDiv>Hello</StyledDiv>;
}

4. Implement CSS Variables for Theming

Dynamic Theming: Use CSS variables for dynamic theming and to manage different themes within your application. This allows you to change themes without altering CSS directly.

// styles/globals.scss
:root {
  --primary-color: #0070f3;
  --font-stack: Arial, sans-serif;
}

body {
  font-family: var(--font-stack);
  color: var(--primary-color);
}

5. Leverage Sass Functions and Mixins

Custom Functions and Mixins: Create reusable Sass functions and mixins to handle complex styles and calculations, improving maintainability and consistency.

// styles/_mixins.scss
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

// styles/components.module.scss
.box {
  @include flex-center;
  background-color: $primary-color;
}

6. Use Critical CSS for Performance

Optimize Critical CSS: Extract and inline critical CSS for above-the-fold content to improve page load performance. This can be done using tools like critical or integrating with build-time optimizers.

Learn about Critical CSS here :

Critical CSS: Speeding Up Your Website's First Paint Have you ever landed on a webpage that took forever to load, only to stare at a blank screen before content appeared…tidewave.net

7. Implement Advanced Build-Time Optimization

Optimize Sass Builds: Configure advanced build-time optimizations using Next.js plugins or custom Webpack configurations to reduce CSS file sizes and enhance performance.

// next.config.js
module.exports = {
  webpack(config) {
    config.module.rules.push({
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: 'sass-loader',
          options: {
            // Options for Sass compilation
          },
        },
      ],
    });
    return config;
  },
};

8. Use PostCSS for Additional Processing

Integrate PostCSS: Enhance your CSS processing pipeline with PostCSS plugins (e.g., autoprefixer) to automatically handle vendor prefixes and other transformations.

// postcss.config.js
module.exports = {
  plugins: [
    require('autoprefixer'),
    require('cssnano')({ preset: 'default' }),
  ],
};

9. Apply Scoped CSS Using Styled Components

Component-Specific Styling: Use styled-components for styling React components with scoped, dynamic styles, while keeping global styles in Sass.

// components/StyledButton.js
import styled from 'styled-components';

const StyledButton = styled.button`
  background-color: ${props => props.primary ? '#0070f3' : '#fff'};
  color: ${props => props.primary ? '#fff' : '#0070f3'};
`;

function StyledButtonComponent() {
  return <StyledButton primary>Click me</StyledButton>;
}

10. Regularly Review and Refactor Styles

Maintainability: Regularly review and refactor your styles to ensure they remain organized and efficient as your project evolves. Use tools to identify unused CSS and optimize styles accordingly.

By implementing these advanced techniques, you can make the most of CSS and Sass in your Next.js project, leading to cleaner, more efficient, and maintainable styling solutions.

Conclusion

Integrating CSS and Sass into a Next.js project is both simple and effective. With global CSS, you can apply broad styles across your application, while CSS Modules offer scoped styling for individual components. Sass enhances your styling capabilities with advanced features like variables and mixins. These tools help you craft well-structured, maintainable, and scalable styles, ensuring your Next.js application remains visually appealing and performs efficiently. By employing these methods, you can achieve a balance between aesthetic quality and high performance.

You can read this article on the same topic ( But it’s shorter than this one 😄 😅) : https://tidewave.net/blog/how-to-integrate-css-and-sass-in-nextjs