Next JS Integrating CSS in JS


Integrating CSS-in-JS libraries like Styled Components and Emotion in Next.js allows you to write styles directly within your JavaScript files, providing dynamic styling capabilities and scoped styles for your components. Both libraries offer a modern approach to styling React applications and come with their own unique features. Below is an overview of how to integrate these libraries into a Next.js project.

1. Styled Components

Styled Components is a popular CSS-in-JS library that allows you to style your components using tagged template literals.

Installation

To use Styled Components in your Next.js application, first install it via npm or yarn:

npm install styled-components

or

yarn add styled-components

Setting Up Styled Components

You need to set up a custom _document.js file in your pages directory to ensure styles are rendered correctly on the server side.

Example Setup:

  1. Create _document.js:
// pages/_document.js import Document, { Html, Head, Main, NextScript } from 'next/document'; import { ServerStyleSheet } from 'styled-components'; export default class MyDocument extends Document { static async getInitialProps(ctx) { const sheet = new ServerStyleSheet(); const originalRenderPage = ctx.renderPage; ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => sheet.collectStyles(<App {...props} />), }); const initialProps = await Document.getInitialProps(ctx); return { ...initialProps, styles: [ <> {initialProps.styles} {sheet.getStyleElement()} </>, ], }; } render() { return ( <Html> <Head> <link rel="stylesheet" href="https://example.com/global-styles.css" /> </Head> <body> <Main /> <NextScript /> </body> </Html> ); } }

Creating Styled Components

Now you can create styled components within your components:

// components/MyComponent.js import styled from 'styled-components'; const Container = styled.div` padding: 20px; border: 1px solid #ccc; border-radius: 5px; background-color: #f4f4f4; `; const Title = styled.h1` font-size: 2em; color: #0070f3; `; const Button = styled.button` background-color: #0070f3; color: white; border: none; padding: 10px 15px; cursor: pointer; &:hover { background-color: darken(#0070f3, 10%); } `; const MyComponent = () => { return ( <Container> <Title>Hello, Styled Components!</Title> <Button>Click Me</Button> </Container> ); }; export default MyComponent;

2. Emotion

Emotion is another popular CSS-in-JS library that allows you to write CSS styles with JavaScript and supports both the styled component API and CSS prop.

Installation

To use Emotion in your Next.js application, install it via npm or yarn:

npm install @emotion/react @emotion/styled

or

yarn add @emotion/react @emotion/styled

Setting Up Emotion

Like Styled Components, you should set up a custom _document.js to manage server-side rendering of styles.

Example Setup:

  1. Create _document.js:
// pages/_document.js import Document, { Html, Head, Main, NextScript } from 'next/document'; import createEmotionServer from '@emotion/server/create-instance'; import createEmotionCache from '../utils/createEmotionCache'; export default class MyDocument extends Document { static async getInitialProps(ctx) { const cache = createEmotionCache(); const { extractCriticalToChunks } = createEmotionServer(cache); const originalRenderPage = ctx.renderPage; ctx.renderPage = () => originalRenderPage({ enhanceApp: (App) => (props) => <App {...props} emotionCache={cache} />, }); const initialProps = await Document.getInitialProps(ctx); const emotionStyles = extractCriticalToChunks(initialProps.html); return { ...initialProps, styles: [ <> {initialProps.styles} <style data-emotion={`${emotionStyles.ids.join(' ')}`} dangerouslySetInnerHTML={{ __html: emotionStyles.css }} /> </>, ], }; } render() { return ( <Html> <Head> <link rel="stylesheet" href="https://example.com/global-styles.css" /> </Head> <body> <Main /> <NextScript /> </body> </Html> ); } }
  1. Create createEmotionCache.js:
// utils/createEmotionCache.js import createCache from '@emotion/cache'; const createEmotionCache = () => { return createCache({ key: 'css' }); }; export default createEmotionCache;

Creating Emotion Styled Components

Now you can create styled components using Emotion:

// components/MyComponent.js /** @jsxImportSource @emotion/react */ import styled from '@emotion/styled'; const Container = styled.div` padding: 20px; border: 1px solid #ccc; border-radius: 5px; background-color: #f4f4f4; `; const Title = styled.h1` font-size: 2em; color: #0070f3; `; const Button = styled.button` background-color: #0070f3; color: white; border: none; padding: 10px 15px; cursor: pointer; &:hover { background-color: darken(#0070f3, 10%); } `; const MyComponent = () => { return ( <Container> <Title>Hello, Emotion!</Title> <Button>Click Me</Button> </Container> ); }; export default MyComponent;

Advantages of Integrating CSS-in-JS Libraries

  1. Scoped Styles: Both Styled Components and Emotion scope styles to the component, preventing style conflicts.

  2. Dynamic Styles: These libraries allow you to write dynamic styles based on props and state, making it easier to create responsive and interactive designs.

  3. Developer Experience: The integration with JSX enhances the developer experience by allowing you to manage styles and markup in a single file.

  4. Theming Support: Both libraries offer robust theming capabilities, allowing you to create consistent styles across your application easily.

  5. Server-Side Rendering: Both Styled Components and Emotion support server-side rendering, which is essential for performance and SEO in Next.js applications.

Important Considerations

  • Performance: CSS-in-JS solutions can introduce additional runtime overhead. However, both Styled Components and Emotion are optimized for performance.

  • Global Styles: For global styles, you can still use regular CSS files imported into _app.js, alongside your CSS-in-JS styles.

  • Learning Curve: If your team is already familiar with traditional CSS or preprocessors, there might be a learning curve when adopting CSS-in-JS solutions.

Summary

Integrating CSS-in-JS libraries like Styled Components and Emotion in Next.js enables you to manage styles effectively and dynamically within your components. With scoped styles, powerful theming capabilities, and built-in support for server-side rendering, these libraries enhance the styling experience in modern web applications. By following the setup processes outlined above, you can take advantage of these tools to create maintainable and visually appealing Next.js applications.