Skip to main content

Creating Custom Theme

The article describes the steps to manually create a custom theme for your UI5 Web Components project without any tools.

Note: We recommend using the UI Theme Designer tool to effortlessly create a custom theme for your UI5 Web Components project as described in the Custom Theming with UI Theme Designer article. However, it requires SAP BTP account and configuration in the SAP BTP Cockpit. In case you don't have access to the UI Theme Designer, this article is for you.

Preface

The theming of the UI5 Web Components is based entirely on CSS variables. Switching between themes means changing the values of these CSS Variables. Applying a custom theme means setting custom values for these CSS Variables.

The CSS variables (used by the UI5 Web Components) are maintained in the theming-base-content project and available also on NPM: @sap-theming/theming-base-content. The great thing is that they are backward compatible - new variables may be added, but old are kept and could be safely used. For instance, you can explore the Morning Horizon CSS Variables. These are exactly the CSS variables being applied when the theme is set to Morning Horizon("sap_horizon").

So far we have the ingredients - the CSS variables. Now, we need to learn what's the easiest way to change them.

At this point, you may ask, can't I just copy the Morning Horizon CSS Variables, change some of the values and finally include the CSS file in my app? And, the answer is yes - you can do that and it will work. Whatever CSS variables you change, the changes will take effect. However, this is not the most effective way.

Instead, it's best to change the source .less file (also available in theming-base-content), change some Less variables and compile it to CSS. Let's see how this could be implemented.

Creating a Custom Theme​

1. Using the "@sap-theming/theming-base-content"​

  • Create a blank project.
mkdir create-custom-theme
cd create-custom-theme
npm init
  • Install @sap-theming/theming-base-content from NPM to get the source .less files of the themes we are going to extend.
npm install @sap-theming/theming-base-content
  • Create a single less file src/mytheme.less.

  • Import source less file of sap_horizon.

// src/mytheme.less

@import "../../node_modules/@sap-theming/theming-base-content/content/Base/baseLib/sap_horizon/css_variables.less";

2. Customizing variables​

You are free to change the values of as many variables as you want. However, we mostly recommend changing the main ones sapPrimary1 - sapPrimary7 as most of the variables are derived from them.

// src/mytheme.less
@import "@sap-theming/theming-base-content/content/Base/baseLib/sap_horizon/css_variables.less";

@sapPrimary1: violet;
@sapPrimary2: violet;

3. Generating the custom CSS variables​

  • Install less to compile less to css.
npm install less --save-dev
  • Create a simple script in the project's root, called customtheme.js
const less = require('less');
const fs = require('fs');

const themeName = "mytheme";
const baseThemeName = "sap_horizon";

const CUSTOM_THEME_METADATA = `
.sapThemeMetaData-Base-baseLib {
background-image: url('data:text/plain;utf-8, { "Path": "Base.baseLib.${themeName}.css_variables", "Extends": ["${baseThemeName}","baseTheme"]}');
}`;

async function compileLess(inputFile, outputFile) {
if (!fs.existsSync("dist")) {
fs.mkdirSync("dist");
}

try {
const lessData = await fs.promises.readFile(inputFile, 'utf-8');

const { css } = await less.render(lessData, {
filename: inputFile
});
const output = `${CUSTOM_THEME_METADATA} ${css}`;

await fs.promises.writeFile(outputFile, output, {encoding:'utf8',flag:'w'});
console.log(`Successfully compiled Less file ${inputFile} to CSS file ${outputFile}`);

} catch (error) {
console.error('Error compiling Less:', error);
}
}

compileLess('src/mytheme.less', 'dist/mytheme.css');

The script runs the less compiler over the .less file (src/mytheme.less) to produce a .css out of it (dist/mytheme.css) and adds a small piece of metadata (see CUSTOM_THEME_METADATA variable), required by the UI5 Web Components framework to detect the custom theme.

  • Create a task in the package.json for convenience
"scripts": {
"build:theme": "node customtheme.js"
}
  • Run the task
npm run build:theme

That's it! The task outputs the CSS variables into the dist/mytheme.css file.

Using a Custom Theme​

1. Adding the custom CSS​

Now that you have generated the custom CSS, you need to add it to your project.

  • The simplest option would be to use a <link> tag and point to the file:
<link rel="stylesheet" type="text/css" href="<path-to-your-css-file>/mytheme.css">
  • Or, use <style> tag and paste the content of mytheme.css inside:
<style>
/* Here goes the content of mytheme.css */
</style>
  • Most of the modern build tools know how to handle CSS imports and could add the imported CSS file content as style tag for us:
import "<path-to-your-css-file>/mytheme.css";

2. Configuring the custom theme​

In the previous step we loaded the CSS, now we only need to set it to the UI5 Web Components. To do so, you can use one of the standard APIs for setting a theme:

  • With URL parameter: index.html?sap-ui-theme=mytheme

  • With JS API:

import { getTheme, setTheme } from "@ui5/webcomponents-base/dist/config/Theme.js";

setTheme("mytheme");

Resources

Everything said so far is implemented in the following demo project - ui5-webcomponents-custom-theme. The project implements the script for producing the custom CSS vars and provides a simple test page to demonstrate the custom theme usage.