Changing the Fonts

v1.0

Doku uses two typefaces, and each is reached through a single custom property, so swapping them is a two-line override:

css
:root {
    --font-sans: "Your Face", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    --font-mono: "Your Mono", "JetBrains Mono", monospace;
}

Put that in a child theme stylesheet, or in Appearance > Customize > Additional CSS if you would rather not build one. Additional CSS is one of the settings the Doku Options box can override per entry, so a single landing page can carry a different face from the rest of the site.

Why there is no font picker in the Customizer. Doku ships DM Sans and DM Mono as local .woff2 files in doku/assets/fonts/, declared in doku/assets/css/fonts.css, and fetches nothing from Google Fonts or any other third party. Every entry in a font list would be either a third-party request on every page load or a file you have to host yourself anyway — and hosting it yourself is what the rest of this page covers.

--font-mono is not only code. Every article heading, h1 through h6, and the site title in the header are set in the mono face, alongside code blocks, inline code, the code block’s filename and language chrome, and keyboard keys. Changing it changes the look of every heading on every page, which is usually the point, but look at a doc page and not just a code sample after you do.

Hosting the font yourself

Put the .woff2 files in your child theme and declare them above the override:

css
@font-face {
    font-family: "Your Face";
    font-style: normal;
    font-weight: 100 900;  /* one variable file covers every weight */
    font-display: swap;
    src: url("fonts/your-face.woff2") format("woff2");
}

The interface uses weights 400, 500, 600 and 700, and article text uses italics. A variable font covers all of that in one file. With static fonts, ship an @font-face per weight and one for italic, or the browser will synthesize the ones you leave out — a slanted upright and a smeared bold, which is what an interface looks like when the weights are uneven for no visible reason.

font-display: swap matches what Doku’s own faces use: text paints immediately in the fallback and is repainted when the file arrives, rather than staying invisible while it downloads.

Loading a font with @import url("https://fonts.googleapis.com/...") does work, and it puts a third-party request back on every page load — the one thing the theme is built to avoid, and, in the EU, the part of Google Fonts that has caused site owners trouble. Download the files and serve them from your own domain instead.

You do not need to remove DM Sans or DM Mono. A @font-face rule downloads nothing until something on the page asks for that family, so once both properties point elsewhere the bundled files are simply never fetched.

Matching the editor

The block editor loads blocks.css rather than main.css, so it does not see a :root rule written for the front end. To make the editing canvas match, add your stylesheet to it from a functions.php in the child theme — the one thing a child theme needs a functions.php for, since the stylesheet itself is picked up without one:

php
add_action( 'after_setup_theme', function () {
    add_editor_style( 'style.css' );
} );

Two numbers tuned to the shipped faces

  • The default reading width of 760px puts roughly 90 characters of body text on a line in DM Sans. A face with a wider or narrower average character sets a different count at the same width, so read a paragraph after switching, and adjust Appearance > Customize > Doku Options > Layout > Content width if the lines have grown long. Shorter lines are easier to read than longer ones; anything past about 90 characters is worth narrowing.
  • --text-code is 13.5px, half a pixel above the interface size, because DM Mono renders optically smaller than DM Sans at the same nominal size. Another mono may not need that compensation — set it to 13px if your code sits too large beside the text around it.

Was this page helpful?