Theming-App

Integrating the theming app

You can reference the theming app API as a script link:

<script src="/theming/import"></script>

Note: You should integrate the theming API script as early as possible to prevent the resource from briefly being displayed in the default colors.

How can I integrate the colors of the theming app?

First option: CSS variables

The theming API script ensures that the colors of the theming app are set in the :root selector in your resource. It also resolves errors that are known to us and inaccuracies in the Material CSS classes. If you are using the default Material classes or your framework builds on these CSS classes, you have now finished setting up the theming app. Now check whether all the colors have been applied correctly everywhere, once in the default bright design and once in the default dark design.

Note: The link tag for the CSS variables is set at the start of the HTML head, and the CSS fixes at the end.

Defining a fallback theme

If the theming app cannot be reached, the theming API uses the standard d.velop AG design. If the initialization of the theming API fails, you can create and reference a CSS file with the CSS variables in your project. In this case, this CSS file should be called dvelopThemingFallback.css. This link tag is removed if the theming API has been initialized successfully.

Preventing the inclusion of CSS variables

If window.ignoreCSSTheme is set to true, the CSS variables and CSS fixes are not included in your resource.

<script>
  window.ignoreCSSTheme = true;
</script>
<script src="/theming/import"></script>

Preventing the inclusion of CSS fixes

If window.ignoreThemeFixes is set to true, the CSS fixes are not included in your resource. The CSS variables are still included.

<script>
  window.ignoreThemeFixes = true;
</script>
<script src="/theming/import"></script>

Second option: JSON

You can also integrate the theming colors in JSON format. In this case, an event is sent once the color values are available:

let theme;
if( window.themingInstance && window.themingInstance.GetJSON() ) {
    theme = JSON.parse( window.themingInstance.GetJSON() );
    ...
} else {
    window.addEventListener('dvelopThemingLoaded', () => {
        theme = JSON.parse( window.themingInstance.GetJSON() );
        ...
    });
}

Warning: The JSON values must be processed by your app before they become effective in the user interface. To avoid any flickering during navigation, the background color of the resource should be obtained via CSS at minimum.

What are the benefits of the theming app?

Centralization of user-specific color values

When you use the theming app, you do not need to worry about which colors your app is to use. The theming app supplies you with the colors of the design schema selected by the user that is currently logged in. The GUI framework you use determines how you use the colors. Users can then choose from a variety of design schemas (bright, dark, accessibility, etc.).

Accessibility

If you are using the theming app, you can make your app design more accessible. More information under Accessibility.

How does theming work in Material Design?

The Material theming function builds on three color values: The primary, secondary and background colors. The items in focus are in the primary color (e.g. buttons). Items that should provide a contrast are in the secondary color (e.g. checkboxes). In addition, gradients of the font color are used on some components (e.g. non-clickable buttons).

A complete theme therefore has the following properties:

  • Primary color
  • Font color on primary color
  • Secondary color
  • Font color on secondary color
  • Error color
  • Font color for error color
  • Background color
  • Font color for background color
  • Gradients

In the preconfigured Material web components, this system is implemented with the aid of CSS variables. You can globally set the CSS variables (that is, in the root: selector) to overwrite the default Material colors:

:root {
  --mdc-theme-primary: #fa1234;
  --mdc-theme-on-primary: #000000;
  --mdc-theme-secondary: #ee3460;
  --mdc-theme-on-secondary: #ffffff;
  --mdc-theme-surface: #ffffff;
  --mdc-theme-on-surface: #000000;
  --mdc-theme-background: #ffffff;
  --mdc-theme-on-background: #000000;
  --mdc-theme-error: #B0020;
  --mdc-theme-on-error: #ffffff;
  --mdc-theme-text-hint-on-background: rgba(0, 0, 0, 0.38);
  ...;
}

However, Material has not implemented the function itself completely consistently. In some CSS classes, a static color value is still used.

Theming errors, color corrections and additional color values

The theming app corrects the mentioned Material theming errors. In addition, some Material Design decisions are corrected in favor of a clear contrast, such as the colors of selected chips. Additional color values (for warnings or success messages, for example) are also supplied.

Accessibility

The theming app offers various functions in the context of accessibility.

High contrast design

If your app uses the color values from the theming app, you no longer have to worry about contrast values, because the high-contrast design available by default fulfils the specifications regarding contrasts from BITV 2.0.

warning: If you use a material framework, further adjustments may be necessary.

Focus frame

The Theming app offers the user the option of activating focus frames. This can be done either implicitly via the selection of the high-contrast theme or explicitly via the accessibility dialog. The focus frames are automatically set in each iFrame via the following CSS rule:

*:focus:not(.theming-no-focus-border) {
  border: 2px solid var(--mdc-theme-primary) !important;
}

This focus mechanism also works if you do not use material design. If you explicitly do not want a border to be displayed for an element in the focused state, add the CSS class theming-no-focus-border to the element.

This option can also be queried via Javascript:

<script src="/theming/importAccessibility"></script>
if( window.accessibilityInstance.FocusBordersActivated ) {
...
}

A change in the accessibility dialog is reported via an event in all iFrames:

document.addEventListener("dvelopAccessibilityFocusBordersActivatedChanged", () => {
    if( window.accessibilityInstance.FocusBordersActivated ) {
        ...
    } else {
        ...
    }
})

Disable animations

In the accessibility dialog, users can deactivate animations. This is realised by the following CSS rule, which is set in all iFrames as soon as the user has activated the setting:

*:not(.dvelopAccessibilityKeepAnimations) {
  -webkit-transition: none !important;
  -moz-transition: none !important;
  -o-transition: none !important;
  -ms-transition: none !important;
  transition: none !important;
  animation-duration: 0s !important;
}

If an element is still to display animations with this setting, the class dvelopAccessibilityKeepAnimations must now be added to the respective element.

This option can also be queried via Javascript, e.g. to handle timeouts differently:

<script src="/theming/importAccessibility"></script>
if( window.accessibilityInstance.AnimationsDisabled ) {
...
}

A change in the accessibility dialog is reported via an event in all iFrames:

document.addEventListener("dvelopAccessibilityDisableAnimationsChanged", () => {
    if( window.accessibilityInstance.AnimationsDisabled ) {
        ...
    } else {
        ...
    }
})

Deactivate timings

info: This functionality is not yet available everywhere.

In the accessibility dialog, users can deactivate timings. Here, however, the theming app only takes over the storage of the activation status and makes it available to the apps. For this, the accessibility API must be included:

<script src="/theming/importAccessibility"></script>
if( window.accessibilityInstance.TimingsDisabled ) {
    ...
}

In addition, an event is sent to all iframes when the setting is changed:

document.addEventListener("dvelopAccessibilityDisableTimingsChanged", () => {
    if( window.accessibilityInstance.TimingsDisabled ) {
        ...
    } else {
        ...
    }
})

Supplied color values

CSS

