feat(theming): Replace SASS-Based theming with global CSS variables #29363
Labels
area: theming
feature
This issue represents a new feature or feature request rather than a bug or bug fix
needs: discussion
Further discussion with the team is needed before proceeding
P3
An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Feature Description
Motivation
This feature request aims to simplify and consolidate CSS code instead of splitting it into multiple mixins. The current recommended way of theming components requires writing a dedicated file with at least three mixins:
theme
,color
, andtypography
(anddensity
?). While this approach follows a good philosophy of separating concerns, it has some significant drawbacks:1. Exponential Growth and Difficult Maintenance
In large projects with hundreds of components, having a separate theme for each component can become boilerplate-heavy and lead to tedious maintenance. For example, the material.angular.io app theme imports and uses all themes scattered across the app. Scaling this approach to a much larger project would be painful and error-prone. The component-attached stylesheet is no longer the single source of truth.
2. Excessive Boilerplate
Creating a new component requires writing a dedicated theme that we have to import and use in
styles.scss
. This adds unnecessary complexity to the development process.3. Lack of Component View Encapsulation
One of Angular's cool features is view encapsulation, which prevents style collisions. However, since themes need to be applied in the main
styles.scss
file, encapsulation cannot be used. This forces us to rely on verbose CSS class names (e.g.,app-my-component-header-title
), whereas a simplerheader-title
would suffice when wrapped in an encapsulated stylesheet.4. Dependence on SASS
To customize Angular Material, you have to use SASS, but some developers might prefer not to rely on it for various reasons. Additionally,
ng new
offers different stylesheet formats, which means forcing SASS can be limiting.Proposed Alternative
Inspired by the new Material 3
use-system-variables
capability, I propose using a set of CSS variables (e.g.,--sys-primary
,--sys-body-large
, etc.) available globally for Angular Material and custom components, instead of relying on SASS mixins. Of course, we could consider having a schematics to help developer to generate those variables just likeng generate @angular/material:m3-theme
does.@crisbeto listed those variables in this comment
Also, using css variables only instead of SASS theme simplify overrides and remove the need of Angular components mixins (like
mat.button-theme($my-theme)
).However, I can understand we still need to import core styles. This could be easily addressed by registering the right css file in
angular.json
file in buildstyles
option list.Problems to Consider
1. Conditional Logic Based on Theme Type (Dark or Light)
We have to find a css alernative to
get-theme-type($theme)
.color: if(mat.get-theme-type($theme) == dark, white, black);
Native CSS does not provide an
if
conditional operator, but the CSScontainer
property could be a viable alternative (cf. https://stackoverflow.com/a/76327443).2. Reading Palettes' Hues
Without SASS, palettes will not be available. However, this issue could be mitigated by adding more CSS variables (e.g.,
--sys-primary-80
,--sys-secondary-20
).To sumarize
This proposal aims to streamline the theming process in Angular Material by reducing boilerplate, enhancing maintainability, and leveraging modern CSS capabilities. It aligns with the broader trend of using CSS variables for theming and can simplify the theming experience for developers.
Thank you for considering this feature request. I believe it can significantly improve the development workflow and theming consistency in Angular Material projects.
Use Case
We could replace the following code :
by this lighter code in pure css :
The text was updated successfully, but these errors were encountered: