Scratch – text colour modes

Continuing my incremental NetNewsWire theme build. Version 2 Font size made the theme responsive to font size settings. Today’s effort maintains the aim of respecting people’s choices. This time with colour mode.

Opting into dark mode with color-scheme

MacOS and iOS provide system level dark/light modes. Applying the currently selected mode to the content is a good starting point for a theme.

We can use CSS color-scheme to say we’re ready to use either light or dark modes. (To apply to everything in the viewport, I’m using :root instead of html here out of habit mostly):

:root {
	color-scheme: light dark;
}

Then when we use the Canvas and CanvasText system-color keywords, they will adopt the text or background colours corresponding to the current dark/light mode.

body {
	color: CanvasText;
	background-color: Canvas;
}

This works. Dark text on white background, then with dark mode applied, white text on dark background.

Contrast good, more contrast better?

Safari, and by extension the web view in NetNewsWire, uses a very dark grey #1e1e1e instead of black for CanvasText (or Canvas in dark mode). Regardless, when contrasted with white, the resulting contrast is a very high 16.67:1 ratio.

Personally I find myself with an afterimage superimposed on my vision after spending time reading with a very high contrast dark mode. To mitigate this effect I want to reduce the contrast somewhat. To ensure I was not reducing to the extent someone might have difficulty reading it I checked the Web Content Accessibility Guidelines.

Success Criterion 1.4.6 Contrast (Enhanced) suggests a minimum contrast ratio of 7:1 is expected for regular sized text. As this is a Level AAA success criterion, I can feel additional certainty that keeping within this contrast ratio will avoid issues associated with sufficient contrast.

Mixing system colours with color-mix

To preserve the convenience of the magic of system colours I’m combining them with color-mix:

body {
	color: color-mix(in oklab, CanvasText var(--color-contrast), Canvas);
	background-color: Canvas;
}

Defining the mix percentage of CanvasText as a variable allowed me to readily pull it to the top as a configuration. 65% resulted in the 7:1 contrast ratio I was aiming for.

:root {
	color-scheme: light dark;
	--color-contrast: 65%;
}

OddContrast together with a colour picker proved useful for checking the ratio.

Toning down the links

The default dark mode links were looking more prominent than necessary to my eye. Their purple colour, which could be the result of inverting the light mode hue, was reminiscent of a visited state. Keeping the link underlines removes the necessity for the links to have colour contrast with the text. I want the links to pop just a little. Applying the same “color” to the links with a slightly higher --color-contrast did the trick.

body,
a {
	color: color-mix(in oklab, CanvasText var(--color-contrast), Canvas);
	background-color: Canvas;
}

a {
	--color-contrast: 80%;
}

Using prefers-color-scheme for specific colours

For the actual visited state for the links I want to specify a specific colour for dark and light modes individually. This is easily done by setting the default (for light mode) and overriding it using prefers-color-scheme in a media query. Like so:

:root {
	--visited-link-color: oklch(50.3% 0.282 295);
}

@media (prefers-color-scheme: dark) {
	:root {
		--visited-link-color: oklch(84.1% 0.09855 303);
	}
}

a:visited {
	color: var(--visited-link-color);
}

I find the system-color elegant, however there is no reason to not specify all colours using the media query override approach.

There’s another CSS tool I haven’t used here that might be handy. Check out light-dark

Install

To enable a quick switch between different versions of this theme I’ve generated a zip of each version – incorporating the version number in the name:

Get the latest version on the Scratch project page.

Next up

The typography is begging for attention. While I think about how to dice up that task, I reckon I’ll tackle the much too frequently seen sideways scroll bar.

At some point I ought to consider a dark mode on this site too.