Frontend Academy · Lesson

CSS-in-JS: Styled-components and Emotion

Write component styles as tagged template literals with styled-components or the css prop with Emotion, and use props for dynamic styles.

Lesson 3 of 413 steps

CSS-in-JS: Styled-components and Emotion is a free Frontend Academy lesson on CoddyKit. This is lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, and your progress syncs across the web and the CoddyKit app. The Frontend Academy course includes 4 lessons in total.

What Is CSS-in-JS?

CSS-in-JS writes component styles directly in JavaScript/TypeScript. Styles are co-located with components, support dynamic values from props, and are automatically scoped. The two most popular libraries are styled-components and Emotion.

Styled-components Basics

Use tagged template literals to define styled components. The result is a React component that renders an HTML element with the styles applied.

import styled from 'styled-components';

const Button = styled.button`
  background: ${props => props.primary ? '#6366f1' : 'white'};
  color: ${props => props.primary ? 'white' : '#6366f1'};
  padding: 8px 16px;
  border: 2px solid #6366f1;
  border-radius: 4px;
  cursor: pointer;

  &:hover {
    opacity: 0.9;
  }
`;

<Button primary>Primary</Button>
<Button>Outline</Button>

Emotion — css Prop

Emotion's css prop applies styles to any JSX element. Requires the @emotion/react pragma or the Babel preset.

/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react';

function Card({ featured }: { featured?: boolean }) {
  return (
    <div css={css`
      padding: 16px;
      border-radius: 8px;
      border: ${featured ? '2px solid #6366f1' : '1px solid #e2e8f0'};
    `}>
      Content
    </div>
  );
}

Dynamic Styles from Props

Both libraries can read props to compute styles. This is their primary advantage over static CSS — no class-switching needed.

Theming with ThemeProvider

Styled-components and Emotion both support a ThemeProvider that injects theme values into all styled components.

import { ThemeProvider } from 'styled-components';

const theme = { colors: { primary: '#6366f1', bg: '#f7fafc' }, space: { sm: 8, md: 16 } };

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

// Access in styled component:
const Card = styled.div`
  background: ${props => props.theme.colors.bg};
  padding: ${props => props.theme.space.md}px;
`;

Extending Styled Components

Extend an existing styled component to create a variant without duplicating styles.

const Button = styled.button`
  padding: 8px 16px;
  border-radius: 4px;
`;

const DangerButton = styled(Button)`
  background: #e53e3e;
  color: white;
`;

Global Styles

Use createGlobalStyle (styled-components) or Global (Emotion) for global CSS like body styles and resets.

import { createGlobalStyle } from 'styled-components';

const GlobalStyle = createGlobalStyle`
  *, *::before, *::after { box-sizing: border-box; }
  body { margin: 0; font-family: system-ui; }
`;

<><GlobalStyle /><App /></>

Runtime Cost of CSS-in-JS

CSS-in-JS libraries inject styles at runtime via JavaScript. This adds CPU cost for parsing and style injection, plus JavaScript bundle size. Zero-runtime alternatives (vanilla-extract, linaria) generate static CSS at build time.

Zero-Runtime Alternatives

vanilla-extract: write styles in TypeScript, compiled to static CSS. linaria: CSS-in-JS syntax compiled to CSS Modules. Both give CSS-in-JS ergonomics without runtime overhead.

TypeScript with styled-components

Define a ThemeType and extend the DefaultTheme interface from styled-components for fully typed themes.

import 'styled-components';
import { theme } from './theme';

declare module 'styled-components' {
  export interface DefaultTheme extends typeof theme {}
}

When to Choose CSS-in-JS

CSS-in-JS is excellent for: dynamic styles driven by runtime JavaScript values, design systems with strong theming needs, teams that prefer JS-first workflows. The runtime cost is usually acceptable for non-performance-critical UIs.

Quick Check

What is the main trade-off of runtime CSS-in-JS libraries compared to static CSS solutions?

Recap: CSS-in-JS

Styled-components: tagged template literals, render a styled React element. Emotion: css prop or styled API. Dynamic styles from props eliminate class-switching. ThemeProvider injects theme values. createGlobalStyle for global CSS. Runtime cost is the main trade-off. Zero-runtime alternatives: vanilla-extract, linaria.

Free to start

Learn HTML with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
41
Lessons
163

Frequently Asked Questions

Is the “CSS-in-JS: Styled-components and Emotion” lesson free?

Yes — the full text of “CSS-in-JS: Styled-components and Emotion” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Frontend Academy course, upgrade to CoddyKit PRO. The Frontend Academy course includes 4 lessons in total.

What will I learn in “CSS-in-JS: Styled-components and Emotion”?

Write component styles as tagged template literals with styled-components or the css prop with Emotion, and use props for dynamic styles. You practise Frontend Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Frontend Academy?

No prior experience is required. Frontend Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 3 of 4.

How long does the “CSS-in-JS: Styled-components and Emotion” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Frontend Academy lesson?

Yes. Every Frontend Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. BEM Methodology: Block Element Modifier
  2. CSS Modules: Scoped Class Names
  3. CSS-in-JS: Styled-components and Emotion
  4. Tailwind CSS Utility-First Approach
← Back to Frontend Academy