Skip to content

XPages App to Web App: Part Seven - CSS

In the last part we created the login form. In this part we're going to start adding some theming.

Theme Colours

The power of XPages is in the out-of-the-box themes available. These provide styling for the various XPages components and some developers may even have not add their own CSS. But hopefully developers have.

Those who have been developing since the days of Domino 8.5.2 and 8.5.3 may remember the OneUIv2.1 themes which included colour variants. If you have an older Domino server, you may still find them in /Data/domino/html/oneuiv2.1/themes directory. In here are theme directories for blue, gold, green, onyx, orange, pink, purple, red, and silver. Each directory has its own CSS files. The files are virtually identical except for different colours for a handful of elements. To change colour theme for XPages' OneUI2.1 themes, we usually would change the theme of the database and rebuild the application. (If I remember correctly, the XPages demo application provided a dynamic way of switching theme colour, but I don't have an example to check.)

This was how different coloured themes was done in those days. But things have changed.

There is now a better way to handle theme colouring. Colours are no longer defined in stylesheets. Instead CSS variables are a better way. A separate stylesheet can assign colours to a variable name, and the main stylesheet can then use those variables. For example, we will have a stylesheet called "blue-theme.css":

:root {
    --primary-color: #000;
    --primary-color-dark: #FFF;
    --button-primary: #005C99;
    --button-primary-dark: #708DA0;
}

By assigning the variables to the root, they are global. And the syntax is "--" + variable name. The main stylesheet will not have any colours defined. Instead, the variable names will be used:

.btn-primary {
  background-color: var(--button-primary);
  color: var(--primary-color-dark);
}

With this approach, to change the colour of the application, we just need to load a different CSS stylesheet, switching "blue-theme.css" for "green-theme.css", for example.

The use of CSS variables can be used for more than just colours, for example for font-sizes or fonts. This provides a great amount of flexibility for UI.

It's probably not an option XPages developers have used though, even in more recent versions of Domino, because it requires the main stylesheet to use variables. However, when moving beyond XPages, it's an option that can - and should - be embraced. And with variables and native for support for calc(), nesting, color-mix(), and even trigonometric functions, if you're not supporting legacy browsers you may not even need to use SASS or LESS.

light-dark

Enabled with CSS

But modern websites and web applications provide something more. Users expect to choose light-mode or dark-mode - or for it to auto-adjust. The good news is that this too can also be handled with standard CSS using light-dark(). If you looked closely at the extract from "blue-theme.css" above, you'll have noticed that there is --primary-color and --primary-color-dark. I deliberately omitted something from the main CSS. The actual styling I'm using is:

.btn-primary {
  background-color: light-dark(var(--button-primary), var(--button-primary-dark));
  color: light-dark(var(--primary-color-dark), var(--primary-color));
}

With the use of variables this starts to get a little trickier to read. But the syntax used is to pass two colours to light-dark(). The first is the colour to use when in light-mode, the second is the colour to use when in dark-mode. To actually use this, we need to add something more to the main stylesheet:

:root {
  color-scheme: light dark;
}

.light-mode {
  color-scheme: only light;
}

.dark-mode {
  color-scheme: only dark;
}

Light-Dark Switcher

With just this CSS, the application will pick up the light or dark mode of the operating system. It's important to understand that even though you can set light or dark mode on the browser, it's the operating system setting that light-dark uses.

The application I'm building is only used by me. I prefer to switch between light and dark mode at the click of an icon. So I'm not auto-switching the theme based on the operating system setting. Instead, I'm adding a switcher icon and storing the setting in localStorage, which we covered in the last blog post.

To switch the theme, I'm preferring an icon. There are various icon libraries out there, but I'm using Google's material design icons. This means I can just use a span, just with different text in the span. As in part five I'll be adding the event handler and loading the relevant light/dark setting in the bootstrap() function:

    const themeSwitcher = document.getElementById("themeToggle");
    themeSwitcher.addEventListener("click", function () {
        switchTheme(true);
    });
    switchTheme(false);

The boolean parameter being passed is whether or not to change the theme. So on the eventHandler, we want to change the theme, whereas in the bootstrap we just want to set the theme. The switchTheme() function itself is this:

const switchTheme = (switchTheme) => {
    // localStorage is only a string
    const darkMode = localStorage.getItem("shipSpotterLightDark") === "true";
    if (switchTheme) {
        darkMode = !darkMode;
        localStorage.setItem("shipSpotterLightDark", darkMode);
    }
    let toggle = document.getElementById("themeToggle");
    if (darkMode) {
        document.documentElement.classList.add("dark-mode");
        document.documentElement.classList.remove("light-mode");
        toggle.innerText = "light_mode";
    } else {
        document.documentElement.classList.add("light-mode");
        document.documentElement.classList.remove("dark-mode");
        toggle.innerText = "dark_mode";
    }
};

The first line of the function checks whether dark mode has been enabled. Remember localStorage values are always strings and may be null, so we need to handle it accordingly. From the eventHandler, we toggle the boolean and update localStorage. Then we set the relevant class (light-mode or dark-mode) on the html tag. We also put the relevant label (light_mode or dark_mode) on the themeToggle span to set the icon accordingly.

Wrap up

In 2024 CSS is extremely powerful. Frustratingly powerful, at times. But extremely powerful. Because of its prevalence for many years, SASS and LESS will still be used in many applications for some years. But when targeting only modern browsers, in many scenarios CSS alone may be sufficient.

Table of Contents

  1. Introduction
  2. Dev Tools
  3. Frameworks
  4. DRAPI
  5. Home Page
  6. Mocking, Fetch, DRAPI and CORS
  7. CSS
  8. Landing Page Web Component
  9. Services
  10. Ship Form Actions
  11. Ship Search and Save