CSS-in-JS for React. You write real CSS inside tagged template literals to create styled React components — and because it's JavaScript, your styles can react to props, state and themes.
This is a real React app running styled-components. The <Button> is one styled component whose CSS branches on its $variant and $size props. Change the controls and the generated styles update instantly.
const Button = styled.button`
background: ${p => p.$variant === 'danger' ? '#ef4444' : '#6d5efc'};
padding: ${p => p.$size === 'lg' ? '12px 22px' : '8px 16px'};
color: white; border: none; border-radius: 10px;
&:hover { filter: brightness(1.08); }
`;
styled-components and Emotion share a theming model: wrap your tree in a <ThemeProvider> and every styled component can read props.theme. Flip the switch to swap the whole card's palette from a single theme object.
<ThemeProvider theme={dark ? darkTheme : lightTheme}>
<Card>...</Card> {/* Card reads props.theme.bg, .fg */}
</ThemeProvider>
Because styles are computed in render, component state drives them directly. This toggle's track and knob colours are derived from React state passed as a prop to a styled component — no class juggling.
const Track = styled.div`
background: ${p => p.$on ? '#22c55e' : '#cbd5e1'};
`;
const Knob = styled.div`
transform: translateX(${p => p.$on ? '22px' : '0'});
`;
Emotion offers the same styled API plus a css prop, and is popular for being lightweight and framework-agnostic. The mental model is identical: real CSS, scoped automatically, reactive to props. Swapping one library for the other is often a near drop-in change.
// Emotion looks almost the same:
import styled from '@emotion/styled';
const Tag = styled.span`
background: ${p => p.color};
padding: 4px 10px; border-radius: 99px;
`;
// or the css prop:
<div css={{ padding: 16, borderRadius: 12 }} />