All posts
Jacob Rask
Jacob Rask

Volvo Cars Online Engineering

Our future CSS strategy


Or, CSS -in-js

As we build the next generation of the web implementation of our Design System Language, we're looking for any opportunities to improve the foundation of our web experiences, leveraging the learnings accrued over the years since VCC UI was introduced and used widely across our web development teams.

With that in mind, we've been analysing what works, what slows us down, and what might hinder us in the future as the web development space continues to advance. This analysis has shaped our strategic direction for how we see styles for the web might be written in the future and how to get there with as little disruption for the product teams as possible.

If we could sum up our aim in one word, it would be resilience. If we could sum up the direction in one acronym, it would be CSS.

Why back to CSS?

VCC UI and other Volvo Cars React components are currently styled using CSS-in-JS with Fela.

By utilising Fela and colocating the styles with the component we avoid including unused CSS on our pages; a component's styles will only be included on a page when it's needed and if a feature is removed from a product, its styles will be deleted with it. At the same time, component based styles with CSS-in-JS lack some of the expressiveness of CSS selectors and assumptions you can make when writing plain CSS. Further, every component needs to start from scratch, resetting styles in a way that works across all browsers.

CSS-in-JS inlined in <style> on the page also avoids the problem of render blocking CSS, but this comes at a cost; on every page navigation you need to fetch all CSS again.

Analysis of the generated styles that are injected into the page at runtime demonstrate;

  1. We have a lot of common or near common styles duplicated on the page
  2. There are a number of scenarios where Fela is unable to de-duplicate a common style, causing us to lose the atomicity benefit of Fela and increasing the amount of CSS we have to load on every page load.

While external CSS is render blocking, it has the advantage on a multi-page website like that once it has been loaded it is cachable by the user as they navigate between pages instead of adding to the weight of every page. By adding external CSS files to our toolbox, teams can balance the trade-offs between first page load speed and next page navigations as appropriate for their type of visitors.

An alternative direction

We envisage providing a set of Design System compliant stylesheets that provide base, Volvo Cars styled browser resets and utility classes that enable you to apply the most commonly used styles to any element without depending on any JavaScript runtime.

With new additions to CSS like :where and @layer we have been able to create CSS resets and defaults that are non-intrusive and won't override the CSS you write in an application. Instead of starting from a default stylesheet provided by different browsers you start from a default Volvo Cars stylesheet, reducing the amount of CSS you need to write for individual components.

Resilience and portability

Embracing the primitives provided by the web platforms ensures longevity and resilience. Even in case of major changes to the broader ecosystem like JavaScript frameworks, our CSS will continue to work, everywhere. Any web developer can pick it up, understand it, and – if needed – build new abstractions on top of it.

The recent changes in Next.js and React 18 are a good recent example, where CSS-in-JS libraries needed updates for async rendering and streaming responses. There is also the risk in having a dependency on a small external open source team for our styling solution.

Components on that are server-side rendered only, and micro-frontend components with their own build pipeline like the Site Navigation can be styled using the same CSS custom properties with the new CSS library. Fela requires a JavaScript runtime for theming, so these components can currently not react to theme changes from the page around them, such as switching to dark mode. Similarly, third-party integrations cannot reuse the JavaScript based design tokens, but instead require additional custom styles on every page.

There are also teams that for various reasons need to build something outside of React and VCC UI, but no officially supported patterns or escape hatches letting them drop down to the raw design tokens to build their own components in a different framework.

A layered user interface architecture

Our plan is to implement core components using a layered approach. The base layer is the CSS library, providing design tokens and CSS classes. On top of that there are abstractions that provide a better developer experience for the most common use cases in a framework like React.

As an example, the typical usage of a button would be

<VolvoCarsButton variant="primary">Shop</VolvoCarsButton>

If you have a special requirement not covered by the Button component, or if you are doing something outside of React, you can drop down to the CSS.

<button className="button-primary">
Shop <SomethingYouCantDoWithVolvoCarsButton />

The transition
For the forseeable future, moving away from Fela and CSS-in-JS will be opt-in. We will encourage teams to consider where they can utilise our CSS libraries, and be part of shaping those to ensure they cover different team's needs, but there'll be no overnight wholesale change.

In the meantime, if you need to continue using Fela for component level changes, but wish to also use our CSS utility classes, you can do so;

<Block as="h1" className="statement-3" extend={{ hyphens: 'auto' }}>
Are you ready to switch?

What about VCC UI?

VCC UI is the React implementation of the current truth of the Volvo Cars Design System and is still maintained. As we transition parts of the design system to @volvo-cars/css and other packages, VCC UI will gradually do less and other packages do more.

If you're running into any issues or have feedback

We are available in GitHub Discussions or in #design-system-web on Slack - feedback is always welcome!