DocBook themes

Volume 4, Issue 38; 03 Aug 2020

Adding support for dark mode as an aid to accessibility.

Once upon a time, browsers made it (relatively) easy to specify custom (CSS) stylesheets. That meant users could decide what colors and contrasts made reading easiest for them. Not so anymore. I expect that advertisers objected to users’ ability to “change their brand”, but perhaps I’m just being cynical.

Dark mode (which I don’t personally use) is more than just a preference, it’s an accessibility feature. On that basis, I wanted to explore whether or not I could make the DocBook xslTNG Stylesheets support dark mode.

Step one was rolling up my sleeves and trying to do something rational with the color selection. I’m no graphic designer, but I did what I could. I searched around a fair bit for resources to help me understand how to design a color theme. Eventually, I arrived at the documentation for Material Design.I make no assertions about the relative merits of the material design approach over other approaches. I’d welcome suggestions for other styles to investigate. It was simply the first set of guidelines that I found that seemed both reasonably comprehensive and accessible to someone with my small amount of design and color sense. I reworked the CSS so that all the colors are based on a palette:

  /* The default theme. */
  --background-color: #fffff8;
  --surface-color: #fffff8;
  --primary-color: #7f7f7f;
  --primary-variant-color: #5f5f5f;
  --secondary-color: #ffbc42;
  --error-color: #ffafaf;
  --error-border-color: #b00020;
  --on-background-color: #000000;
  --on-surface-color: #000000;
  --on-primary-color: #ffffff;
  --on-primary-variant-color: #ffffff;
  --on-secondary-color: #000000;
  --on-error-color: #000000;
  --enabled-color: rgb(240,240,240);
  --hovered-color: rgb(235,235,235);
  --focused-color: rgb(221,221,221);
  --modal-overlay-color: rgba(255,255,255,0.85);

That’s mostly the same as the previous colors. I’ve substituted primary and secondary colors for the previously ad hoc “green” and “yellow” colors used in a few places.

Next, I did my best to code up the “dark” material design:

  /* Dark */
  --background-color: #121212;
  --surface-color: #121212;
  --primary-color: #bb86fc;
  --primary-variant-color: #3700b3;
  --secondary-color: #03dac6;
  --error-color: #cf6679;
  --error-border-color: #b00020;
  --on-background-color: #ffffff;
  --on-surface-color: #ffffff;
  --on-primary-color: #000000;
  --on-primary-variant-color: #ffffff;
  --on-secondary-color: #000000;
  --on-error-color: #000000;
  --enabled-color: rgb(44,33,56);
  --hovered-color: rgb(49,38,63);
  --focused-color: rgb(63,51,74);
  --modal-overlay-color: rgba(18,18,18,0.85);
  --keycap-box-shadow: 1px 1px 1px 0px rgba(255,255,255,0.75);

and the “light” material design:

  /* Light */
  --background-color: #ffffff;
  --surface-color: #ffffff;
  --primary-color: #6200ee;
  --primary-variant-color: #3700b3;
  --secondary-color: #03dac6;
  --error-color: #b00020;
  --error-border-color: #cf6679;
  --on-background-color: #000000;
  --on-surface-color: #000000;
  --on-primary-color: #ffffff;
  --on-primary-variant-color: #ffffff;
  --on-secondary-color: #000000;
  --on-error-color: #ffffff;
  --enabled-color: rgb(240,240,240);
  --hovered-color: rgb(235,235,235);
  --focused-color: rgb(221,221,221);
  --modal-overlay-color: rgba(255,255,255,0.85);

Finally, I added some JavaScript to allow a user to switch between them. That’s kind of bogus from an accessibility point of view, but I haven’t thought up a better answer.

The JavaScript uses the HTML “local storage” feature to make the users choice persistent. It’s possible that there will be a single “flash” on large pages as I haven’t worked out how to make the user style active from the very beginning of rendering.

The whole thing is very much experimental. You can try it out by building the main branch yourself or downloading the docbook-xslTNG-1.3.0a1-SNAPSHOT release. The relevant settings are $v:theme-list to enumerate the themes (you’ll have to update the CSS as well to add more), $theme-picker to enable the theme selection JavaScript controls, and $default-theme to select a default theme. Note that selecting a default theme without enabling theme selection forces the selected theme on all your readers. (All your readers not willing to hack the class attribute on the html element, anyway.)

If you just want to see what it looks like, there’s a sample documentIf you have dark mode selected in your operating system and if your browser makes that information available to JavaScript (and if you have JavaScript enabled, naturally), then that sample document should come up in dark mode by default. Otherwise, it should come up in the new default color scheme. online. The theme selector is the “hamburger menu” in the upper left. (It’s two pages so that the “persistent ToC” coloring can be seen on the second page.)

Comments, suggestions, and more aesthetically pleasing (light and dark) color themes most humbly solicited.


Tks for the example. My personal comments:

  1. I don't see adequate contrast in 'dark' mode?

  2. In both cases, for 'code' elements, how does the colour help with accessibility?

  3. The font size? Suggest base size of 14pt minimum. Looks like 8pt?

  4. The huge blank side panels could (should?) be used for page content?

  5. Requested addition (low vision readers), font base size, 10-24pt?

Thanks for the work Norm.

—Posted by Dave Pawson on 03 Aug 2020 @ 03:32 UTC #

I took the dark mode colors straight from the Materials Design page, so I would have expected the contrast to be adequate. I'm certainly open to different colors if there are better choices. The syntax highlighting isn't directly an accessibility feature, I suppose. We already had syntax highlighting, so I just adjusted the colors to work in the different modes. I'm not sure why you're seeing small fonts. The base size is 13.5pt. In order to improve legibility, there's a maximum line length. That's why you see lots of white space if you have a very wide monitor. (This is a huge improvement, IMHO.) A theme that defaults to much larger fonts is a good idea, thanks!

For the Balisage Proceedings i used filter: invert(100%); but it's in a media selector that's initially disabled, and enabled through javascript, as is the Dark Theme button. I added exceptions for images, for obvious reasons.

A downside to using CSS filters is that support isn't universal (the code checks for support) and also that in desktop firefox using a CSS filter breaks absolute positioning (there are workarounds, and absolute positioning doesn't work o nmobile device browsers generally anyway today).

A slightly lower contrast than white on black is best - people who need high contrast will normally use the operating system's high contrast dark mode (except Apple users, as they don't seem to have one, so people who need it the most presumably won't be using Apple products, although i expect Apple to introduce a dark mode at some point).

Using font-size: 100% uses the browser-configured preferred font size, and keeping sizes and distances in root em units (rem) preserves the relationship, so that's usually what i do.

—Posted by Liam Quin on 05 Aug 2020 @ 06:55 UTC #

Thank you, Liam!

Please provide your name and email address. Your email address will not be displayed and I won’t spam you, I promise. Your name and a link to your web address, if you provide one, will be displayed.

Your name:

Your email:


Do you comprehend the words on this page? (Please demonstrate that you aren't a mindless, screen-scraping robot.)

What is five minus two?  (e.g. six plus two is 8)

Enter your comment in the box below. You may style your comment with the CommonMark flavor of Markdown.

All comments are moderated. I don’t promise to preserve all of your formatting and I reserve the right to remove comments for any reason.