Your React app might be 40% slower on first render than it needs to be. Not because you wrote bad code. Not because React is slow. But because styled-components never implemented React 18's useInsertionEffect hook: a feature specifically designed to solve CSS-in-JS performance problems. While React 18 shipped in March 2022 with this optimization path, styled-components remained on React 17 patterns, injecting styles during render instead of between render and layout. This creates a performance-killing cycle: styles get injected, layout recalculates, more styles inject, more recalculations. Exactly what useInsertionEffect was designed to prevent. "For new projects, I would not recommend adopting styled-components," wrote Evan Jacobs, its maintainer for the last couple of years. Clear. Direct. Honest. But what about the millions of existing components already in production? When Evan announced maintenance mode on March 17, 2025, he was refreshingly transparent: styled-components won't work in React Server Components without 'use client' directives. The ecosystem has moved on. He no longer runs styled-components in production. The React team themselves have made it clear: runtime CSS injection will always be slower than statically extracted styles. They recommend using for static styles and inline styles for dynamic values. That's the future. Respect. Maintaining a library with 34,000 stars for free is exhausting. We've been sponsoring styled-components for years. We know the burden. Evan's honesty gave everyone clarity to make decisions. But here's what that announcement didn't address: thousands of production apps with hundreds of thousands of styled components that can't just disappear. Teams at Linear, Sanity, and countless others. We all woke up to the same problem. Our codebases using styled-components don't care that Tailwind is trending (no lack of trying to make them!). They need to ship features today. Our decision? Pick up where the community left off, at least temporarily. At Sanity, we had a problem. Sanity Studio runs on styled-components. So does our UI library. Thousands of components, all dependent on a library whose own maintainer says not to use. We had three choices: Rewrite everything (months of work, we're actually doing this) Accept degrading performance (not happening) Fix it ourselves Actually, we chose option zero first: contribute the fix upstream. In July 2024, we opened PR #4332 with the useInsertionEffect implementation. But with one maintainer juggling 34,000 stars worth of expectations, for free, our PR joined the queue. No blame. Open source maintenance is brutal. So when maintenance mode arrived, we did what we had to: turned our PR into a fork and opened it up for anyone else stuck in the same boat. We didn't just optimize blindly. We benchmarked against every CSS-in-JS library out there. Emotion, Stitches, Goober, restyle. Styled-components, even in its unmaintained state, is still the most performant by a long shot. Our optimizations made the fastest library even faster. Here's what styled-components never implemented: React 18's useInsertionEffect . This API was literally designed for CSS-in-JS libraries. // Before: styled-components injects styles during render (!) function StyledComponent () { // This happens during render, blocking everything, might cause relayout const className = componentStyle . generateAndInjectStyles (); return < div className = { className } />; } // After: using the hook React built for CSS-in-JS function StyledComponent () { // Buffers styles and generates a className, not blocking const className = componentStyle . generateStyles () useInsertionEffect (() => { // Insert styles before useLayoutEffect, no risk of relayout componentStyle . injectStyles (); }); return < div className = { className } />; } This single change is huge. Moving it to useInsertionEffect changes everything. React can now optimize when styles get injected: after render, before layout. Exactly when they should be. But that's just where we started. We replaced userland array operations with native Array.prototype.flatMap . Swapped useRef initialization patterns with useState for better memory usage. Eliminated unnecessary effect cycles. Even optimized the hash function with Math.imul for faster style generation. Small changes? Sure. But flatten and phash run on every single render of every styled component. In an app with thousands of components, milliseconds become seconds. Seconds over time becomes minutes. Multiplied by users, you have hours. And so on. We also modernized the build output from ES5 to modern JavaScript. Native spread syntax. Native classes. The JavaScript engines in your users' browsers are incredibly optimized for modern syntax. Why ship transpiled code that runs slower? When Linear tested our fork on their app, they saw up to 40% faster initial component rendering . No code changes. No migration. Just: # React 18 pnpm add --save-exact styled-components@npm:@sanity/styled-components # React 19 pnpm add --save-exact styled-components@npm:@sanity/css-in-js Kenneth from Linear messaged us: Linear now renders first page visits up to 40% faster thanks to your hard work! Thank you so much. Been a pleasure with such a quick turnaround. Then added: "A lot of companies would benefit from the fork." He's right! Streaming SSR in styled-components? Broken since React 18. We had to fix it for the . React 19 gave us the solution: native support for inline CSS stylesheets that get hoisted correctly into during streaming. We adopted the technique restyle.dev pioneered. The result was beautiful. ServerStyleSheet ? Gone. Completely eliminated. Our second fork rebuilds for this new world: // The old way (broken in React 19) import { renderToNodeStream } from ' react-dom/server ' ; import { ServerStyleSheet } from ' styled-components ' ; res . write ( ' Test ' ); const sheet = new ServerStyleSheet (); const jsx = sheet . collectStyles (< App />); const stream = sheet . interleaveWithNodeStream ( renderToNodeStream ( jsx )); stream . pipe ( res , { end : false }); stream . on ( ' end ' , () => res . end ( ' ' )); // Our fork (just works) import { renderToReadableStream } from ' react-dom/server ' ; async function handler ( request ) { // Look ma, no needed! const stream = await renderToReadableStream ( < App /> , { bootstrapScripts : [ ' /main.js ' ] }); return new Response ( stream , { headers : { ' content-type ' : ' text/html ' }, }); } But here's where it gets really good. Next.js App Router with regular styled-components? You need a whole setup: StyledComponentsRegistry wrapper component wrapper component useServerInsertedHTML hook hook ServerStyleSheet instance instance StyleSheetManager provider With our fork? Just add the compiler to next.config.ts . That's it. No registry. No style collectors. No providers. React 19 handles the complexity, so you don't have to: // next.config.ts import type { NextConfig } from ' next ' const config : NextConfig = { compiler : { styledComponents : { transpileTemplateLiterals : false }} } export default config Solving the hard problem of streaming SSR had a beautiful side effect: ServerStyleSheet became completely unnecessary. In any situation. Our React 19 fork (@sanity/css-in-js) was originally built to solve streaming SSR. It also ended up faster than our React 18 fork. React Compiler optimizations. Conditional use(context) that prevents unnecessary re-renders when themes change. The new JSX runtime with refs as props. All these React 19 features compound into better performance than even our optimized React 18 version. We built it to fix streaming SSR. The performance upgrade came from embracing React 19's architecture. We named the repository styled-components-last-resort . That's exactly what this is. We're not the new maintainers. We're not adding features. We're actively migrating away from styled-components ourselves. To vanilla-extract, if you're curious (yes, we use Tailwind in other projects too). But migration takes time. Linear can't pause product development to rewrite styles. Neither can you. These forks do two things: dramatically improve your performance today (faster renders, twice as fast to reach animations, more stable frame rates) and buy you time to migrate properly tomorrow. Real performance gains while you plan your real migration. Most performance advice assumes greenfield projects. Real codebases have: Thousands of components using styled-components Complex theming systems built on its APIs Dynamic styles that can't be statically extracted Teams who need to ship features, not rewrites Our forks accept this reality. Install, get the performance boost, keep shipping while you plan your real migration. After the maintenance mode announcement, developers started flooding GitHub issues. Some proposed maintaining a community fork. Others shared hacky workarounds. Many just accepted their fate. We're open-sourcing our solution because we've all benefited from styled-components for years. Evan and the contributors gave us a tool that powered millions of components. The least we can do is help others transition gracefully. You'll find our README blunt about our intentions: ⚠️ Not actively maintained long-term ✅ Security fixes only ❌ No new features 🤝 Looking for a real maintainer If someone wants to properly maintain styled-components for the community, we'll hand over the keys. We're not trying to own this. We're just holding the door open while everyone finds their exit. Teams can migrate on their own timeline. No emergency rewrites. No performance firefighting. Just steady progress toward modern styling solutions while shipping features every day. If you're stuck with styled-components: Stage 1: Immediate relief (Today) # React 18 pnpm add --save-exact styled-components@npm:@sanity/styled-components # React 19 pnpm add --save-exact styled-components@npm:@sanity/css-in-js Stage 2: Stop the bleeding (This sprint) Freeze new styled-components usage Start new components with your target solution Document your migration strategy Stage 3: Actual recovery (This quarter) Pick your replacement: vanilla-extract, Tailwind, Panda CSS Migrate systematically, component by component Delete styled-components forever Both forks are available now at github.com/sanity-io/styled-components-last-resort You can use our configured styled-components benchmarking tool to test different libraries (styled-components, emotion, styled-jsx, etc), benchmarks (mount wide/deep tree, dynamic styles), and runners (concurrent, synchronous). You can also check out our the benchmarking tool we built to assess performance more deeply (tip: put on some deep techno when watching this): This video (before, after) shows the diff when running two chrome (v128) windows in split screen on a M1 Pro at a 3456x2234 resolution, connected to a charger so there's no CPU throttling, macOS 14.5. Your app has styled-components. That's not changing today. But it doesn't have to be slow while you figure out tomorrow. Sometimes open source isn't about building the future. Sometimes it's about helping each other manage the present. Evan gave us years of styled-components. This is us passing it forward. At Sanity, we build the Content Operating System that powers content at scale. We've been supporting open source because we depend on it. Sometimes that means sponsoring maintainers. Sometimes it means fixing the infrastructure ourselves.