:root {
  color-scheme: <light or dark>;

  --mdc-theme-primary: <primary color>;
  --mdc-theme-on-primary: <font color on primary color>;
  --mdc-theme-secondary: <secondary color>;
  --mdc-theme-on-secondary: <font color on secondary color>;
  --mdc-theme-surface: <background color>;
  --mdc-theme-on-surface: <font color on background>;
  --mdc-theme-background: <background color>;
  --mdc-theme-on-background: <font color on background>;
  --mdc-theme-error: <error color>;
  --mdc-theme-on-error: <font color on error color>;

  --mdc-theme-text-hint-on-background: <font color 38%>;
  --mdc-theme-text-primary-on-background: <font color 87%>;
  --mdc-theme-text-secondary-on-background: <font color 54%>;
  --mdc-theme-text-disabled-on-background: <font color 38%>;
  --mdc-theme-text-icon-on-background: <font color 54%>;
  --mdc-checkbox-unchecked-color: <font color 54%>;
  --mdc-checkbox-checked-color: <secondary color>;
  --mdc-checkbox-disabled-color: <font color 38%>;
  --mdc-checkbox-ink-color: <background color 54%>;
  --mdc-theme-text-primary-on-light: <font color 87%>;
  --mdc-theme-text-secondary-on-light: <font color 54%>;
  --mdc-theme-text-hint-on-light: <font color 38%>;
  --mdc-theme-text-disabled-on-light: <font color 38%>;
  --mdc-theme-text-icon-on-light: <font color 70%>;
  --mdc-theme-text-icon-on-dark: <background color 50%>;
  --mdc-theme-text-disabled-on-dark: <background color 50%>;
  --mdc-theme-text-hint-on-dark: <background color 50%>;
  --mdc-theme-text-secondary-on-dark: <background color 70%>;
  --mdc-ripple-hover-opacity: <opacity for ripples on hover>;
  --mdc-ripple-press-opacity: <opacity for ripples on press>;
  --mdc-ripple-color: <font color 54%>;

  --dmc-theme-background12: <background color 12%>;
  --dmc-theme-on-background12: <font color 12%>;
  --dmc-theme-background32: <background color 32%>;
  --dmc-theme-on-background32: <font color 32%>;
  --dmc-theme-background38: <background color 38%>;
  --dmc-theme-on-background38: <font color 38%>;
  --dmc-theme-background50: <background color 50%>;
  --dmc-theme-on-background50: <font color 50%>;
  --dmc-theme-background54: <background color 54%>;
  --dmc-theme-on-background54: <font color 54%>;
  --dmc-theme-background60: <background color 60%>;
  --dmc-theme-on-background60: <font color 60%>;
  --dmc-theme-background62: <background color 62%>;
  --dmc-theme-on-background62: <font color 62%>;
  --dmc-theme-background70: <background color 70%>;
  --dmc-theme-on-background70: <font color 70%>;
  --dmc-theme-background87: <background color 87%>;
  --dmc-theme-on-background87: <font color 87%>;
  --dmc-theme-disabled-text: <disabled text>;
  --dmc-theme-disabled-background: <disabled background>;
  --dmc-theme-on-disabled-background: <font color on disabled>;
  --dmc-theme-chip-color: <chip color>;
  --dmc-theme-on-chip-color: <font color for chip>;
  --dmc-theme-chip-selected: <color for selected chip>;
  --dmc-theme-snackbar: <background color snackbar>;
  --dmc-theme-progress: <color progressbar>;
  --dmc-theme-primary-transparent: <primary color transparent>;
  --dmc-theme-green: <green for success messages>;
  --dmc-theme-green-transparent: <green transparent>;
  --dmc-theme-yellow: <yellow for warning messages>;
  --dmc-theme-yellow-transparent: <yellow transparent>;
  --dmc-theme-red-transparent: <red transparent>;
  --dmc-theme-smoke: <smoke>;
  --dmc-theme-elevation--z1: <box-shadow for elevation-level 1>;
  --dmc-theme-elevation--z2: <box-shadow for elevation-level 2>;
  --dmc-theme-elevation--z3: <box-shadow for elevation-level 3>;
  --dmc-theme-elevation--z4: <box-shadow for elevation-level 4>;
  --dmc-theme-elevation--z5: <box-shadow for elevation-level 5>;
  --dmc-theme-elevation--z6: <box-shadow for elevation-level 6>;
  --dmc-theme-elevation--z7: <box-shadow for elevation-level 7>;
  --dmc-theme-elevation--z8: <box-shadow for elevation-level 8>;
  --dmc-theme-elevation--z9: <box-shadow for elevation-level 9>;
  --dmc-theme-elevation--z10: <box-shadow for elevation-level 10>;
  --dmc-theme-elevation--z11: <box-shadow for elevation-level 11>;
  --dmc-theme-elevation--z12: <box-shadow for elevation-level 12>;
  --dmc-theme-elevation--z13: <box-shadow for elevation-level 13>;
  --dmc-theme-elevation--z14: <box-shadow for elevation-level 14>;
  --dmc-theme-elevation--z15: <box-shadow for elevation-level 15>;
  --dmc-theme-elevation--z16: <box-shadow for elevation-level 16>;
  --dmc-theme-elevation--z17: <box-shadow for elevation-level 17>;
  --dmc-theme-elevation--z18: <box-shadow for elevation-level 18>;
  --dmc-theme-elevation--z19: <box-shadow for elevation-level 19>;
  --dmc-theme-elevation--z20: <box-shadow for elevation-level 20>;
  --dmc-theme-elevation--z21: <box-shadow for elevation-level 21>;
  --dmc-theme-elevation--z22: <box-shadow for elevation-level 22>;
  --dmc-theme-elevation--z23: <box-shadow for elevation-level 23>;
  --dmc-theme-elevation--z24: <box-shadow for elevation-level 24>;

  --dmc-theme-primary-rgb: <primary color as rgb value>;
  --dmc-theme-on-primary-rgb: <font color on primary color as rgb value>;
  --dmc-theme-secondary-rgb: <secondary color as rgb value>;
  --dmc-theme-on-secondary-rgb: <font color on secondary color as rgb value>;
  --dmc-theme-surface-rgb: <background color as rgb value>;
  --dmc-theme-on-surface-rgb: <font color on background color as rgb value>;
  --dmc-theme-background-rgb: <background color as rgb value>;
  --dmc-theme-on-background-rgb: <font color on background color as rgb value>;
  --dmc-theme-error-rgb: <error color as rgb value>;
  --dmc-theme-on-error-rgb: <font color on error color as rgb value>;

  --dmc-theme-opacity-0: <opacity level 0>;
  --dmc-theme-opacity-4: <opacity level 0.04>;
  --dmc-theme-opacity-12: <opacity level 0.12>;
  --dmc-theme-opacity-26: <opacity level 0.26>;
  --dmc-theme-opacity-32: <opacity level 0.32>;
  --dmc-theme-opacity-38: <opacity level 0.38>;
  --dmc-theme-opacity-42: <opacity level 0.42>;
  --dmc-theme-opacity-50: <opacity level 0.50>;
  --dmc-theme-opacity-54: <opacity level 0.54>;
  --dmc-theme-opacity-60: <opacity level 0.60>;
  --dmc-theme-opacity-62: <opacity level 0.62>;
  --dmc-theme-opacity-70: <opacity level 0.70>;
  --dmc-theme-opacity-87: <opacity level 0.87>;
}

