Dark mode requires additional media queries and special classes (for manual dark mode setting). Themed JSS handles all these automatically, you just need to specify property overrides for your theme in dark mode:
1linkimport { theme } from 'themed-jss'
2link
3linkconst myTheme = theme(
4link {
5link primary: 'blue',
6link background: 'white',
7link text: 'black'
8link },
9link // dark mode overrides:
10link {
11link background: 'black',
12link text: 'white'
13link }
14link)
👉 With this theme, this style:
1linkstyle(theme => ({
2link background: theme.primary,
3link text: theme.background,
4link border: `1px solid ${theme.primary}`
5link
6link [when(':hover')]: {
7link background: 'transparent',
8link text: theme.primary
9link }
10link}))
Will be (roughly) compiled to this CSS:
1link.scoped-0-0-1 {
2link background: blue;
3link text: white;
4link border: 1px solid blue;
5link}
6link
7link.scoped-0-0-1:hover {
8link background: transparent;
9link text: blue;
10link}
11link
12link@media (prefers-color-scheme: dark) {
13link .scoped-0-0-1 {
14link text: black;
15link }
16link}
☝️ When dark mode overrides are specified, Themed JSS will calculate each style in both dark mode and light mode. It will then diff the styles, and add necessary media queries and styling rules for CSS properties that do differ between light and dark mode.
In our previous example, the generated media query
will (incorrectly) override color
style over specified :hover
rule. Themed JSS did not include the :hover
rule in the
media query as it did not have any properties that would differ between light and dark mode.
👉 Use!darkmode
to enforce inclusion of a property in dark mode media queries:
1linkstyle(theme => ({
2link background: theme.primary,
3link text: theme.background,
4link border: `1px solid ${theme.primary}`
5link
6link [when(':hover')]: {
7link background: 'transparent',
8link text: `${theme.primary} !darkmode`
9link }
10link}))
Now this (roughly) CSS will be generated:
1link.scoped-0-0-1 {
2link background: blue;
3link text: white;
4link border: 1px solid blue;
5link}
6link
7link.scoped-0-0-1:hover {
8link background: transparent;
9link text: blue;
10link}
11link
12link@media (prefers-color-scheme: dark) {
13link .scoped-0-0-1 {
14link text: black;
15link }
16link
17link .scoped-0-0-1:hover {
18link text: blue;
19link }
20link}
Not all systems support dark mode settings, as a result it is crucial to not only rely on media queries, but also provide the ability for users to override dark mode preference for your website.
👉 Initialize manual dark mode controls:
1linkimport { DarkMode } from 'themed-jss/dark-mode'
2link
3linkDarkMode.initialize()
👉 Toggle dark mode settings:
1linkDarkMode.toggle()
👉 Set dark mode preference:
1linkimport { DarkModeState } from 'themed-jss/dark-mode'
2link
3linkDarkMode.state().set(DarkModeState.Light)
4linkDarkMode.state().set(DarkModeState.Dark)
👉 Read dark mode preference:
1linkDarkMode.state().get()
👉 Subscribe to dark mode settings:
1linkimport { subscribe, pipe } from 'callbag-common'
2link
3linkpipe(
4link DarkMode.state(),
5link subscribe(state => {
6link if (state === DarkModeState.Light) console.log('LIGHT MODE')
7link else console.log('DARK MODE')
8link })
9link)
☝️
DarkMode
state will by default be set to system settings (i.e. matching media query). If it is toggled / set to something different, the state will be stored in local storage automatically. On next boot (DarkMode.initialize()
), the local storage value will also be fetched.If the dark mode preference is switched back to what the system setting is, the local storage override will be deleted. This means if the user reverts back to system settings and then changes their system settings, dark mode state will also be updated automatically.
👉 Use inDarkMode()
for styles specific to dark mode, and inLightMode()
for styles specific to light mode:
1linkimport { inDarkMode, inLightMode } from 'themed-jss/dark-mode'
2link
3linkexport default style(theme => ({
4link background: theme.primary,
5link text: theme.background,
6link
7link ...inDarkMode({
8link borderColor: theme.card,
9link }),
10link
11link ...inLightMode({
12link borderColor: theme.text
13link }),
14link}))
Home Usage Dark Mode Reference Helpers