Write styled-components syntax, get build-time CSS extraction and full RSC compatibility. Use build-time CSS-in-JS without the hassle.

Yak hero
Button.tsx
import { styled, css } from "@yak/react";

const Button = styled.button<{ $primary?: boolean }>`
  font-size: 1.5em;
  color: palevioletred;

  &:hover {
    color: red;
  }

  ${({ $primary }) =>
    $primary &&
    css`
      background: blue;
      color: white;
    `}
  `;
npm i@yak/react

Fastest CSS-in-JS solution

We built a comprehensive benchmark suite across the CSS-in-JS field. Yak pairs unmatched render performance with the most flexible API. It is always faster than runtime solutions like styled-components or emotion.

See all 22 styling techniques (opens in a new tab)
SSR performancerequests / second · higher is better ↑
yak10.0.0
196
StyleX0.19.0
159
tailwind-merge3.7.0
100
styled-components6.5.3
75
Panda2.0.0-beta.17
73
Emotion11.14.1
57

Familiar on the surface.
Real CSS underneath.

Button.tsx
import { styled, css } from "@yak/react";
import { Icon } from "./Icon";

const Button = styled.button<{
  $primary?: boolean;
}>`
  font-size: 1.5em;
  color: palevioletred;

  &:hover {
    color: red;
  }

  ${Icon}:hover & {
    color: blue;
  }

  ${({ $primary }) =>
    $primary &&
    css`
      background: blue;
      color: white;
    `}
`;

Framework-agnostic

Swap the import for Solid. Props stay idiomatic.

import { styled } from "@yak/react";
import { styled } from "@yak/solid";

Type-safe props

A bad prop is a compile error, not a runtime surprise.

const Button = styled.button<{
  $primary?: boolean;
}>`

Real CSS

Nesting and pseudo-selectors, not a subset.

&:hover {
  color: red;
}

Target other components

Reference another styled component directly.

${Icon}:hover & {
  color: blue;
}

Prop interpolation

Props flow straight into your styles.

${({ $primary }) =>
  $primary &&
  css`
    background: blue;
    color: white;
  `}

The css helper

Compose conditional style blocks.

css`
  background: blue;
  color: white;
`}

Tagged templates in. Real CSS out.

A Rust SWC plugin rewrites your styled components at compile time, inside whichever bundler you use. Static styles become a class; dynamic values ride on inline CSS variables.

your bundler
1

Write

Author components with the styled API you already know, and add yak to your bundler config.

Button.tsx
const Button = styled.button`
  font-size: 1.5em;
  color: palevioletred;
  &:hover { color: red; }
`;
next.config.ts
import { withYak } from "@yak/react/withYak";

export default withYak({
  // your Next.js config
});
2

Compile

The Rust SWC plugin runs inside your bundler, moves the static styles into a CSS file and leaves a class reference behind.

Button.js
import "./Button.css";
const Button = styled.button`
  font-size: 1.5em;
  color: palevioletred;
  &:hover { color: red; }
`;
const Button = styled.button("button_x7a");
Button.css
.button_x7a {
  font-size: 1.5em;
  color: palevioletred;
}
.button_x7a:hover { color: red; }
3

Ship

The browser gets a plain stylesheet and a component that carries a class name. No styling runtime.