Design Converter
Education
Senior Software Engineer
Last updated on Jun 5, 2024
Last updated on May 27, 2024
Next.js has emerged as a leading framework for building React applications focusing on performance and developer experience. Regarding styling these applications, CSS-in-JS libraries have become increasingly popular due to their ability to provide dynamic styling capabilities directly within JavaScript code. Emotion is one such library that stands out for its powerful and flexible approach to styling in Next.js applications.
Next.js is a React framework that enables functionality such as server-side rendering and generating static websites for React-based web applications. It's designed to make the development process smoother and optimize the applications' performance. With features like file-based routing, built-in CSS and Sass support, and pre-rendering, Next.js helps you create robust web applications.
When you create a Next.js application using create next app, you're setting up a project structure that includes an app directory and a pages directory, among other things. The app directory is where you can define your root layout and global styles, while the pages directory contains your page components that correspond to routes.
Emotion is a performant and flexible CSS-in-JS library that allows you to style applications quickly and with a great degree of customization. It supports both the styled components pattern and the css prop, making it a versatile choice for developers familiar with CSS-in-JS methodologies. Emotion is also compatible with client components in Next.js, although it may require specific configurations to work seamlessly.
With Emotion, you can define styles in a JavaScript file using the styled function, which can then be applied to your React components. This approach not only keeps your styles co-located with your components but also leverages the full power of JavaScript to create dynamic styles.
Combining Next.js with Emotion enhances the styling experience by allowing developers to write CSS styles alongside JavaScript logic. This integration is straightforward and brings the power of Emotion’s CSS-in-JS capabilities into the Next.js ecosystem, offering a seamless development workflow. Additionally, using a custom document component in Next.js helps render styles and insert them into the <head>
.
To start using Emotion in your Next.js project, you need to install the necessary dependencies. This includes @emotion/react for the React-specific Emotion library and @emotion/styled for using the styled components pattern. You may also want to include @emotion/server for server-side rendering optimizations.
Here's how you can install these dependencies:
1npm install @emotion/react @emotion/styled @emotion/server
Once the dependencies are installed, you can begin to use Emotion in your Next.js project. For example, you can create a styled component using Emotion's styled function:
1import styled from '@emotion/styled'; 2 3const StyledButton = styled.button` 4 background-color: #ff6b6b; 5 color: white; 6 font-size: 16px; 7 padding: 10px 20px; 8 border: none; 9 border-radius: 4px; 10 cursor: pointer; 11 &:hover { 12 background-color: #ff8787; 13 } 14`; 15 16function Home() { 17 return ( 18 <div> 19 <StyledButton>Click Me</StyledButton> 20 </div> 21 ); 22} 23 24export default Home;
In Next.js, the App component plays a crucial role as it initializes pages. You can override the default App component to include global styles or to set up a custom Emotion cache. This is done by creating a _app.js file in the ‘pages’ directory.
Here's an example of how to customize the App component to use Emotion with a custom cache:
1import { CacheProvider } from '@emotion/react'; 2import createCache from '@emotion/cache'; 3 4// Create a custom cache instance 5const cache = createCache({ key: 'custom' }); 6 7function MyApp({ Component, pageProps }) { 8 return ( 9 // Provide the custom cache to the app 10 <CacheProvider value={cache}> 11 <Component {...pageProps} /> 12 </CacheProvider> 13 ); 14} 15 16export default MyApp;
By wrapping your application with the CacheProvider from Emotion and passing in your custom cache, you ensure that all your styled components use this cache instance. This can be beneficial for performance optimizations and for avoiding conflicts with other instances of Emotion potentially used by third-party components.
Integrating Emotion with Next.js is a process that enhances the styling capabilities of your application. With these steps, you can set up Emotion in your Next.js project and start building beautifully styled components with ease.
Emotion shines when it comes to styling in Next.js, offering a CSS-in-JS solution that is both powerful and developer-friendly. By leveraging Emotion, you can write styles that are both dynamic and reusable, with all the benefits of JavaScript logic. Additionally, Emotion can insert critical css right before it's required, ensuring optimal performance and seamless integration with global styles.
Emotion 10 and above enhances server-side rendering by inserting style tags directly into the markup, which can sometimes interfere with certain selectors.
Styled components are a cornerstone of Emotion, allowing developers to encapsulate styles within reusable components. This pattern is particularly useful for creating a consistent design system across your Next.js application.
To use styled components with Emotion in Next.js, you first define your styled components using the styled function from @emotion/styled. Here's how you can define a NavBar component using Emotion's styled function:
1import styled from '@emotion/styled'; 2 3const NavBar = styled.nav` 4 background-color: #348; 5 color: #fff; 6 padding: 1rem; 7 display: flex; 8 justify-content: space-between; 9 align-items: center; 10`; 11 12const NavItem = styled.a` 13 color: #fff; 14 text-decoration: none; 15 margin-left: 2rem; 16 17 &:first-of-type { 18 margin-left: 0; 19 } 20 21 &:hover { 22 color: #ddd; 23 } 24`; 25 26function Header() { 27 return ( 28 <NavBar> 29 <div>Logo</div> 30 <div> 31 <NavItem href="#">Home</NavItem> 32 <NavItem href="#">About</NavItem> 33 <NavItem href="#">Services</NavItem> 34 <NavItem href="#">Contact</NavItem> 35 </div> 36 </NavBar> 37 ); 38} 39 40export default Header;
In this example, the NavBar and NavItem components are styled using Emotion's styled function, encapsulating all the necessary styles for the navigation bar and its items. The NavBar component sets the background color, layout, and spacing, while NavItem takes care of the individual navigation links' styling. These components can now be reused throughout the application, ensuring a consistent look and feel for the navigation experience.
React Server Components represent a new approach to building React applications, allowing you to render components on the server without sending the corresponding JavaScript to the client. This can significantly reduce the amount of code sent over the wire and improve performance.
Emotion works well with React Server Components, as it can generate the necessary CSS on the server and send only the styles that are required for the initial render. This is achieved through the use of Emotion's server-side rendering APIs, which extract critical CSS and enable it to be inlined in the HTML response.
Here's an example of how you might use Emotion with React Server Components in a Next.js application:
1// pages/_document.js 2import Document, { Html, Head, Main, NextScript } from 'next/document'; 3import { CacheProvider } from '@emotion/react'; 4import createEmotionServer from '@emotion/server/create-instance'; 5import createCache from '@emotion/cache'; 6 7const key = 'custom'; 8const cache = createCache({ key }); 9const { extractCritical } = createEmotionServer(cache); 10 11export default class MyDocument extends Document { 12 static async getInitialProps(ctx) { 13 const originalRenderPage = ctx.renderPage; 14 15 ctx.renderPage = () => 16 originalRenderPage({ 17 enhanceApp: (App) => (props) => ( 18 <CacheProvider value={cache}> 19 <App {...props} /> 20 </CacheProvider> 21 ), 22 }); 23 24 const initialProps = await Document.getInitialProps(ctx); 25 const styles = extractCritical(initialProps.html); 26 return { 27 ...initialProps, 28 styles: ( 29 <> 30 {initialProps.styles} 31 <style 32 data-emotion={`${key} ${styles.ids.join(' ')}`} 33 dangerouslySetInnerHTML={{ __html: styles.css }} 34 /> 35 </> 36 ), 37 }; 38 } 39 40 render() { 41 return ( 42 <Html> 43 <Head /> 44 <body> 45 <Main /> 46 <NextScript /> 47 </body> 48 </Html> 49 ); 50 } 51}
1// components/ServerRenderedTitle.js 2import { css } from '@emotion/react'; 3 4const titleStyle = css` 5 color: #333; 6 font-size: 24px; 7`; 8 9function ServerRenderedTitle() { 10 return <h1 css={titleStyle}>Welcome to Next.js with Emotion</h1>; 11} 12 13export default ServerRenderedTitle;
Custom _document.js:
Purpose: This file customizes the initial HTML document structure in a Next.js application.
Emotion Integration: It sets up Emotion for server-side rendering by creating a custom cache and extracting critical CSS.
Steps:
createCache and createEmotionServer are used to configure Emotion's server-side rendering.
The CacheProvider wraps the application to provide Emotion's cache.
The extractCritical function extracts the necessary CSS from the rendered HTML.
The critical CSS is inlined into the HTML response within a <style>
tag.
Example Component (ServerRenderedTitle):
Purpose: Demonstrates how to use Emotion's css function to style a React component.
Usage: The ServerRenderedTitle component is styled using Emotion and can be rendered on the server.
Key Point: Emotion ensures that only the critical CSS needed for the component is included in the server-rendered HTML, optimizing loading performance.
By following this approach, you can effectively use Emotion with React Server Components in a Next.js application, ensuring efficient server-side rendering and optimized CSS delivery.
When using Emotion with Next.js, it’s important to follow best practices to ensure that your application is not only visually appealing but also performs well. Emotion provides various mechanisms to optimize the CSS-in-JS experience, helping you maintain a high-performance application. Additionally, using gatsby-plugin-emotion is recommended for enabling emotion's SSR with Gatsby.
To optimize your use of CSS-in-JS with Emotion in a Next.js application, consider the following strategies:
1/** @jsxImportSource @emotion/react */ 2import { css } from '@emotion/react'; 3 4function DynamicStyledComponent({ isActive }) { 5 return ( 6 <div 7 css={css` 8 color: ${isActive ? 'green' : 'red'}; 9 transition: color 0.3s; 10 `} 11 > 12 This text changes color based on the isActive prop. 13 </div> 14 ); 15}
1// Example of extracting critical CSS with Emotion 2import { extractCritical } from '@emotion/server'; 3 4const { css, ids } = extractCritical(renderToString(<MyApp />));
1import createCache from '@emotion/cache'; 2const cache = createCache({ key: 'custom' });
1import styled from '@emotion/styled'; 2 3const StaticStyledButton = styled.button` 4 background-color: #0070f3; 5 /* ... other static styles ... */ 6`;
As your Next.js application grows, it's crucial to keep scalability in mind. Here are some tips to ensure that your use of Emotion scales well with your application's complexity:
1import dynamic from 'next/dynamic'; 2 3const LazyLoadedComponent = dynamic(() => import('./LazyLoadedComponent'), { 4 ssr: false, 5});
Componentization: Break down your UI into small, reusable components. This makes it easier to manage styles and improves the maintainability of your application.
Theme integration: Use Emotion's theming capabilities to maintain consistency across your application. A theme provider can help manage colors, fonts, and other design tokens.
1import { ThemeProvider } from '@emotion/react'; 2 3const theme = { 4 colors: { 5 primary: '#0070f3', 6 // ... other colors ... 7 }, 8 // ... other theme properties ... 9}; 10 11function App({ Component, pageProps }) { 12 return ( 13 <ThemeProvider theme={theme}> 14 <Component {...pageProps} /> 15 </ThemeProvider> 16 ); 17}
Performance monitoring: Regularly monitor the performance of your application using tools like Lighthouse or Next.js's built-in analytics. This can help you identify bottlenecks related to CSS-in-JS and address them promptly.
Documentation and conventions: Establish coding conventions and document how to use Emotion in your project. This ensures that all developers on the team use Emotion consistently and efficiently.
Embracing Next.js Emotion unlocks a powerful and efficient way to handle styling in your React applications. By leveraging styled components and Emotion's CSS-in-JS capabilities, you can create dynamic, reusable, and maintainable styles that scale with your application's growth. With the added benefits of performance optimizations through critical CSS extraction and server-side rendering, Emotion stands out as an excellent choice for developers looking to combine the robust features of Next.js with the flexibility of CSS-in-JS.
Tired of manually designing screens, coding on weekends, and technical debt? Let DhiWise handle it for you!
You can build an e-commerce store, healthcare app, portfolio, blogging website, social media or admin panel right away. Use our library of 40+ pre-built free templates to create your first application using DhiWise.