Theming¶
Element provides a default element
theme with light
and dark
theme types as well as supports the definition of custom themes. A custom theme can support either light
, dark
, or both theme types.
How it works¶
Element uses CSS variables to implement theming, as they can be changed at runtime in the browser without page reload. The semantic color tokens in the design system are set to CSS variables instead of direct color codes, e.g. $element-ui-0: var(--element-ui-0);
and are changed at runtime by either applying the .app--dark
CSS class or by changing the value using the service SiThemeService
.
The SCSS variables are also set or overwritten to use those semantic tokens including the base font. Besides that, assets like the brand logo can also be overwritten using CSS variables.
Dark mode¶
Element supports a light
and dark
theme mode, which applies to the theme itself as well as all components. A user can choose either light
or dark
mode, while the default is being derived from the browser or operating system configuration.
Applying dark mode¶
Switching dark mode is done by adding the class app--dark
to the <html>
tag. This will then switch the CSS variables to the value for the dark theme.
This process is automated using the SiThemeService
service. Inject the service in your component and use applyThemeType('dark' | 'light' | 'auto')
:
Note: It is recommended to call
themeService.applyThemeType('auto')
during initialization of the app (e.g. withinapp.component.ts
) as this derives the theme choice from the user's browser or operating system configuration, allowing a coherent experience across different apps.
Preparing application for dark mode support¶
The dark theme works out of the box, if you use the semantic tokens and follow these few steps:
In the application's SCSS, make sure to use the semantic tokens everywhere, i.e. use
$element-ui-4
for border colors instead of$element-gray-200
.In some cases using the
$element-ui-*
tokens will fails, e.g. for things likebackground-color: rgba($element-ui-4, 0.5)
.
Custom themes¶
The SiThemeService is responsible for all theming topics.
- At startup, it tries to load a custom active theme from the SiThemeStore.
- If available, it applies the custom theme. Otherwise, the default Element theme is used.
The SiDefaultThemeStore
is a localStorage based implementation of the SiThemeStore
, which is used by default. To provide custom themes using other means than a localStorage like e.g. a backend service, you can implement your own SiThemeStore
and load a Theme
custom theme object.
You need to provide your implementation in the main app module:
{ provide: SiThemeStore, useClass: YourThemeStoreImpl }
Theme editor¶
For testing and creating custom themes we provide a theme editor.
Note: Do not use the theme editor in your products yet, as we still expect many changes.
Build time custom theme¶
It's also possible to use custom themes at build time. This option is mostly for OEM theming. To use a theme at build time, first set up a SCSS file with the theme definitions. These are a SCSS map. For the required keys, please see the the Siemens Brand definitions.
For example, create _theme-oem.scss
with this:
$theme-oem: (
// definitions, see above
);
Then, to include this theme and build it as the default, change the main style sheets:
// first configure the element-theme by not building the 'siemens-brand' theme
@use '@siemens/element-theme/src/theme' with (
$element-theme-default: 'oem', // the default is 'siemens-brand';
$element-themes: ('oem'), // themes to build.
);
@use '@siemens/element-ng/element-ng';
// build the OEM theme
@use '@siemens/element-theme/src/styles/themes';
@use './theme-oem';
@include themes.make-theme(theme-oem.$theme-oem, 'oem', false);
The list $element-themes
doesn't need to include the value set as $element-theme-default
. $element-theme-default
determines the name of the theme used as default, i.e. the one that is active w/o setting any additional class on the root element.
To use e.g. the siemens-brand
theme by default but also allow a oem
theme as opt-in, use $element-theme-default: 'siemens-brand'
or completely emit this configuration and provide $element-themes: ('oem')
. The additional oem
theme is built and can be activated by applying the class theme-oem
to the <html>
tag.
If both a light and a dark mode version are desired, defines two maps, e.g.
$theme-oem-light: (
// light mode and shared definitions
);
$theme-oem-dark: (
// dark mode definitions
);
Then, use themes.make-theme()
like this:
@include themes.make-theme(theme-oem.$theme-oem-light, 'oem', false);
@include themes.make-theme(theme-oem.$theme-oem-dark, 'oem', true);
Important info
The required keys in the map might change in future versions of Element, so forward compatibility is not guaranteed. Topic like usability and accessibility and not guaranteed that way so please always involve UX when using this feature.
Except where otherwise noted, content on this site is licensed under MIT License.