Theming, SSR & Choosing a Styling Approach
Theming
import { ThemeProvider } from '@emotion/react';
const theme = { colors: { primary: '#3b82f6' }, spacing: 8 };
<ThemeProvider theme={theme}>
<Button /> {/* any nested styled component can read theme via props.theme */}
</ThemeProvider>Global Styles
import { Global, css } from '@emotion/react';
<Global styles={css`body { margin: 0; font-family: sans-serif; }`} />A deliberate escape hatch from component-scoped styling — appropriate for CSS resets and base typography, the small set of genuinely app-wide concerns.
SSR
In server-rendered apps (Next.js), Emotion's CSS must be extracted and injected into the server-rendered HTML so styles are present before client JS runs — otherwise users briefly see a flash of unstyled content. Emotion ships specific SSR utilities for this.
High-Frequency Updates
For values changing very rapidly (continuous scroll/mouse position), regenerating CSS on every render adds overhead — direct inline style manipulation, bypassing Emotion's class-generation machinery, is usually the more performant choice there.
Emotion vs. Tailwind vs. Zero-Runtime CSS-in-JS
Emotion: expressive, dynamic, JS-driven styles, some runtime cost. Tailwind: build-time utility classes, zero runtime cost, denser markup. Newer zero-runtime CSS-in-JS (vanilla-extract, Linaria) tries to keep colocated styles while shifting generation to build time — an evolution addressing Emotion-style runtime overhead directly. Many UI libraries (MUI) use Emotion internally, so it often arrives as a transitive dependency regardless of a project's primary styling choice.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free