JSON

{
  "Name": "<Themename>",
  "IsDark": "<true or false>",
  "Contrast": "<true or false>",
  "PrimaryColor": "<primary color>",
  "SecondaryColor": "<secondary color>",
  "BackgroundColor": "<background color>",
  "Error": "<error color>",
  "OnPrimaryColor": "<font color on primary color>",
  "OnSecondaryColor": "<font color on secondary color>",
  "OnBackgroundColor": "<font color on background color>",
  "OnErrorColor": "<font color on error color>",
  "Background12": "<background color 12%>",
  "OnBackground12": "<font color 12%>",
  "Background38": "<background color 38%>",
  "OnBackground38": "<font color 38%>",
  "Background32": "rgba(255,255,255,0.32)",
  "OnBackground32": "<font color 32%>",
  "Background50": "<background color 50%>",
  "OnBackground50": "<font color 50%>",
  "Background54": "<background color 54%>",
  "OnBackground54": "<font color 54%>",
  "Background60": "<background color 60%>",
  "OnBackground60": "<font color 60%>",
  "Background62": "<background color 62%>",
  "OnBackground62": "<font color 62%>",
  "Background70": "<background color 70%>",
  "OnBackground70": "<font color 70%>",
  "Background87": "<background color 87%>",
  "OnBackground87": "<font color 87%>",
  "RippleHoverOpacity": "<opacity for ripples on hover>",
  "RipplePressOpacity": "<opacity for ripples on press>",
  "DisabledText": "<disabled text>",
  "DisabledBackground": "<disabled background>",
  "OnDisabledBackground": "<font color on disabled>",
  "ChipColor": "<chip color>",
  "ChipSelected": "<color for selected chip>",
  "OnChipColor": "<font color für chips>",
  "Snackbar": "<background color snackbar>",
  "Progress": "<color progressbar>",
  "Smoke": "<smoke>",
  "PrimaryTransparent": "<primary color transparent>",
  "Green": "<green for success messages>",
  "GreenTransparent": "<green transparent>",
  "Yellow": "<yellow for warning messages>",
  "YellowTransparent": "<yellow transparent>",
  "RedTransparent": "<red transparent>",
  "ElevationZ1": "<box-shadow for elevation-level 1>",
  "ElevationZ2": "<box-shadow for elevation-level 2>",
  "ElevationZ3": "<box-shadow for elevation-level 3>",
  "ElevationZ4": "<box-shadow for elevation-level 4>",
  "ElevationZ5": "<box-shadow for elevation-level 5>",
  "ElevationZ6": "<box-shadow for elevation-level 6>",
  "ElevationZ7": "<box-shadow for elevation-level 7>",
  "ElevationZ8": "<box-shadow for elevation-level 8>",
  "ElevationZ9": "<box-shadow for elevation-level 9>",
  "ElevationZ10": "<box-shadow for elevation-level 10>",
  "ElevationZ11": "<box-shadow for elevation-level 11>",
  "ElevationZ12": "<box-shadow for elevation-level 12>",
  "ElevationZ13": "<box-shadow for elevation-level 13>",
  "ElevationZ14": "<box-shadow for elevation-level 14>",
  "ElevationZ15": "<box-shadow for elevation-level 15>",
  "ElevationZ16": "<box-shadow for elevation-level 16>",
  "ElevationZ17": "<box-shadow for elevation-level 17>",
  "ElevationZ18": "<box-shadow for elevation-level 18>",
  "ElevationZ19": "<box-shadow for elevation-level 19>",
  "ElevationZ20": "<box-shadow for elevation-level 20>",
  "ElevationZ21": "<box-shadow for elevation-level 21>",
  "ElevationZ22": "<box-shadow for elevation-level 22>",
  "ElevationZ23": "<box-shadow for elevation-level 23>",
  "ElevationZ24": "<box-shadow for elevation-level 24>",
  "PrimaryRGB": "<primary color as rgb value>",
  "SecondaryRGB": "<secondary color as rgb value>",
  "BackgroundRGB": "<background color as rgb value>",
  "ErrorRGB": "<error color as rgb value>",
  "OnPrimaryRGB": "<font color on primary color as rgb value>",
  "OnSecondaryRGB": "<font color on secondary color as rgb value>",
  "OnBackgroundRGB": "<font color on background color as rgb value>",
  "OnErrorRGB": "<font color on error color as rgb value>",
  "Opacity0": "<opacity level 0>",
  "Opacity4": "<opacity level 0.4>",
  "Opacity12": "<opacity level 0.12>",
  "Opacity26": "<opacity level 0.26>",
  "Opacity32": "<opacity level 0.32>",
  "Opacity38": "<opacity level 0.38>",
  "Opacity42": "<opacity level 0.42>",
  "Opacity50": "<opacity level 0.50>",
  "Opacity54": "<opacity level 0.54>",
  "Opacity60": "<opacity level 0.6>",
  "Opacity62": "<opacity level 0.62>",
  "Opacity70": "<opacity level 0.7>",
  "Opacity87": "<opacity level 0.87>"
}