LumisDocs
Formatters

HTML Multi-Themes Formatter

Options and examples for Lumis multi-theme HTML output using CSS custom properties.

One HTML block that supports multiple themes via CSS custom properties. Useful for light/dark mode.

Options

RuntimeOptions
Rustlanguage, structure, themes, default_theme, css_variable_prefix, pre_class, pre_attrs, code_attrs, include_highlights, highlight_lines, line_numbers, header
Elixirlanguage, structure, themes, default_theme, css_variable_prefix, pre_class, pre_attrs, code_attrs, include_highlights, highlight_lines, line_numbers, header
JavaScript / TypeScriptlanguage, structure, themes, defaultTheme, cssVariablePrefix, preClass, preAttrs, codeAttrs, includeHighlights, highlightLines, lineNumbers, header
JavaNot currently supported in lumis4j
CLI--structure, --themes, --default-theme, --css-variable-prefix, --pre-class, --pre-attr, --no-pre-attr, --code-attr, --no-code-attr, --include-highlights, --highlight-lines, --highlight-lines-class, --highlight-lines-style, --line-numbers, --header-open, --header-close

Use pre_attrs / preAttrs to override the block background, including backgrounds from a named default or light-dark(). See Override the block background.

The override leaves theme variables and token styles intact. If your theme-switching CSS sets the <pre> background with !important, remove that root background rule so the attribute can take effect.

Basic example

import {highlight} from '@lumis-sh/lumis'
import {htmlMultiThemes} from '@lumis-sh/lumis/formatters'
import javascript from '@lumis-sh/wasm-javascript'
import latte from '@lumis-sh/themes/catppuccin_latte'
import frappe from '@lumis-sh/themes/catppuccin_frappe'

const html = await highlight(
  'const x = 1',
  htmlMultiThemes({
    language: javascript,
    themes: {light: latte, dark: frappe},
    defaultTheme: 'light-dark()',
  })
)

cssVariablePrefix

By default, CSS variables are prefixed with --lumis (e.g., --lumis-light, --lumis-dark-bg). Override the prefix if it conflicts with your CSS. Produces variables like --code-light, --code-dark-bg, etc.

const html = await highlight(
  'const x = 1',
  htmlMultiThemes({
    language: javascript,
    themes: {light: latte, dark: frappe},
    cssVariablePrefix: '--code',
  })
)

defaultTheme

Controls what color values appear inline (not just as CSS variables):

ValueBehavior
omitted / nullCSS variables only, no inline colors
"light"Inline colors from the light theme, CSS variables for all themes
"light-dark()"Uses CSS light-dark() to select colors from the element's color-scheme

Lumis leaves color-scheme unset so the output follows the page's theme. Use light dark on the page to follow the OS, or light / dark to select one scheme. To opt just a block into OS switching, set preAttrs: {style: 'color-scheme: light dark;'}; this overrides an inherited light-only or dark-only choice. See Light/Dark Mode for all runtimes and inline code.

What light-dark() covers

CSS light-dark() is a color function, so only color and background-color use it. For font-weight, font-style and text-decoration, a value both themes share is written as an ordinary declaration; a value they disagree on is written as --lumis-light-* and --lumis-dark-* variables with no declaration, since only a rule of your own can switch it. Leaving it out of the style attribute is what keeps that rule from needing !important, see Light/Dark Mode.

Output format

HTML Multi-Themes wraps each line in a span. Tokens carry CSS variables for each configured theme:

<pre class="lumis lumis-themes catppuccin_frappe catppuccin_latte" style="--lumis-light-bg:#eff1f5; --lumis-dark-bg:#303446;"><code class="language-javascript" translate="no" tabindex="0"><span class="l-line" data-line="1"><span style="--lumis-dark:#ca9ee6; --lumis-light:#8839ef;">const</span></span></code></pre>
  • <pre> carries lumis, lumis-themes, and the included themes' names as classes. Theme keys such as light and dark name the CSS variables; they are not added as classes. Custom pre_class / preClass values are appended as usual.
  • <code class="language-*"> identifies the language and keeps the block focusable
  • <span class="l-line" data-line="N"> wraps only a line's content
  • <span class="l-line-number"> opens the line when line_numbers is on, see Line Numbers
  • Lines are separated by \n text nodes; nothing follows the last line element
  • A final source newline ends its line rather than adding an empty numbered line
  • <span style="--lumis-..."> carries per-theme token colors and font styles

With structure: "inline" only the token spans are written, for a <code> or other element of your own. See Inline code.

Line layout and copy protection use inline styles, as in HTML Inline, including when colors are supplied only through variables. See Line layout for the rules if you supply custom CSS.

For CSS or formatters written for line divs, see HTML line markup migration.

Good uses

  • light/dark mode
  • user-selectable theme switching
  • one HTML block shared across themes

On this page