Themes and styles
Styles in a Lagoon application are not written in CSS: they are generated at every build from SCSS sources of Lagoon.UI* modules and SCSS files of the client project. This page explains how the result is composed, how to customize it, and how to offer multiple themes to the user.
Application style files
Application SCSS sources are located in Client/resources/styles/. For a single-theme application, the entry point is main.scss:
// Use RGAA compatible style
$custom-rgaa: false;
// Label position
$custom-label-outside: false;
// Set the header logo
$header-logo: "~/images/header-logo.png";
// Spinner
$spinner: 'logo';
$sp-color: $primary;
The build compiles this file to Client/wwwroot/_vroot/styles.css. The _vroot folder is build output: do not modify it and do not version it. To change the rendering, always modify the SCSS sources.
Compilation is performed by MSBuild tasks from the Lagoon.Build package, before each application build. In Release, the stylesheet is minified; in Debug, it remains readable. The project's <LagoonMinifyCss>true|false</LagoonMinifyCss> property forces one or the other.
Aggregation order
All sources are merged into a single SCSS document, in this order:
Lagoon.UI: Bootstrap, variables, and component styles;- other referenced
Lagoon.UI*modules (Lagoon.UI.GridView,Lagoon.UI.Notifications, …); - the application file (
main.scss, or eachtheme-*.scss).
Override a variable
Lagoon's SCSS engine has been modified to allow variable redefinition at the global level: the last assignment of a variable applies to the entire document, including styles of modules declared before it. The !default keyword is therefore unnecessary.
Concretely, all variable declarations are grouped before style rules, keeping only the last value of each and reordering them according to their dependencies. A variable assigned in the application file, which is processed last, takes precedence over values defined by modules:
// Every Lagoon.UI rule using $primary picks up this value
$primary: #0B5394;
// A variable can reference another one, whatever the declaration order
$sp-color: $primary;
In application files, the ~/ prefix designates the site root (~/images/logo.png). In module sources, it designates the _content/<Module>/ folder of that module.
$custom-* options
Some boolean variables select an entire set of variables and styles:
| Variable | Effect | Default value |
|---|---|---|
$custom-rgaa | More contrasted palette and adjustments for accessibility (RGAA). | false |
$custom-label-outside | Labels displayed above fields, instead of being placed in the field as a placeholder. | false |
See Accessibility for the use of these options.
Offering multiple themes
An application can offer multiple themes, for the user to choose from. A theme is a complete stylesheet, compiled from a theme-<nom>.scss file. Themes rely on the same modules and vary their variables (colors, $custom-* options, logos, spinner, …).
Declare themes
Create a theme-<nom>.scss file per theme in Client/resources/styles/, and place what is common in a shared file imported by each of them:
// Label position
$custom-label-outside: false;
// Use RGAA compatible style
$custom-rgaa: false;
@import "shared";
// Use RGAA compatible style
$custom-rgaa: true;
// Label position
$custom-label-outside: true;
@import "shared";
// Set the header logo
$header-logo: "~/images/header-logo.png";
.my-custom-class {
color: $primary;
}
Each theme-<nom>.scss is compiled to _vroot/theme-<nom>.css, and the theme name is the <nom> part of the file (standard and rgaa in the example).
main.scss is ignoredOnce a theme-*.scss file exists, main.scss is no longer compiled and styles.css is no longer produced. Move its content to the shared file.
At startup, the server detects themes from the generated theme-*.css files and transmits them to the client. No list needs to be maintained.
Choose the default theme
The theme applied until the user chooses another one is configured with the App:Theme key in the server's appsettings.json:
{
"App": {
"Theme": "rgaa"
}
}
If the key is absent, or if it does not match any theme, the first theme in alphabetical order is used.
Only set App:Theme if the application declares themes: without a theme-*.scss file, the homepage would look for a theme-<nom>.css sheet that does not exist.
Let the user choose
Add LgThemeMenuItem to the menu. It opens, in a small modal window, the theme selection page, which displays one button per theme:
<LgThemeMenuItem />
The label of each button is the translation key theme-<nom>. Declare it in the client project's Dico.xml:
<string key="theme-standard" fr="Standard" en="Standard" />
<string key="theme-rgaa" fr="RGAA" en="WCAG" />
The choice is applied immediately, without reloading the page, and saved in the browser (key theme in localStorage). It is therefore specific to each browser, not to the user account. If the saved theme cannot be loaded, for example because it was deleted, the application reverts to the default theme.
Change theme programmatically
The client application (App, available in any component inheriting from LgComponentBase) exposes the themes:
| Member | Role |
|---|---|
App.Themes | List of available themes (empty for a single-theme application). |
App.GetCurrentTheme() | Name of the displayed theme. |
App.SetTheme(string theme) | Applies and saves a theme; raises an ArgumentException if the name is not in App.Themes. |
Favicon and icon per theme
Each theme can have its own tab icon and its own application icon: place favicon-<nom>.ico and icon-<nom>.png in Client/wwwroot/, alongside favicon.ico and icon.png. They are swapped when the theme changes. A theme without a dedicated file uses favicon.ico and icon.png.
Home page (index.html)
Keep the link to styles.css in the client's index.html, even in a multi-theme application:
<link rel="stylesheet" href="styles.css?v={APP_VERSION}" />
The server rewrites it on the fly to load the saved theme's or default theme's stylesheet, and adds a preload script for this sheet at the top of the page. The hash of this script is automatically added to the content security policy (CSP).
See also
- Spinner — SCSS variables of the loading spinner.
- Application — application logos.
- Accessibility —
$custom-rgaaand$custom-label-outsideoptions. - LgThemeMenuItem — theme selection menu entry.