Emotion - Documentation

What is Emotion?

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.

Why use Emotion?

Setting up Emotion

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.

Basic Usage

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.

Core Concepts

Styled Components

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.

CSS-in-JS

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.

The css prop

The 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

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.

Theme

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};`}>
    Styled with theme
  </div>
);


<ThemeProvider theme={theme}>
  <MyComponent />
</ThemeProvider>

Media Queries

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%;
  }
`;

Pseudo-selectors

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;
  }
`;

Keyframes

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.

Advanced Techniques

Composition

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.

Inheritance

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>

Utilities

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;
`;

Global Styles

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} />

Server-Side Rendering (SSR)

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.

Styling React Components

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.

Advanced theming

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.

Customizing the styling process

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.

Integration and Best Practices

Integrating with other libraries

Emotion generally integrates well with other popular React libraries. However, some considerations may apply depending on the library:

Testing and debugging

Testing and debugging Emotion styles is similar to testing and debugging regular React components.

Performance optimization

Emotion is designed to be performant, but there are strategies to further optimize your application:

Accessibility

Always consider accessibility when writing your styles. Ensure your styles adhere to WCAG guidelines and provide sufficient contrast, proper focus states, and semantic HTML.

Code splitting

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>
       {showComponent && <MyComponent />}
    </>
  );
};

This approach loads the styled component only when the user interacts with the component. This can significantly improve initial load times for large applications.

Migration and Troubleshooting

Migrating from other styling solutions

Migrating from other styling solutions to Emotion requires a careful approach, depending on the source.

Regardless of the source, thorough testing is crucial after migration to ensure all styles are working correctly.

Common issues and solutions

Debugging tips

Troubleshooting SSR issues

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.

API Reference

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 prop

The 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.