Themes
Modes UI offers a default light and dark theme along with some fine-tuned themes (color palettes) based on our highlight colors that you can try out on this documentation page.
A theme is nothing more than a stylesheet that uses the Modes UI token naming convention to define design tokens and apply custom styles to components. To create a theme, you will need a basic understanding of CSS, including CSS Custom Properties
You can also create your own theme using the Modes Theme Builder tool.
Theme basics
All themes are scoped to classes using the mo-theme-{name}
convention, where
{name}
is a lowercase, hyphen-delimited value representing the name of the theme. The included
light and dark themes use mo-theme-default-light
and mo-theme-default-dark
,
respectively. A custom theme called “Amethyst”, for example, would use a class called
mo-theme-amethyst-light
and mo-theme-amethyst-dark
, respectively.
All selectors must be scoped to the theme’s class to ensure interoperability with other themes. You should
also scope them to :host
so they can be imported and applied to custom element shadow roots.
:host, .mo-theme-amethyst-light { /* ... */ }
Activating themes
To activate a theme, import it and apply the theme’s class to the <html>
element. This
example imports and activates the built-in dark theme.
<html class="mo-theme-default-dark"> <head> <link rel="stylesheet" href="path/to/modes-web-components/themes/dark.css" /> </head> <body> ... </body> </html>
There is one exception to this rule — the default light theme does not need to be activated. For
convenience, the light theme is scoped to :root
and will be activated by default when
imported.
Using non-default themes
You should always import the default theme variant that you need. If you want to allow the users to choose between the two options, you will have to import both light and dark default themes. These default theme files include a lot of token variable definitions and the default color definitions that are required for all the components to function as intended. If you want to add more color to your application, you must add the new color scheme on top of the existing default theme (light or dark).
If you want your theme color scheme to work for both light and dark mode, you’ll have to create two separate theme files to apply based on the mode the user has selected. In the dark theme the color scheme (shades) will have to be inverted to create the same contrast with a black background. You can find examples of this in the creating themes section.
<html> <head> <link rel="stylesheet" href="path/to/modes-web-components/themes/light.css" /> <link rel="stylesheet" href="path/to/modes-web-components/themes/dark.css" /> <link rel="stylesheet" href="path/to/modes-web-components/themes/my-custom-theme.css" /> </head> <body> ... </body> </html>
It’s for this reason that themes must be scoped to specific classes.
Gray theme
Modes UI comes with the gray theme, which is a lower contrast variation of the default theme. It is enabled the same way other custom themes are enabled, and it is an extension to the default themes.
<html> <head> <link rel="stylesheet" href="path/to/modes-web-components/themes/light.css" /> <link rel="stylesheet" href="path/to/modes-web-components/themes/dark.css" /> <link rel="stylesheet" href="path/to/modes-web-components/themes/gray.css" /> <link rel="stylesheet" href="path/to/modes-web-components/themes/gray-dark.css" /> </head> <body> ... </body> </html>
Once the theme is imported, enable it by applying the class mo-theme-gray-light
(and
mo-theme-gray-dark
depending on theme) to the root html element in the DOM.
You can find an example of this on this very site. Use the theme selector on the top right and notice how the html class changes in the DOM. If you have access to the source code, you can check the Javascript logic in the theme-picker.js file.
Creating themes
The way you create a new theme in Modes UI is by creating a new color scheme. This color scheme is essentially built from the different shades of one color for now, as the library is monochrome. You need to provide a shade palette with specific token names, that the components will then use instead of the default ones. If these tokens are misnamed or otherwise broken, the components will fallback to the default theme values.
Here’s an example of the Amethyst
theme files that are offered in the library:
:host, html[class*='amethyst'] { --mo-color-primary-0: #000000; --mo-color-primary-10: #250059; --mo-color-primary-20: #3f0689; --mo-color-primary-25: #4a1b94; --mo-color-primary-30: #562ba0; --mo-color-primary-35: #6239ad; --mo-color-primary-40: #6e46ba; --mo-color-primary-50: #8860d5; --mo-color-primary-60: #a37af1; --mo-color-primary-70: #bc99ff; --mo-color-primary-80: #d3bbff; --mo-color-primary-90: #ebddff; --mo-color-primary-95: #f7edff; --mo-color-primary-98: #fef7ff; --mo-color-primary-99: #fffbff; --mo-color-primary-100: #ffffff; }
:host, html[class*='amethyst-dark'] { --mo-color-primary-0: #ffffff; --mo-color-primary-10: #ebddff; --mo-color-primary-20: #d3bbff; --mo-color-primary-25: #c7aaff; --mo-color-primary-30: #bc99ff; --mo-color-primary-35: #b088ff; --mo-color-primary-40: #a37af1; --mo-color-primary-50: #8860d5; --mo-color-primary-60: #6e46ba; --mo-color-primary-70: #562ba0; --mo-color-primary-80: #3f0689; --mo-color-primary-90: #250059; --mo-color-primary-95: #18003f; --mo-color-primary-98: #0c0026; --mo-color-primary-99: #060019; --mo-color-primary-100: #000000; }
You can find these pre-defined themes/color schemes in the themes
folder alongside the default
ones. They offer examples on what is a good color scheme in terms of shades, and how to invert the colors
for the use of the dark mode variant.
You can use the Modes Theme Builder to generate both a light and dark mode palette for any given color.
Dark theme
The built-in dark theme uses an inverted color scale so, if you’re using design tokens as intended, you’ll get dark mode for free. While this isn’t the same as a professionally curated dark theme, it provides an excellent baseline for one and you’re encouraged to customize it depending on your needs.
The dark theme works by taking the light theme’s color tokens and “flipping” the scale so 10 becomes 90, 20 becomes 80, 30 becomes 70, etc. Next, the luminance of each primitive was fine-tuned to avoid true black, which is often undesirable in dark themes, and provide a richer experience. The result is a custom dark palette that complements the light theme and makes it easy to offer light and dark modes with minimal effort.
To install the dark theme, add the following to the <head>
section of your page.
<link rel="stylesheet" href="path/to/modes-web-components/themes/dark.css" />
To activate the theme, apply the mo-theme-default-dark
class to the
<html>
element.
<html class="mo-theme-default-dark"> ... </html>
To allow users to toggle between the themes using e.g., the mo-switch
, you can add an event
listener for the mo-change
event in the mo-switch
and programmatically add the
desired theme in to the html
tag. See the theme-picker.js
file in the project’s
source code for an actual JavaScript code example that implements theme switching on this documentation
page.
Detecting the user’s color scheme preference
Modes UI doesn’t try to auto-detect the user’s light/dark mode preference (except on the documentation page). This should be done at the application level. As a best practice, to provide a dark theme in your app, you should:
-
Check for
prefers-color-scheme
and use its value by default - Allow the user to override the setting in your app
- Remember the user’s preference and restore it on subsequent logins
Avoid using the prefers-color-scheme
media query because not all apps support dark mode, and it
would break things for the ones that don’t.