DarkColorScheme

Summary: How to use the core dark/night theme or add one to your skin
Version: 20240123
Prerequisites: PmWiki 2.3.30 or more recent, recent browser with JavaScript and localStorage enabled
Status: experimental
Maintainer: Petko
License: GPL
Categories: Skins, Layout, CSS
Users: (view? / edit)

How to add a dark color theme to my skin?

Description

PmWiki helper functions for a dark color theme.

Work is underway to enable a dark color theme for the PmWiki-responsive skin. The functions and the user interface can be reused with other skins, if the skin maintainer prefers it.

This page outlines how a custom skin can offer a dark mode with the core functions.

To enable these functions for your skin, add to your skin.php file something like this:

global $EnableDarkThemeToggle;
SDV($EnableDarkThemeToggle, 1);

(Using SDV() here will allow admins to override this variable from config.php.)

If the skin doesn't have a skin.php file but supports toggling between light and dark themes, a wiki administrator can add $EnableDarkThemeToggle = 1; to config.php.

See $EnableDarkThemeToggle.

Core functions

PmWiki 2.3.30 has new functions that make it easy to enable a dark color theme (or scheme). The PmWiki-responsive skin has styles for a dark theme, but the core functions are also available and can be reused in other skins.

The dark theme is toggled automatically by adding or removing a class name "pmDarkTheme" to the <html> element of the wiki page, and the settings are remembered in local storage on the browser.

This happens in 3 cases:

  • a user clicks on a Dark theme label or icon somewhere in the page;
  • a user browses to a new page;
  • a user has opened multiple tabs and toggles the dark theme in one of them -- in this case all other open tabs are also toggled.

The functions can also activate and deactivate stylesheets from the page if they have the attribute data-theme="dark" or data-theme="light".

There is a theme toggle switch which can be easily inserted either in the skin template, or in a wiki page, header, footer or sidebar. The switch can be just an icon, or it can have a label. You can have more than one toggle switch in a page, any of them toggles the dark theme.

It is also possible to have CSS classNames and WikiStyles displaying and hiding content based on the color theme. All these are in the core and can be enabled (and customized) in other skins.

Most of the core functions are in the file pmwiki/pub/pmwiki-utils.js -- make sure it is updated and enabled (it is by default, per $EnablePmUtils).

Syntax highlighting

This applies to the syntax highlighting with the core PmWiki-Responsive skin and with other skins.

There are 2 types of syntax highlighting.

One is PmSyntax for the PmWiki markup, and it already includes styles for the dark theme. Note that these are experimental and we may change them if we find better ones. As usual, you can override the core styles with your own in pub/css/local.css, and feel free to suggest a better color theme at PITS:01497.

The other is WikiStyles#highlight for displaying code from different programming languages. PmWiki uses the HighlightJS library which comes with many light and dark color themes, and the installation code at WikiStyles#highlight can be adapted to load any of them. See below Separate stylesheets per color theme for an explanation of the data-theme="dark" disabled attributes.

Custom skin styles

In the skin.css file, it may be easiest to define all your colors as custom properties or variables.

/* Define the colors for the light theme */
:root {
  --myskin-color: black;
  --myskin-bgcolor: white;
  --myskin-linkcolor: blue;
}

/* Define the colors for the dark theme */
@media screen {
  html.pmDarkTheme {
    --myskin-color: #ccc;
    --myskin-bgcolor: #111;
    --myskin-linkcolor: #8ff;

    /*this is for the input forms, links*/
    color-scheme: dark;
  }
}
/* Optional: Define styles for the ◪ toggle icon */
.pmToggleDarkTheme {
  cursor: pointer;
}
.pmToggleDarkTheme:before {
  content: "\25ea";
}

/* Use the variables in your definitions for texts, backgrounds and links */
body {
  color: var(--myskin-color);
  background-color: var(--myskin-bgcolor);
}
a {
  color: var(--myskin-linkcolor);
}

/* Slightly dim embedded images and videos in dark mode */
@media screen {
  html.pmDarkTheme img, html.pmDarkTheme video {
    filter: brightness(.8) saturate(.8) contrast(1.1);
  }
}

/* Optional: classes to show/hide depending on the theme */
html.pmDarkTheme .onlyLightTheme,
html:not(.pmDarkTheme) .onlyDarkTheme {
  display: none;
}

Separate stylesheets per color theme

You can use CSS variables as outlined above, or separate stylesheets that will be enabled or disabled when needed.

Stylesheets that will be toggled need to have the attribute data-theme with the value either "light" or "dark", and the dark one is initially disabled:

