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.
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.
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
- BEM Methodology: Block Element Modifier
- CSS Modules: Scoped Class Names
- CSS-in-JS: Styled-components and Emotion
- Tailwind CSS Utility-First Approach