Next.js Functions

 

Implementing Dark Mode in NEXT.js Apps: CSS Variables and Theme Switching

In today’s digital landscape, user experience plays a pivotal role in the success of web applications. One essential aspect of user experience is the ability to provide users with choices that cater to their preferences, and one such preference is the choice between light and dark modes.

Implementing Dark Mode in NEXT.js Apps: CSS Variables and Theme Switching

Dark mode, characterized by its dark color scheme with light text, not only enhances visual appeal but also reduces eye strain, especially during nighttime usage. Implementing dark mode in your NEXT.js apps can greatly improve the user experience and make your application more accessible to a wider audience. In this guide, we’ll walk you through the process of adding dark mode to your NEXT.js application using CSS variables and theme switching.

1. Why Implement Dark Mode?

Before diving into the technical details, let’s briefly discuss why implementing dark mode in your NEXT.js app is a good idea.

1.1. Improved User Experience

Dark mode provides users with a visually pleasing and comfortable environment, especially in low-light conditions. It reduces eye strain and can make your app more accessible to a broader audience.

1.2. Enhanced Aesthetics

Many users simply prefer the sleek and modern look of dark mode. Implementing it can give your app a contemporary feel and attract users who appreciate this design.

1.3. Differentiation

Implementing dark mode can help your app stand out from the competition. Offering customization options like dark mode can make your app more appealing and unique.

Now that we understand the benefits, let’s get into the technical aspects of implementing dark mode in your NEXT.js app.

2. Setting Up Your NEXT.js Project

To get started, you need a NEXT.js project. If you don’t already have one, you can create a new NEXT.js app by running the following command:

bash
npx create-next-app my-dark-mode-app

Once your project is set up, navigate to the project directory using your terminal:

bash
cd my-dark-mode-app

3. Creating a Theme File

The first step in implementing dark mode is to create a theme file that will define the colors and styles for both light and dark modes. Let’s create a file named theme.js inside your project’s root directory:

javascript
// theme.js
export const lightTheme = {
  primaryBackground: 'white',
  primaryText: 'black',
  // Add more styles as needed
};

export const darkTheme = {
  primaryBackground: 'black',
  primaryText: 'white',
  // Add more styles as needed
};

In this example, we’ve defined two themes: lightTheme and darkTheme, each with its own set of colors. You can expand these themes to include more style properties according to your project’s requirements.

4. Creating a Theme Switcher Component

To allow users to switch between light and dark modes, you’ll need to create a theme switcher component. This component will toggle the active theme when clicked. Create a file named ThemeSwitcher.js in your components directory:

javascript
// ThemeSwitcher.js
import { useState } from 'react';
import { lightTheme, darkTheme } from '../theme';

const ThemeSwitcher = () => {
  const [isDarkMode, setIsDarkMode] = useState(false);

  const toggleTheme = () => {
    setIsDarkMode((prevMode) => !prevMode);
  };

  const currentTheme = isDarkMode ? darkTheme : lightTheme;

  return (
    <div>
      <button onClick={toggleTheme}>Toggle Dark Mode</button>
      <style jsx global>
        {`
          :root {
            --primary-background: ${currentTheme.primaryBackground};
            --primary-text: ${currentTheme.primaryText};
            // Add more CSS variables for other styles
          }
        `}
      </style>
    </div>
  );
};

export default ThemeSwitcher;

In this component, we use the useState hook to manage the dark mode state. The toggleTheme function toggles the isDarkMode state, which in turn updates the CSS variables in the :root pseudo-class, changing the theme dynamically.

5. Integrating the Theme Switcher

Now that you have your theme switcher component, you can integrate it into your application layout. Open your pages/_app.js file and include the ThemeSwitcher component:

javascript
// pages/_app.js
import { useEffect } from 'react';
import { ThemeProvider } from 'styled-components'; // You can use your preferred styling library
import { lightTheme, darkTheme } from '../theme';
import ThemeSwitcher from '../components/ThemeSwitcher';

function MyApp({ Component, pageProps }) {
  useEffect(() => {
    // Check for user preference and set the theme accordingly
    const userPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    if (userPrefersDark) {
      document.documentElement.style.setProperty('--primary-background', darkTheme.primaryBackground);
      document.documentElement.style.setProperty('--primary-text', darkTheme.primaryText);
    }
  }, []);

  return (
    <ThemeProvider theme={lightTheme}>
      <ThemeSwitcher />
      <Component {...pageProps} />
    </ThemeProvider>
  );
}

export default MyApp;

In this code, we’re using styled-components for styling, but you can adapt this to your preferred styling method. We also check the user’s preference for dark mode using the window.matchMedia API and set the initial theme accordingly.

6. Styling Your Components

Now that you have set up the themes and the theme switcher, it’s time to apply these themes to your components. You can use CSS variables to apply theme-specific styles to your components.

Let’s say you have a Button component that you want to style differently based on the theme. Here’s how you can do it:

javascript
// components/Button.js
import styled from 'styled-components';

const StyledButton = styled.button`
  background-color: var(--primary-background);
  color: var(--primary-text);
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
`;

const Button = ({ children, onClick }) => {
  return <StyledButton onClick={onClick}>{children}</StyledButton>;
};

export default Button;

In this example, we’re using styled-components to create a StyledButton component that uses CSS variables for background color and text color. This allows the button to automatically adapt to the active theme.

7. Testing Your Dark Mode

You can now test your dark mode implementation by running your NEXT.js app:

bash
npm run dev

Open your app in a web browser, and you should see the theme switcher button. Clicking it should toggle between light and dark modes, updating the styles of your components accordingly.

8. Additional Tips and Considerations

8.1. Persistence

To provide a seamless experience, you can store the user’s theme preference in a cookie or local storage so that it persists across sessions.

8.2. Accessibility

Ensure that your dark mode implementation is accessible. Test it with screen readers and keyboard navigation to make sure all users can use your app comfortably.

8.3. Customization

Allow users to customize their dark mode experience by providing options to adjust contrast, font size, and other aspects of the UI.

8.4. Testing

Thoroughly test your dark mode implementation across different browsers and devices to ensure a consistent experience for all users.

Conclusion

Implementing dark mode in your NEXT.js app can significantly enhance user experience and attract a broader audience. By using CSS variables and theme switching, you can create a seamless and visually appealing dark mode experience. Remember to consider persistence, accessibility, customization, and thorough testing to ensure your dark mode implementation is top-notch. With these steps, you’ll be well on your way to offering a modern and user-friendly application.

Dark mode is just one of many ways to improve your web app. Stay updated with the latest trends and technologies to keep your app competitive and user-friendly.

Previously at
Flag Argentina
Brazil
time icon
GMT-3
Accomplished Senior Software Engineer with Next.js expertise. 8 years of total experience. Proficient in React, Python, Node.js, MySQL, React Hooks, and more.