<!-- Always loaded -->
<link rel='stylesheet' href='$SkinDirUrl/skin.css' type='text/css' />

<!-- Only loaded when the theme is light/default -->
<link rel='stylesheet' href='$SkinDirUrl/light.css' type='text/css' data-theme="light" />

<!-- Only loaded when the theme is dark, initially disabled -->
<link rel='stylesheet' href='$SkinDirUrl/dark.css' type='text/css' data-theme="dark" disabled />

Custom skin template

In the skin template, you can insert something like this at an appropriate position:

<span class="pmToggleDarkTheme" title="$[Toggle dark theme]"></span>
Or:
<span class="pmToggleDarkTheme" title="$[Toggle dark theme]"> $[Dark theme]</span>

Note that the first example has an empty element; the icon defined in .pmToggleDarkTheme:before{} will appear inside it. In the second example the element will display Dark theme with the icon before the label.

Wiki markup in page, header, footer, sidebar

If you prefer adding the toggle icon or label in a wiki page, just use the wikistyle %pmToggleDarkTheme%:

* %pmToggleDarkTheme% %% (empty wikistyle, icon only)
* %pmToggleDarkTheme% $[Dark theme] %% (with label)
  • (empty wikistyle, icon only)
  • Dark theme (with label)

You can add this in Site.SideBar, Site.PageActions, or for example in a skin header wiki page.

Any element with the class name "pmToggleDarkTheme" will toggle the dark theme.

In a wiki page, you can use the class names (wikistyles) %onlyLightTheme% and %onlyDarkTheme% to indicate parts of the text to be shown only when a theme is enabled:

* Welcome to the %onlyLightTheme% LIGHT %onlyDarkTheme% DARK %% theme!
* %item orange onlyLightTheme% Item shows when light
* %item yellow onlyDarkTheme% Item shows when dark
  • Welcome to the LIGHT DARK theme!
  • Item shows when light
  • Item shows when dark

Images

On a dark theme, images with white or very light backgrounds may appear too bright, and images with transparent backgrounds and black or very dark lines or text may appear too dark.

One approach is to prepare separate pictures that look better on the dark theme. With PmWiki 2.3.32, wiki administrators can enable a suffix for pictures to be shown when the dark theme is active:

$ImgDarkSuffix = '-dark';

On the wiki, when using Attach:my-picture.png, if there is another uploaded picture "my-picture-dark.png" the latter will be shown on the dark theme.

I don't recommend enabling the $ImgDarkSuffix variable in the skin -- this is better left to be enabled by the wiki administrators.

A second approach may work for monochrome pictures (black on white or transparent). A skin author may define styles to invert the picture when on the dark theme, or a wiki admin in pub/css/local.css:

@media screen {
  html.pmDarkTheme #wikitext    .dark-image-invert  img { filter: invert(.928); }
  html.pmDarkTheme #wikihead .dark-image-invert  img,
  html.pmDarkTheme #wikisidebar .dark-image-invert  img,
  html.pmDarkTheme #wikifoot .dark-image-invert  img { filter: invert(.928); }
  html.pmDarkTheme .dark-image-invert-100 img { filter: invert(1); } /*100%*/
}

Then in the wiki page, wrap the monochrome picture in the >>dark-image-invert<< wikistyle.

>>dark-image-invert<<
Attach:MonochromePic.png

Or a small inline icon Attach:icon.png within text.
>><<

The invert() values defined above match an inverted white to the background of the wiki elements in the PmWiki-responsive skin.

Notes

See PITS:01497 (Dark color theme) for a discussion or to report any problems.

A recent browser with JavaScript and localStorage enabled is needed; localStorage may be unavailable if the browser is configured to reject cookies.

The dark theme cannot be enabled by default, and a browser/OS preference is not detected (yet). The theme is toggled per-user and the user choice should be remembered by the browser on subsequent visits.

If a wiki extensively uses WikiStyles directly setting colors and backgrounds (instead of CSS class names), these styles may not look great on the dark theme. For best experience and easier maintenance, in your wikistyles use CSS class names that can be redefined in the stylesheet.

Change log / Release notes

  • 20240123 Added $EnableDarkThemeToggle.
  • 20240122 Added section Core functions, update Notes.
  • 20240121 Added section Syntax highlighting, Separate stylesheets per color theme, update CSS.
  • 20231220 First draft.

See also

Contributors

  • Written and maintained by Petko.

Comments

See discussion at DarkColorScheme-Talk

User notes? : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.