Skip to content

fix: make syntax highlighting readable in dark mode - #17

Merged
magnus-madsen merged 1 commit into
masterfrom
fix/dark-mode-syntax-highlighting
Aug 8, 2026
Merged

fix: make syntax highlighting readable in dark mode#17
magnus-madsen merged 1 commit into
masterfrom
fix/dark-mode-syntax-highlighting

Conversation

@magnus-madsen

Copy link
Copy Markdown
Member

Code blocks rendered as a light #f6f7f6 panel with black text on the dark page background.

Causes

1. highlight.css was a hard-coded light Base16 palette. Its .hljs rule (specificity 0-1-0) beat tabi's pre code { background: transparent } (0-0-2), so the light panel won in both themes. There was no prefers-color-scheme or [data-theme] variant anywhere in the file, and tabi's own dark syntax theme (_syntax_theme.scss) is inert here because it targets the .z-* classes Zola only emits when highlight_code = true.

2. highlight_fix.css matched nothing. It targeted pre.language-flix, but highlight.js's cssSelector is "pre code" and it adds hljs / language-* to the code element, never the pre. That also left the pre's 1rem inline padding outside the coloured panel, so code sat flush against the box edge.

3. Every block was highlighted as Flix. Zola records the fence language in data-lang, but highlight.js reads a language-* class. Without one it fell back to highlightAuto, and since highlight.js is a custom build carrying only grmr_flix, the Scala, Rust, shell, markdown and plain-text blocks were all lexed with the Flix grammar.

Changes

  • static/highlight.css — retheme tokens onto the Catppuccin variables tabi already defines unconditionally on :root; .hljs becomes background: transparent; color: var(--text). Adds the scopes the Flix grammar emits but the old file never styled (.hljs-literal, .hljs-title.class_).
  • static/highlight_fix.css — drop the dead rule; put the block background on pre via var(--codeblock-bg), which is dark in both themes per tabi's design, plus color: var(--text) so blocks highlight.js skips stay readable.
  • static/highlight_activate.js — copy data-lang to a language-* class, guarded by hljs.getLanguage(); anything without a bundled grammar gets nohighlight.

Verification

Rendered with headless Firefox against zola serve:

  • Dark /blog/design-flaws-in-flix/ — dark panel flush under the FLIX bar, no light box.
  • Palette /blog/taming-impurity-with-polymorphic-effects/ — keywords mauve, numbers peach, strings green.
  • Non-Flix /blog/redundancies-as-compile-time-errors/ — the Scala block is plain and readable; case/as no longer miscoloured as Flix keywords.
  • Light — built with -u http://127.0.0.1:8000 and data-theme flipped to light; code blocks stay dark, matching tabi's own styling.
  • Alignment /blog/effect-systems-vs-print-debugging/ — the // ^^^ empty effect set caret comment still lines up under { }.

Note

The pre background rule is global, so it applies to any <pre> on the site, not only code fences. All current content uses pre solely for code.

🤖 Generated with Claude Code

Code blocks rendered as a light #f6f7f6 panel with black text on the dark
page background. Three separate causes:

- highlight.css was a hard-coded light Base16 palette. Its `.hljs` rule
  (specificity 0-1-0) beat tabi's `pre code { background: transparent }`
  (0-0-2), so the light panel won in both themes. Retheme the tokens using
  the Catppuccin variables tabi already defines on :root, so highlighted
  code matches the theme's own code styling.

- highlight_fix.css targeted `pre.language-flix`, but highlight.js puts its
  classes on the `code` element, never the `pre`. The rule matched nothing.
  Move the background onto `pre`, where it also covers the block's padding
  and applies to blocks highlight.js leaves alone.

- Zola records the fence language in `data-lang`, but highlight.js reads a
  `language-*` class. Without one it auto-detected, and since the bundle
  carries only the Flix grammar, every Scala, shell and plain-text block was
  highlighted as Flix. Tag blocks from `data-lang` and opt the rest out.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@magnus-madsen
magnus-madsen merged commit 297677b into master Aug 8, 2026
2 checks passed
@magnus-madsen
magnus-madsen deleted the fix/dark-mode-syntax-highlighting branch August 8, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant