Skip to content

CSS Theming

A theme-aware SVG export carries no baked-in colors on its shapes. Instead, every bond, label, charge, and annotation is reclassified into a stable set of .mk-* classes, and a single scoped stylesheet inside the file supplies the light palette, the dark palette, and the switching logic. You can restyle the whole drawing from your page with ordinary CSS, using the class system, dark-mode hooks and override patterns described below.

The mk class reference

Structural classes mark the drawing’s machinery. They are plain class rules with no !important, so any host selector can override them.

ClassTargets
mk-bondBond line strokes, including projection bonds and Newman circles
mk-dashDashed (hash) bond lines; the dash pattern stays as an attribute
mk-wedgeSolid wedge fills
mk-wedge-outlineHollow wedge outlines
mk-double-xCrossed double-bond marks
mk-capRounded bond end caps
mk-vertexVertex dots where bonds meet at implicit carbons
mk-aromaticAromatic ring circles
mk-deloc-arcDelocalization arcs
mk-lpLone-pair dots and bars
mk-radicalRadical dots
mk-charge-labelCharge text and the plus/minus strokes inside circled charges
mk-charge-circleThe ring around circled charges
mk-haloThe page-colored halo painted behind atom labels
mk-underlayPage-colored masks that break crossing bonds
mk-fo-textHTML annotation text inside foreignObject blocks (uses color, not fill)
mk-bgThe background rectangle, when background export is enabled
mk-newman-bgThe page-colored circle fill in Newman projections
mk-dflt-fill, mk-dflt-strokeFallback classes for shapes that used the default drawing color

Color classes ride on top of the structural ones. Each element present in the drawing gets a class named after its symbol: mk-C, mk-O, mk-N, and so on, applied to atom label text (which also carries mk-atom), and inherited by that atom’s charges, lone pairs, and radicals. Rules are emitted only for elements present in the drawing. In animated exports, element-coloured symbols inside rich labels (spans in a foreignObject) also get the mk-<Element> class, so one .mk-O override recolours both; see animations. Colors that match no color-scheme entry get a hashed custom class like mk-c0-k3v9, with an automatically derived dark counterpart; the random suffix prevents collisions when several SVGs are inlined on one page.

The !important policy: element and custom color rules carry !important; structural rules do not. The flag exists for multi-embed safety, because several inlined SVGs share page-scoped cascade order and a later file’s generic text rule could otherwise stomp an earlier file’s element colors. The practical consequence is in the recipes below.

How the injected CSS is built

Every rule is scoped to the export’s random root ID, but the ID is wrapped in :where(), which contributes zero specificity. An injected rule for .mk-bond therefore competes as if it were bare .mk-bond, and any host selector with higher specificity wins without fighting an ID. A representative excerpt:

inside the exported <style> block
/* light */
:where(#molkit-a1b2c) .mk-bond { stroke: #000000; }
:where(#molkit-a1b2c) .mk-halo { fill: var(--mk-page-bg, #ffffff); }
:where(#molkit-a1b2c) .mk-O, :where(#molkit-a1b2c) text.mk-O { fill: #ff0000 !important; color: #ff0000 !important; stroke: none; }
/* dark, inside @media (prefers-color-scheme: dark) */
:where(#molkit-a1b2c:not(.mk-light, .mk-light *)) .mk-bond { stroke: #e0e0e0; }
:where(#molkit-a1b2c:not(.mk-light, .mk-light *)) .mk-O, :where(#molkit-a1b2c:not(.mk-light, .mk-light *)) text.mk-O { fill: #ef4444 !important; color: #ef4444 !important; stroke: none; }

The light values come from your active color scheme at export time (see color schemes); gradient bonds keep their gradients, with dark mode remapping the stop colors by attribute selector.

Dark mode: the three-state system

Theme-aware exports resolve dark mode in three states.

  1. Default, follow the OS. The dark palette ships inside a prefers-color-scheme: dark media query and activates with the system setting. This is what you get in an img tag with zero work.
  2. Force dark with the class mk-dark. Add mk-dark to the inlined SVG or any ancestor and the dark palette applies regardless of the OS. The same dark rules are emitted a second time under an .mk-dark ancestry scope, appended last so they win the cascade at equal specificity.
  3. Force light with the class mk-light. Add mk-light to the SVG or any ancestor and the media query is suppressed (its scope selector excludes .mk-light ancestry), so the export stays light even on a dark OS.

A site with its own theme toggle can drive these classes from the toggle, and embedded drawings then follow the site’s theme instead of the OS setting.

site-theme-toggle.html
<button id="theme-toggle">Toggle theme</button>
<div class="content">
<!-- inlined theme-aware Molkit SVGs anywhere below documentElement -->
</div>
<script>
const root = document.documentElement;
let dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
function applyTheme() {
root.classList.toggle('mk-dark', dark);
root.classList.toggle('mk-light', !dark);
// ...flip your site's own theme class here too
}
document.getElementById('theme-toggle').addEventListener('click', () => {
dark = !dark;
applyTheme();
});
applyTheme();
</script>

Animated exports carry the same three hooks. Exports made before the class hooks shipped respond only to the media query; re-export if you need toggle support. See animations for the playback side.

Override recipes

Recolor all bonds. Structural classes have no !important, so one wrapper class of specificity is enough. Cover the fill-based bond classes too:

brand-bonds.css
.figure .mk-bond, .figure .mk-dash, .figure .mk-wedge-outline { stroke: #1e3a5f; }
.figure .mk-wedge { fill: #1e3a5f; stroke: #1e3a5f; }
.figure .mk-cap, .figure .mk-vertex, .figure .mk-double-x { fill: #1e3a5f; }

Recolor one element site-wide. Element rules use !important, so yours must as well, and it must match both the text and stroke variants:

orange-oxygen.css
svg .mk-O, svg text.mk-O { fill: #d97706 !important; color: #d97706 !important; }
svg line.mk-O, svg path.mk-O { stroke: #d97706 !important; }

Remember the export’s dark block also sets these with !important; add a .mk-dark variant of your rule if you want the override to survive forced dark.

Match the page background. Halos and underlays paint with --mk-page-bg, which defaults to white in light mode and a near-black in dark mode (the background rect itself goes transparent in dark mode). If your dark page uses a different background, set the variable so label halos do not show as off-color rectangles:

page-bg.css
.mk-dark svg { --mk-page-bg: #111827; }

Fonts

Theme-aware CSS controls color; text fidelity is a separate axis with four strategies. Full details at font embedding.

StrategyHost page must provideText selectable
Default: a Google Fonts @import is injected for non-local web fonts usedNetwork access to the fonts CDNYes
Embed fonts for offline use: font binaries inlined as data URIsNothingYes
Mobile-safe rendering: a Liberation Sans glyph subset embedded as an Arial-metric fallbackNothingYes
Convert labels to paths: labels become vector outlinesNothingNo

Print

Every export ends with an ID-scoped print block that forces bonds to solid black at a heavier stroke and hides the background rectangle, so drawings print legibly from any page that embeds them.

See also