Boosting Web Performance Through Efficient CSS Distribution

The Primer design system, which powers many user interface elements, faced performance challenges in 2023 due to a growing number of components and its existing CSS-in-JS solution. This led to extended initial page load times, reduced server-side rendering performance, and difficulties in managing styles.

Boosting Web Performance Through Efficient CSS Distribution

Core components, from buttons to banners, are crucial for the user experience and must be accessible, flexible, and performant across various scenarios. However, with the increasing number of components on some pages, performance issues emerged, linked to the then-used CSS-in-JS solution.

These problems included longer page load times due to client-side style initialization, a drop in server-side rendering (SSR) performance as style collection moved from client to server, and difficult management of style updates with a growing number of components. It became clear that an alternative was needed to eliminate these overheads on both client and server, without compromising system stability during migration.

CSS Modules emerged as a solution. This format allowed developers to leverage native CSS features while retaining the benefits of colocation and encapsulation they were accustomed to from CSS-in-JS. Styles are now written in a separate CSS file alongside the component's JavaScript code. A key feature is that all class names are local by default, preventing collisions with global selectors. Furthermore, CSS Modules eliminate the need for any runtime behavior on the client or server, as styles are directly included in CSS templates sent as part of the HTML page.

However, the transition to CSS Modules represented a radical change from the previous solution. It required updating every component in the Primer design system, as well as all components utilizing this technique across the system. Fortunately, design systems provide an ideal platform for managing such extensive changes.

An incremental migration strategy was chosen for implementing this change. For each component, a new file was created, translating existing styles into CSS Modules. Subsequently, the component was placed behind a feature flag, allowing switching between old and new styles. Visual regression tests were used to verify the identical appearance between both solutions. The feature flag was then progressively rolled out – first to the internal team, then to employees, and finally to all users, to catch any potential issues in the early stages.

This process ensured strong feedback and enabled early problem detection. The use of feature flags guaranteed a safe migration while also providing clear signals about the performance benefits of CSS Modules. By December 2024, all components in Primer had been migrated to CSS Modules. The result was an overall performance improvement, specifically a 55% reduction in page server-side rendering time and a 25% reduction in component initialization time.

With the clear migration results in Primer, the question arose whether similar benefits could be achieved in other parts of the system. The next step was therefore the gradual removal of the CSS-in-JS solution from the entire product. One of the most challenging parts was removing the `sx` property, which served for dynamic styling and component customization. Although it provided excellent TypeScript support and colocation with the component, its dynamic nature led to high runtime costs and poor scalability with a larger number of components on a page.

Dominik Medal

Got an idea for a website or app?

Let's talk it through — non-binding, with no pressure, and a concrete next step.

The first step towards abandoning CSS-in-JS was reducing the use of `sx` across the entire codebase. This led to an immediate performance improvement, similar to the Primer component migration. To facilitate the transition and maintain backward compatibility, an interim library was created that allowed `sx` to continue being used with newly migrated components. This enabled a gradual transition while simultaneously realizing performance gains for those parts of the code that had already switched to direct imports.

The next phase of migration proceeded package by package: all uses of `sx` were converted to equivalent CSS Module files, imports from the old library were replaced with imports from the new one, followed by thorough testing and deployment. The announcement of `styled-components` transitioning into maintenance mode confirmed that the chosen direction was correct.

Work, initiated in April 2025, involved migrating approximately 7,760 `sx` instances and lasted until May 2026. Internal tools were developed to automate the process, including a VS Code extension and codemods for migrating entire files. A team of eight engineers migrated 6,419 properties over six months, observing server-side rendering performance improvements ranging from 1% to 22% on some pages. In April 2026, when work intensified again, the remaining 895 `sx` props were successfully reduced to zero within three weeks, thanks to the dedication of a two-engineer team and effective use of internal automation tools.

The final challenge was decoupling theming from `styled-components`. The system supported seven different themes, each with a high-contrast variant, and all were dependent on `styled-components`. The theme itself was defined in CSS, but the dependency lay in JavaScript utilities. Once again, a gradual migration approach with feature flags was used. Dependencies were successfully removed within two months.

By June 2026, the system had fully transitioned to CSS Modules. The implemented safeguards enabled safe deployment of significant architectural changes, testing in a production environment, and efficient bug detection and fixes. All of this led to the successful achievement of goals and the realization of substantial performance gains. What was initially conceived as a CSS migration ultimately became a gradual refactoring of how the system handles styling, theming, and delivering user interfaces at scale. `sx`, `styled-components`, and `styled-system` were removed from the codebase without disrupting system stability, significantly improving performance and user experience.

Dominik Medal

Let's talk about your project

Tell me what you need and together we will work out the best way forward.

Stop scrolling, call me

+420 735 505 585