- Issue created by @pdureau
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:
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.
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:
type
property is using the Drupal From API instead of a front-dev friendly format like JSON Schema, W3C's Design Tokens format, or CSS value types.- default values are set manually, scope by scope, so any change in the CSS file need to be ported to the YAML file. We may need to use a library like sabberworm/php-css-parser for automatic discovery instead.
- underscores in variable names are automatically replaced by dashes, however underscores are allowed in variable names: https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident
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.
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.
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.
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:
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']
#theme
and most of render elementsThis 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?
Let's start by contacting the maintainer of the contrib modules to ask them if they want to participate.
No. API only.
"CSS variables", "custom properties", "runtime tokens", "cascading variables", "scope"
Only additions.
No.
Active
11.0 🔥
theme system