Emotion is a CSS-in-JS library for React (and other frameworks via adapters). It allows you to write CSS directly in your JavaScript components, leveraging the power of JavaScript’s expressiveness and dynamism to create styles. Instead of managing separate CSS files, you define styles as JavaScript objects, enabling powerful features like dynamic styling, theming, and server-side rendering (SSR) without the complexities of traditional CSS methodologies. Emotion compiles your styles into highly optimized CSS, minimizing the impact on your application’s performance.
Maintainability: Keeps your styles tightly coupled with the components they affect, leading to better organization and easier maintenance. No more hunting through separate CSS files.
Dynamic Styling: Easily create styles that change based on component props or application state. This is ideal for responsive design and interactive UIs.
Theming: Implement global themes and easily switch between them, creating consistent branding across your application.
SSR Support: Works seamlessly with server-side rendering, ensuring your styles are rendered correctly on the initial page load.
Performance: Emotion compiles styles into optimized CSS, minimizing bundle size and improving load times. It avoids unnecessary CSS generation, only producing the styles actually used in your application.
Extensibility: Offers various features and plugins to extend its functionality, such as CSS-in-JS features like styled-components
(though it has its own unique approach).
Community and Support: Emotion boasts a large and active community, providing ample resources and support.
The simplest way to add Emotion to your React project is via npm or yarn:
npm install @emotion/react @emotion/styled
# or
yarn add @emotion/react @emotion/styled
You’ll primarily be using @emotion/react
for inline styling and @emotion/styled
for creating styled components. Ensure these packages are correctly installed and referenced in your project setup.
Inline Styles with @emotion/react
:
import { css } from '@emotion/react';
function MyComponent() {
const myStyles = css`
color: blue;
font-size: 16px;
`;
return <div css={myStyles}>Hello, Emotion!</div>;
}
Styled Components with @emotion/styled
:
import styled from '@emotion/styled';
const MyButton = styled.button`
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
`;
function MyComponent() {
return <MyButton>Click Me</MyButton>;
}
These examples demonstrate the core principles of using Emotion: defining styles as JavaScript objects and applying them directly to React components. Further exploration of advanced features (e.g., theming, media queries, pseudo-selectors) is available in the Emotion documentation.
Emotion’s styled
API allows you to create reusable, styled components. These components are essentially React components that have styles attached directly to them. This approach promotes code organization and reusability. You create styled components by calling styled
with a base React component (like div
, span
, button
, etc.) and then providing a template literal containing your CSS.
import styled from '@emotion/styled';
const MyButton = styled.button`
background-color: blue;
color: white;
padding: 10px 20px;
border: none;
cursor: pointer;
`;
// Usage:
<MyButton>Click me</MyButton>
Styled components inherit the props of their base component and allow you to add dynamic styles based on props.
Emotion is a CSS-in-JS library. This means you write CSS directly within your JavaScript code, as opposed to in separate CSS files. This approach offers several advantages, including dynamic styling, improved code organization, and better tooling integration. Emotion processes this CSS and generates highly optimized CSS at runtime or build time.
css
propThe css
prop is a fundamental part of Emotion. It allows you to apply styles inline to any React component. You pass a CSS object or a template literal to the css
prop.
import { css } from '@emotion/react';
const myStyles = css`
color: red;
font-size: 18px;
`;
// Usage:
<div css={myStyles}>This text is red and 18px.</div>
The css
prop can also accept dynamic values.
Interpolation allows you to inject JavaScript variables and expressions into your CSS template literals. This is incredibly useful for dynamic styling based on component props or application state.
import { css } from '@emotion/react';
const MyComponent = ({ color }) => {
const myStyles = css`
background-color: ${color};
padding: 10px;
`;
return <div css={myStyles}>Dynamically Styled!</div>;
; }
This allows you to create responsive and data-driven styles with ease.
Emotion supports theming through context providers. You can define a theme object and make it available to your styled components via context. This makes it easy to apply consistent styling throughout your application and switch between different themes (e.g., light/dark mode).
import { ThemeProvider, css } from '@emotion/react';
const theme = {
colors: {
primary: 'blue',
secondary: 'green'
};
}
const MyComponent = () => (
<div css={theme => css`background-color: ${theme.colors.primary};`}>
with theme
Styled </div>
;
)
<ThemeProvider theme={theme}>
<MyComponent />
</ThemeProvider>
Emotion allows you to use media queries within your styled components and css
prop. This allows you to create responsive designs that adapt to different screen sizes and devices.
import styled from '@emotion/styled';
const MyDiv = styled.div`
width: 100%;
@media (min-width: 768px) {
width: 50%;
}
`;
Emotion supports all standard CSS pseudo-selectors like :hover
, :focus
, :active
, :before
, :after
, etc. You use these just like you would in regular CSS.
import styled from '@emotion/styled';
const MyButton = styled.button`
background-color: blue;
color: white;
&:hover {
background-color: green;
}
`;
Emotion allows you to define and use CSS keyframes for animations.
import { keyframes, css } from '@emotion/react';
const fadeIn = keyframes`
from { opacity: 0; }
to { opacity: 1; }
`;
const MyComponent = () => (
<div css={css`animation: ${fadeIn} 1s ease-in-out;`}>Fading In</div>
; )
Remember to consult the official Emotion documentation for more advanced usage and detailed explanations of each feature.
Emotion encourages component composition. You can nest styled components or combine them using the css
prop to create complex and reusable UI elements. This promotes modularity and reduces code duplication. For example:
import styled from '@emotion/styled';
const Box = styled.div`
border: 1px solid black;
padding: 10px;
`;
const Button = styled.button`
background-color: blue;
color: white;
`;
const MyComponent = () => (
<Box>
<Button>Click me</Button>
</Box>
; )
This approach leads to cleaner and more maintainable code.
Styled components inherit styles from their parent components. This simplifies styling and promotes consistency across your application. Styles defined in a parent component will cascade down to its children unless overridden. Consider this:
import styled from '@emotion/styled';
const Container = styled.div`
font-family: sans-serif;
`;
const Item = styled.div`
color: blue;
`;
<Container>
<Item>This text inherits the sans-serif font-family.</Item>
</Container>
Emotion doesn’t provide built-in utility classes like some CSS frameworks. However, you can easily create your own set of utility styled components or use a separate utility library alongside Emotion. This keeps your style management flexible and tailored to your project’s needs. For example, a simple utility:
import styled from '@emotion/styled';
const Flex = styled.div`
display: flex;
`;
Emotion allows injecting global styles that apply to your entire application. This is useful for setting default styles or applying consistent design patterns.
import { Global } from '@emotion/react';
const globalStyles = {
body: {
margin: 0,
fontFamily: 'sans-serif',
,
};
}
// ... inside your app:
<Global styles={globalStyles} />
Emotion is designed to work seamlessly with server-side rendering. This ensures that your styles are rendered correctly on the server and the client, preventing the “flash of unstyled content” (FOUC) problem. Make sure you follow Emotion’s recommended setup for SSR in your framework. Correct hydration is crucial for performance.
Emotion excels at styling functional and class components. You can apply styles using the css
prop or by creating styled components that wrap your existing components. This allows you to integrate Emotion into existing React codebases without significant refactoring.
Beyond basic theming, Emotion allows for more complex theming strategies. You can use techniques like nested theme objects, theme functions, and custom context providers to manage highly dynamic and customizable themes. This allows for powerful design systems and component variations.
For very specific needs, you can customize Emotion’s styling process using plugins or by directly interacting with its internal APIs. This level of customization allows you to integrate with other tools or to optimize Emotion for particular performance needs. However, proceed with caution as this requires a more in-depth understanding of Emotion’s internals. Refer to the advanced sections of the official Emotion documentation for guidance on this.
Emotion generally integrates well with other popular React libraries. However, some considerations may apply depending on the library:
Component Libraries: Most component libraries (e.g., Material-UI, Chakra UI) either use CSS-in-JS solutions themselves or can be styled using Emotion. You’ll typically need to ensure that styles from other libraries don’t conflict with your Emotion styles. Be mindful of style specificity and potentially use techniques like CSS Modules or scoped styles to avoid conflicts.
CSS Frameworks: While Emotion allows for CSS-in-JS, you can use it alongside a CSS framework (e.g., Bootstrap, Tailwind CSS). However, this requires careful management to avoid style clashes. Consider using Emotion for more dynamic or component-specific styles, while keeping the framework for more general utility classes.
State Management Libraries: Libraries like Redux or Zustand work seamlessly with Emotion. You can use state management to dynamically change styles based on application state.
Testing and debugging Emotion styles is similar to testing and debugging regular React components.
Unit Tests: You can test your styled components by rendering them in your unit tests and verifying their output using libraries like Jest and React Testing Library. Snapshot testing is useful for verifying the visual output of styled components.
Integration Tests: For complex interactions, integration tests can help ensure that styles are applied correctly in various scenarios.
Debugging: Use your browser’s developer tools to inspect styles and identify issues. You can inspect the generated CSS to troubleshoot style conflicts or unexpected behavior. Emotion’s developer tools (if available for your setup) can provide additional insights.
Emotion is designed to be performant, but there are strategies to further optimize your application:
Minimize unnecessary styles: Avoid over-engineering your styles. Only define the styles you truly need.
Use styled components effectively: Reuse styled components to reduce the amount of redundant CSS generated.
Optimize media queries: Ensure your media queries are efficient and target only necessary breakpoints.
Lazy loading: Use techniques like code splitting (see below) to load styles only when they are needed.
Avoid excessive nesting: Deeply nested styled components can sometimes impact performance. Try to maintain a reasonable level of nesting for improved render times.
Always consider accessibility when writing your styles. Ensure your styles adhere to WCAG guidelines and provide sufficient contrast, proper focus states, and semantic HTML.
Use semantic HTML: Choose appropriate HTML elements to convey the meaning and purpose of content.
Ensure sufficient color contrast: Use tools to check the contrast between text and background colors.
Provide adequate focus styles: Style focus states clearly for keyboard users.
Use ARIA attributes: If necessary, use ARIA attributes to provide additional accessibility information.
For larger applications, code splitting is essential for improved performance and reduced initial load times. Import styled components only when they’re needed to avoid loading unnecessary CSS during the initial page load. This usually involves dynamically importing modules or using techniques provided by your bundler (e.g., Webpack’s dynamic import()
). For example:
const MyComponent = () => {
const [showComponent, setShowComponent] = useState(false);
const loadComponent = () => import('./MyStyledComponent').then(module => {
// Use module.default here
;
})
return (
<>
<button onClick={() => {setShowComponent(true); loadComponent()}}>Load Component</button>
&& <MyComponent />}
{showComponent </>
;
); }
This approach loads the styled component only when the user interacts with the component. This can significantly improve initial load times for large applications.
Migrating from other styling solutions to Emotion requires a careful approach, depending on the source.
From CSS: The most significant change is moving from external CSS files to inline styles within your JavaScript components. You’ll need to rewrite your CSS rules as JavaScript objects or template literals using Emotion’s css
prop or styled
API. The process can be automated partially using tools or scripts depending on the complexity of your CSS, but manual review is usually necessary.
From other CSS-in-JS libraries (e.g., styled-components): While the core concept is similar, the APIs differ. You’ll need to rewrite your styles using Emotion’s syntax and functionalities. The transition might be smoother for simpler projects but could be complex for large applications with deeply nested components and custom theming logic. The Emotion documentation often provides migration guides for common CSS-in-JS libraries.
From inline styles (without a library): If you’re using plain inline styles in your React components, the transition is relatively straightforward. You can simply wrap your inline styles with Emotion’s css
function, which provides more advanced features and better organization.
Regardless of the source, thorough testing is crucial after migration to ensure all styles are working correctly.
Style conflicts: If styles aren’t applied as expected, it could be due to style specificity conflicts. Ensure that your Emotion styles have sufficient specificity to override other styles. Use the browser’s developer tools to inspect the CSS cascade.
Missing styles: Check your imports and ensure that the necessary Emotion packages are correctly installed and that you’re using the appropriate APIs (css
, styled
, etc.). Also, check for typos in class names or selectors.
Dynamic styles not updating: Confirm that the state or props you’re using to drive dynamic styles are correctly updated. React’s reconciliation process should automatically update the rendered styles. If not, inspect your component’s render cycles.
SSR issues (see below): SSR issues are often related to hydration problems or incorrect setup.
Unexpected behavior with media queries or pseudo-selectors: Verify the syntax of your media queries and pseudo-selectors and ensure they are correctly interpreted by Emotion. Browser developer tools can help debug this.
Browser developer tools: The browser’s developer tools (especially the “Elements” panel) are essential for debugging CSS. Inspect the rendered HTML and CSS to identify any discrepancies.
Console logging: Log relevant state and prop values to track how dynamic styles are changing.
Simplify your styles: If you encounter complex issues, temporarily simplify your styles to isolate the problem. Start with minimal styles to ensure basic functionality before adding complexity.
Emotion’s developer tools (if applicable): Check if Emotion offers any browser extensions or tools that provide insights into the styling process.
Check Emotion’s documentation and community resources: The Emotion documentation and community forums are excellent resources for finding solutions to common problems and debugging strategies.
Server-side rendering issues with Emotion often stem from hydration problems. Ensure you’ve followed Emotion’s recommendations for setting up SSR in your framework.
Hydration mismatch: If the client-side rendering doesn’t match the server-side rendering, inspect the rendered HTML for any discrepancies. Ensure the server and client have the same Emotion version and configuration.
Missing styles on the server: Verify that your styles are correctly generated and included in the server-side rendered HTML. Inspect the HTML source to check if the styles are present.
Incorrect setup: Ensure you have correctly configured Emotion’s SSR features, following the specific guidelines for your framework (Next.js, Gatsby, etc.). Check the Emotion documentation for your framework.
Caching issues: Incorrect caching can lead to stale styles being rendered. Ensure your caching strategy is appropriate for your application.
Use Emotion’s SSR helpers: Emotion often provides helper functions to assist with SSR. Refer to the documentation to utilize these functions to ensure correct hydration.
Note: The specifics of certain Emotion APIs might vary slightly depending on the version. Always refer to the official Emotion documentation for the most up-to-date and accurate information. This section provides a general overview.
css
propThe css
prop is a function that allows you to inject styles into a React component. It accepts a CSS object, a template literal, or a function that returns a CSS object or template literal.
Basic usage:
import { css } from '@emotion/react';
const myStyles = css`
color: blue;
font-size: 16px;
`;
<div css={myStyles}>Styled text</div>
Usage with dynamic values:
import { css } from '@emotion/react';
const MyComponent = ({ color }) => (
<div css={css`color: ${color};`}>Dynamically styled text</div>
; )
Advanced usage (with theme):
import { css, ThemeProvider } from '@emotion/react';
const theme = { colors: { primary: 'blue' } };
const MyComponent = () => (
<div css={theme => css`color: ${theme.colors.primary};`}>Themed text</div>
;
)
<ThemeProvider theme={theme}>
<MyComponent />
</ThemeProvider>
cache
The cache
object provides low-level access to Emotion’s internal styling cache. It’s primarily useful for advanced customization and integration with other tools. Direct manipulation of the cache is generally not necessary for most use cases. Consult the advanced section of the Emotion documentation for details on its usage.
injectGlobal
(Note: The use of injectGlobal
is generally discouraged in favor of the Global
component from @emotion/react
, which provides better type safety and maintainability). injectGlobal
was a function for injecting global styles into the document’s <head>
. The recommended modern approach is to use the Global
component as shown in the Advanced Techniques section.
keyframes
The keyframes
function allows you to define CSS keyframes for animations.
import { keyframes, css } from '@emotion/react';
const fadeIn = keyframes`
from { opacity: 0; }
to { opacity: 1; }
`;
<div css={css`animation: ${fadeIn} 1s ease;`}>Animated element</div>
ThemeProvider
The ThemeProvider
component provides a way to manage and inject a theme into your application. It uses React context to make the theme available to all components within its scope.
import { ThemeProvider } from '@emotion/react';
const theme = {
colors: {
primary: 'blue',
secondary: 'green',
,
};
}
<ThemeProvider theme={theme}>
/* Components using the theme */}
{</ThemeProvider>
withEmotionCache
The withEmotionCache
higher-order component (HOC) is used to inject Emotion’s styling cache into a component’s props. This is mostly useful for advanced scenarios, such as integrating with server-side rendering or specialized styling solutions and not usually needed in typical development. Refer to the Emotion documentation for specific examples and use cases.