Loading
github css modules react performance
Web developmentBy SDX Development

Share this article

In its experience report published on September 25, 2026, GitHub says it completed a migration carried out over several years: since June 2026, the styling architecture concerned on github.com has relied entirely on CSS Modules, without styled-components, styled-system, or the sx prop.

Key takeaway

Real gains, but context-specific

GitHub reports a 55% reduction in server-rendering time in one measurement after migrating Primer, followed by gains of approximately 1% to 22% across different pages. These results describe its environment: they do not predict the benefits of a migration on another React application.

Why CSS-in-JS became costly for GitHub

CSS-in-JS addressed concrete needs in Primer, GitHub's design system. Styles remained close to components, design tokens were integrated into the API, and TypeScript made autocompletion easier. With sx, developers could customize a component from a JavaScript object.

According to GitHub, the difficulties became significant around 2023, as the number of components increased on some pages. In a runtime-executed CSS-in-JS solution, style processing accompanies application execution. Repeated across hundreds or thousands of components, this work can become significant.

01

Interpreting styles

Objects and their variations must be processed to determine the rules applicable to the component.

02

Managing classes

The library generates or retrieves the classes corresponding to the styles, depending on its operation and caching mechanisms.

03

Preparing server rendering

Collecting styles can add work to component rendering before the page is sent.

04

Initializing in the browser

Processing and injecting styles can contribute to the interface's initialization cost.

These mechanisms vary by library. Runtime-executed CSS-in-JS must therefore be distinguished from solutions that extract styles at build time: they do not necessarily have the same costs.

CSS Modules: keeping components, moving the work

CSS Modules makes it possible to associate a stylesheet with a component while making class names local to the module by default. The component imports a class-name mapping; the tooling transforms these names to avoid collisions.

GitHub thus retains a component-oriented organization while producing stylesheets without relying on the same JavaScript processing of styles at render time.

Runtime CSS-in-JS

A dynamic API close to the component

Style logic can directly use the component's properties. This convenience must be weighed against the processing cost measured in the application.

CSS Modules

Local CSS prepared at build time

CSS files remain explicitly linked to components. Variants can rely on classes, attributes, and CSS variables.

Dynamic styles do not disappear

Switching to CSS Modules does not prohibit themes or appearance changes. CSS variables can, in particular, vary colors or spacing without rebuilding all the rules in JavaScript. However, behaviors previously provided by the library must be identified and explicitly reimplemented.

What gains did GitHub measure?

The measurements cover several stages and several scopes. They must neither be added together nor interpreted as an equivalent overall acceleration of github.com.

Reported scope Metric Result
After migrating the relevant Primer components Server-rendering time for a page −55%
After migrating Primer Component initialization time −25%
Migration extended to different github.com pages Server-rendering time depending on the page Approximately −1% to −22%
Internal Primer benchmark with 1,000 components Runtime CSS injection compared with static CSS files 242 ms versus 96 ms

The spread of the results is instructive. The number of components, style variations, and weight of other processing differ from one page to another. A significant reduction in a heavily loaded case does not guarantee the same result on a simpler interface.

Point of attention

Faster server rendering is not an SEO promise

Reducing server or JavaScript work can improve the user experience. However, it does not guarantee any automatic improvement in LCP, INP, or search rankings: images, API calls, third-party scripts, caching, and business logic may remain the main bottlenecks.

A gradual migration rather than a rewrite

GitHub started with Primer. For each component, an implementation using CSS Modules was placed behind a feature flag, compared with the old one through visual regression tests, and then deployed gradually. This first phase was completed in December 2024 for the relevant components.

Maintaining compatibility with the existing code

github.com's code still contained approximately 7,760 sx props in April 2025. GitHub used an intermediate layer, @primer/styled-react, so that these usages would continue to work during the transition. A team of eight engineers then converted 6,419 sx props in six months.

This temporary coexistence avoided imposing a single switch on the entire codebase. It made it possible to move forward package by package, with a more manageable validation scope.

