Add a CSS variables API

Created on 23 June 2025, 12 days ago

Problem/Motivation

After SDC in Drupal 10.1 (July 2023), and the Icon API in Drupal 11.1 (Dec 2025), we are continuing to add design systems API in Core with Add a style utility API Active , in order to be able to build business agnostic, shareable, Drupal themes, providing design implementations which can be leveraged by display building tools.

There is a last design system API to cover the main parts of design systems: CSS variables.

Initially, we were targeting 2026, but an exciting discussion with XB's team in DrupalDevDays 2025 (they wanted a way of altering an utility while applying it) made us realise it will be beneficial to ship it alongside the Style API.

In Web implementations of design systems, CSS variables (sometimes referred as custom properties or cascading variables) are an (often small) subset of the design tokens which are overridable at runtime. So, the new value is applied by the browser and not by rebuilding the CSS. Design tokens which can be accessed through CSS variables are defined in the design system implementation (so, in the Drupal theme). Design tokens live at the page level, but they can be overridden with a CSS selector as a scope. CSS variables naming are solely for use by authors and users; CSS will never give them a meaning beyond what is presented here.

CSS variables are a commonly found in design systems. Examples:

Analysis of the current solutions in the contrib space

Like SDC, the Icon API and the upcoming Style API, we believe it must be front-dev friendly, UI logic focused, YAML plugin declaration available in Drupal theme. So, let's have a look on contrib modules are already covering this scope.

UI Skins (usage: 330)

https://www.drupal.org/project/ui_skins

Discovery: {provider}.ui_skins.css_variables.yml in modules and themes.

Example (Material 2 background color variables):

mdc_theme_background:
  label: "Default background color"
  category: Background colors
  type: color
  default_values:
    ":root": "#ffffff"

mdc_theme_surface:
  label: "Surface background color"
  category: Background colors
  type: color
  default_values:
    ":root": "#ffffff"

Personal opinion:

I am maintainer of this module and I participated to define this format, so I may be biased, but I believe this format is a great starting point. However, there is a few issues we can fix in this proposal:

CSS Variables (usage: 10)

https://www.drupal.org/project/cssvars

Not compatible with Drupal 11.

No definition format.

Personal opinion:

If my understanding is right, CSS Variables are not really integrated with Drupal. It is only a form with a textarea where people put free values which are attached to page renderable.

CSS color variables (usage: 4)

Works only for colors, but use CSS variables anyway.

Not a YAML plugin discovery but a PHP file to add in the theme, so not front-dev friendly enough: https://git.drupalcode.org/project/css_color_variables/-/blob/1.0.x/colo...

[
  // Available colors and color labels used in theme.
  'fields' => [
    'primary' => t('Primary'),
    'primary__contrast' => t('Primary contrast'),
    'secondary' => t('Socondary'),
    'secondary__contrast' => t('Socondary contrast'),
      ...
  ],
  // Pre_defined color schemes.
  'schemes' => [
    'default' => [
      'title' => t('deGov default'),
      'colors' => [
        'primary' => '#004673',
        'primary__contrast' => '#ffffff',
        'secondary' => '#818D97',
        'secondary__contrast' => '#ffffff',
      ],
    ],
]

Personal opinion:

Value are not scoped/scopable. Predefined schemes are interesting, but let's keep them out of this scope. We may discuss this in a future ticket.

Honorable mentions

Proposed resolution

Definition & discovery

Based on the analysis below, with some discussions.

For example, it seems it would be a mistake to rely only on automatic discovery from CSS files to get the list of CSS variables, because we will miss the metadata, and because not all CSS variables from a codebase must be exposed to tyhe Drupal CMS. For example, Bootstrap 5 did the mistake of converting all Sass variables (build-time tokens) to CSS variables (runtime tokens) and we need to cherry-pick them.

In the renderer service

There is two expected usage of those variables in the render API.

1. Local usage. Modules can leverage this API by overriding variables values in $build["#attributes"]["style"]. However, this is causing a few issues:

  • The syntax is verbose and error prone
  • Variables values are mixed with other inline styles
  • There is no possibility to add checks about the existence of a variable, or the correctness of the value.

So, it would be better to introduce #variables universal property, which can be added to every renderables already accepting an #attributes property:

  • ['#type' => 'html_tag']
  • ['#type' => 'component']
  • Most of #theme and most of render elements

This is excluding #markup, #plain_text and maybe some #theme and some render elements.

So the renderer service to process this by adding the variables/values pair to $build['#attributes']['style']

2. Global usage. Modules can leverage this API by overriding variables values at the page level, leveraging the scope, like UI Skins module is currently doing: https://git.drupalcode.org/project/ui_skins/-/blob/1.1.x/src/HookHandler...

What do we do? We extend #attached render property with a variables keyword? We extends our own #variables render property? We add an other universal render property?

Remaining tasks

Let's start by contacting the maintainer of the contrib modules to ask them if they want to participate.

User interface changes

No. API only.

Introduced terminology

"CSS variables", "custom properties", "runtime tokens", "cascading variables", "scope"

API changes

Only additions.

Data model changes

No.

Feature request
Status

Active

Version

11.0 🔥

Component

theme system

Created by

🇫🇷France pdureau Paris

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024