Automating known transformations

GitHub developed a Visual Studio Code extension and a codemod to facilitate conversions. When the final phase resumed in April 2026, 895 occurrences of sx remained. GitHub reports removing them in three weeks with two engineers and several GitHub Copilot agents.

This result concerns a transformation that was already defined and tooled. Automation speeds up repetitive changes; it does not eliminate the need to check dynamic styles, responsive behavior, accessibility, and regressions.

Decoupling the theme system

The final obstacle was not limited to sx props. Part of the theming still depended on styled-components. GitHub had to decouple this logic and rely more heavily on Primer's CSS variables, particularly for its different themes and high-contrast variants.

This is an important point for SaaS applications: moving CSS declarations is not enough if the library also provides themes, tokens, or inherited behaviors.

Should you abandon styled-components on a React application?

No, not solely based on GitHub's experience report. A productive and sufficiently performant architecture does not need to be replaced because another company faces different constraints.

Keep the existing solution

Styling is not a measured bottleneck

If performance meets requirements, style dynamism is useful, and the migration would deliver few benefits, keeping CSS-in-JS may be the most reasonable choice.

Test an alternative

Runtime represents a significant cost

Very heavily loaded pages, costly SSR, or a majority of static styles may justify a CSS Modules prototype to compare equivalent implementations.

For a new project, start with the constraints

CSS Modules is a relevant option for using standard CSS with local scope and limiting the runtime dedicated to styles. It is not the only path: structured CSS, utility classes, or build-time generation may also meet the need. The design system, team skills, and customization requirements remain decisive.

How to evaluate a migration without misjudging priorities

Before changing the architecture, establish a baseline on representative pages, including a particularly heavily loaded interface. The protocol must retain the same components, content, behavior, and test conditions.

Six steps before a widespread migration

  1. Profile the existing solution. Isolate the cost of styling from API calls, the database, and business logic.
  2. Choose a pilot. Test a sufficiently widely used component family to produce useful measurements.
  3. Compare equivalent functionality. Preserve variants, themes, and interactive states.
  4. Secure the rollout. Use feature flags, visual tests, and a rollback option.
  5. Automate with review. Entrust repetitive transformations to tools and examine complex cases.
  6. Decide based on results. Extend the migration only if the gains justify its cost and risks.

Measure the server and the browser

For an SSR application, track rendering time, CPU per request, and memory. Complement these with TTFB, transferred JavaScript and CSS volumes, hydration, and LCP and INP measurements from real users. These indicators describe different dimensions: an improvement in one does not guarantee an improvement in the others.

Include maintenance costs

An architecture decision cannot be reduced to a benchmark. Migration time, design-system compatibility, test coverage, and ease of contribution must be included in the evaluation.

The main lesson: keep an evolvable architecture

GitHub's experience report shows that a solution that is convenient at the beginning of a project can become less suitable at another scale. It also shows that a deep change can be carried out gradually, without rewriting the entire application.

Measure, test on a limited scope, preserve compatibility, and validate the results: this approach is more useful to reproduce than the choice of a library. CSS Modules can reduce an identified cost; it does not replace diagnosis.

Sources and documentation scope Show references

References indicated in the editorial brief. The figures are attributed to GitHub's experience report; the documents were not independently verified for this article.

  • GitHub Engineering — Improving site performance by shipping more CSS, publication indicated as September 25, 2026.
  • Primer React — Styling with CSS Architecture Decision Record, for architecture choices and internal benchmarks.
  • Official CSS Modules documentation, for the operation of local classes.
  • Primer React v37 and v38 — documentation of the transition to CSS Modules.
  • styled-components — documentation on server rendering and React Server Components.

Web development

Prepare your web application for its next update.

PHP migration, CMS updates or framework upgrades: identify compatibility issues and test essential user journeys before going live.

  • Dependency compatibility checked
  • Essential user journeys tested in staging
  • Deployment with a rollback plan