The @domternal/theme package provides ready-made light and dark themes for the editor, toolbar, bubble menu, and all UI components. Every visual property is a CSS custom property, so you can customize anything by overriding a single variable.
pnpm add @domternal/theme
Import the theme in your application entry point:
// JavaScript/TypeScript bundler (Vite, Webpack, esbuild)
import ' @domternal/theme ' ;
< link rel = " stylesheet " href = " node_modules/@domternal/theme/dist/domternal-theme.css " />
The package exports multiple entry points:
Import Path Description @domternal/themedist/domternal-theme.cssDefault: compiled CSS @domternal/theme/cssdist/domternal-theme.cssExplicit CSS import @domternal/theme/scsssrc/index.scssSCSS source (for Sass pipelines)
Light mode is the default. Dark mode is activated by adding a CSS class to the editor or any ancestor element.
Class Behavior (none) Light theme (default) dm-theme-darkDark theme, always dm-theme-lightLight theme, always (use to force light inside a dark context) dm-theme-autoFollows the user’s system preference via prefers-color-scheme
< div class = " dm-theme-dark " >
< div class = " dm-toolbar " > ... </ div >
< div class = " dm-editor " > ... </ div >
<!-- Follows system preference -->
< div class = " dm-theme-auto " >
< div class = " dm-toolbar " > ... </ div >
< div class = " dm-editor " > ... </ div >
<!-- Force light inside a dark page -->
< div class = " dm-theme-light " >
< div class = " dm-toolbar " > ... </ div >
< div class = " dm-editor " > ... </ div >
document . body . classList . toggle ( ' dm-theme-dark ' );
Or use dm-theme-auto and let the OS handle it.
Override any CSS custom property on .dm-editor, .dm-toolbar, or any parent element:
/* Custom accent color */
--dm-accent-hover : # be123c ;
--dm-accent-surface : rgba ( 225 , 29 , 72 , 0.1 );
/* Custom editor appearance */
--dm-editor-border-radius : 0 ;
--dm-editor-shadow : none ;
--dm-toolbar-bg : # fef9c3 ;
--dm-button-size : 2.25 rem ;
Since CSS custom properties cascade, you can set them on any ancestor and they flow down to all editor components.
All properties are defined on .dm-editor unless noted otherwise. Light values are the defaults. Dark values are applied when dm-theme-dark or dm-theme-auto (in dark mode) is active.
These are the core design tokens that other properties reference via var().
Property Light Dark Description --dm-bg#ffffff#1e1e1eBase background --dm-text#1a1a1a#e0e0e0Base text color --dm-muted#999999#777777Secondary/muted text --dm-surface#f8f9fa#2a2a2aElevated surface background --dm-border-color#e5e7eb#3a3a3aBorder color --dm-hoverrgba(0,0,0,0.04)rgba(255,255,255,0.08)Hover state background --dm-activergba(0,0,0,0.1)rgba(255,255,255,0.15)Active state background --dm-accent#2563eb#60a5faPrimary accent (blue) --dm-accent-hover#1d4ed8#93c5fdAccent on hover --dm-accent-surfacergba(37,99,235,0.1)rgba(96,165,250,0.15)Accent tint background --dm-focus-colorrgba(66,133,244,0.3)rgba(96,165,250,0.3)Focus ring color --dm-selectionrgba(66,133,244,0.2)rgba(96,165,250,0.25)Text selection color --dm-code-surface#f0f0f0#2d2d2dCode background surface --dm-code-colorinheritinheritCode text color
Property Default Description --dm-editor-bgvar(--dm-bg)Editor background --dm-editor-textvar(--dm-text)Editor text color --dm-editor-font-familySystem font stack Font family --dm-editor-font-size1remBase font size --dm-editor-line-height1.6Line height --dm-editor-padding1remContent padding --dm-editor-border1px solid var(--dm-border-color)Border --dm-editor-border-radius0.75remCorner radius --dm-editor-focus-ringnoneFocus ring (override for custom, e.g., 0 0 0 2px var(--dm-focus-color)) --dm-editor-shadow0 1px 3px rgba(0,0,0,0.04), 0 1px 2px rgba(0,0,0,0.02)Box shadow
Property Default Description --dm-placeholder-colorvar(--dm-muted)Placeholder text color
Property Default Description --dm-link-colorvar(--dm-accent)Link color --dm-link-hover-colorvar(--dm-accent-hover)Link hover color
Property Default Description --dm-code-bgvar(--dm-code-surface)Inline code background --dm-code-textvar(--dm-code-color)Inline code text color --dm-code-font"SF Mono", "Fira Code", Consolas, "Liberation Mono", Menlo, monospaceMonospace font --dm-code-border-radius0.25remInline code corner radius
Property Default Description --dm-code-block-bgvar(--dm-code-surface)Code block background --dm-code-block-textvar(--dm-text)Code block text color
Used by Code Block Lowlight for highlight.js token colors.
Property Light Dark Description --dm-syntax-keyword#c72031#ff7b72Keywords, types --dm-syntax-entity#6f42c1#d2a8ffFunctions, class names --dm-syntax-constant#005cc5#79c0ffConstants, numbers --dm-syntax-string#032f62#a5d6ffStrings, regex --dm-syntax-variable#d35400#ffa657Variables, built-ins --dm-syntax-comment#57606a#8b949eComments --dm-syntax-tag#22863a#7ee787HTML/XML tags --dm-syntax-addition#22863a#aff5b4Diff additions --dm-syntax-addition-bg#f0fff4#033a16Diff addition background --dm-syntax-deletion#b31d28#ffdcd7Diff deletions --dm-syntax-deletion-bg#ffeef0#67060cDiff deletion background
Property Light Dark Description --dm-blockquote-border3px solid #6a6a6a3px solid #555555Left border --dm-blockquote-color#6a6a6a#a0a0a0Text color
Property Default Description --dm-hr-colorvar(--dm-border-color)Rule color
Property Default Description --dm-table-border1px solid var(--dm-border-color)Cell border --dm-table-header-bgvar(--dm-surface)Header cell background --dm-table-selected-bgrgba(66, 133, 244, 0.15)Selected cell background
Property Light Dark Description --dm-highlight-bg#fff3cdrgba(255, 243, 205, 0.2)Default highlight background (used by ==text== input rule)
Property Default Description --dm-mention-bgvar(--dm-accent-surface)Mention background --dm-mention-colorvar(--dm-accent)Mention text color --dm-mention-border-radius0.25remMention corner radius
Property Default Description --dm-details-border1px solid var(--dm-border-color)Details border --dm-details-bgvar(--dm-surface)Summary background --dm-details-summary-font-weight600Summary text weight
Defined on .dm-toolbar:
Property Default Description --dm-toolbar-bgvar(--dm-bg, #ffffff)Toolbar background --dm-toolbar-bordernoneToolbar border --dm-toolbar-padding0.375rem 0.5remToolbar padding --dm-toolbar-gap0.125remGap between items --dm-toolbar-border-radius0.75rem 0.75rem 0 0Toolbar corner radius
Defined on .dm-toolbar:
Property Default Description --dm-button-size2remButton width and height --dm-button-border-radius0.375remButton corner radius --dm-button-colorvar(--dm-text, #374151)Button icon/text color --dm-button-hover-bgvar(--dm-hover)Button hover background --dm-button-active-bgvar(--dm-accent-surface)Active button background --dm-button-active-colorvar(--dm-accent)Active button icon color --dm-button-disabled-opacity0.35Disabled button opacity
Defined on .dm-toolbar:
Property Default Description --dm-separator-colorvar(--dm-border-color)Separator color --dm-separator-margin0.375remSeparator vertical margin
The theme styles these CSS classes. Use them when building custom UI or vanilla JS editors.
Class Description .dm-editorMain editor wrapper. Defines all design tokens. Must have position: relative (set by theme). .dm-editor .ProseMirrorThe contenteditable area. Inherits editor tokens. .dm-toolbarToolbar container. Flex layout with grouped buttons. .dm-toolbar-groupGroup of related toolbar buttons. .dm-toolbar-buttonIndividual toolbar button. .dm-toolbar-separatorVertical separator between button groups. .dm-toolbar-dropdown-panelDropdown panel (headings, font family, colors). .dm-toolbar-dropdown-itemItem inside a dropdown panel.
Class Description .dm-bubble-menuInline formatting toolbar (appears on text selection). Compact button sizing. .dm-floating-menuBlock-level menu (appears on empty lines). .dm-link-popoverURL input popover for links. .dm-image-popoverURL input popover for images.
Class Description .mentionInline mention node. .dm-mention-suggestionMention autocomplete dropdown. .dm-emoji-pickerEmoji picker panel. .dm-emoji-suggestionEmoji autocomplete dropdown. .dm-color-paletteColor grid for text color and highlight pickers. .dm-image-resizableResizable image wrapper with handles. .invisible-charInvisible character indicator (paragraph marks, spaces).
Class Description .dm-table-containerWrapper for table handles and content. .dm-table-col-handleColumn selection handle. .dm-table-row-handleRow selection handle. .dm-table-cell-handleCell corner handle (opens cell toolbar). .dm-table-cell-toolbarFloating toolbar above selected cells. .dm-table-controls-dropdownDropdown for table operations.
Class Description .ProseMirror-selectednodeOutline on selected atom nodes (images, horizontal rules). Uses --dm-accent. .ProseMirror-gapcursorAnimated blinking cursor in gap positions. .selectedCellBackground overlay on selected table cells. Uses --dm-table-selected-bg. .is-emptyAdded to empty nodes for placeholder display. .is-editor-emptyAdded to the editor when the document is empty. .has-focusAdded by the Focus extension to the focused node. .is-openAdded to open details/accordion elements.
You don’t need @domternal/theme to use Domternal. The editor works without any styles. You can build everything from scratch.
At minimum, ProseMirror requires these styles to function correctly:
/* ProseMirror content area */
.dm-editor .ProseMirror {
white-space : break-spaces;
/* Gapcursor (if using Gapcursor extension) */
.dm-editor .ProseMirror-gapcursor {
.dm-editor .ProseMirror-gapcursor::after {
border-top : 1 px solid currentColor ;
animation : ProseMirror-cursor-blink 1.1 s steps ( 2 , start ) infinite ;
@keyframes ProseMirror-cursor-blink {
to { visibility : hidden ; }
.dm-editor .ProseMirror-focused .ProseMirror-gapcursor {
/* Hide selection on drag */
.ProseMirror-hideselection * ::selection {
/* Table column resize handle (if using tables) */
.dm-editor .column-resize-handle {
background-color : # 2563eb ;
The fastest way to customize is to import the default theme and override specific variables:
@import ' @domternal/theme ' ;
--dm-editor-border-radius : 0 ;
--dm-editor-font-family : ' Inter ' , sans-serif ;
--dm-toolbar-bg : # f1f5f9 ;
--dm-toolbar-border-radius : 0 ;
Import the SCSS source and use the theme’s structure:
// Import just the variables and base styles you need
@use ' @domternal/theme/scss ' ;
If building a custom dark theme, override the same semantic tokens:
.my-dark-theme .dm-editor {
--dm-border-color : # 30363d ;
--dm-accent-hover : # 79c0ff ;
--dm-accent-surface : rgba ( 88 , 166 , 255 , 0.15 );
--dm-hover : rgba ( 255 , 255 , 255 , 0.06 );
--dm-active : rgba ( 255 , 255 , 255 , 0.12 );
--dm-code-surface : # 161b22 ;
/* Apply the same tokens to floating UI that escapes the editor */
.my-dark-theme .dm-toolbar ,
.my-dark-theme .dm-bubble-menu ,
.my-dark-theme .dm-emoji-picker ,
.my-dark-theme .dm-mention-suggestion ,
.my-dark-theme .dm-table-controls-dropdown {
--dm-border-color : # 30363d ;
--dm-hover : rgba ( 255 , 255 , 255 , 0.06 );
Caution
Some floating elements (link popover, image popover) use position: fixed and are appended directly to the DOM, outside the .dm-editor wrapper. The default theme includes hardcoded dark overrides for these. If building a fully custom dark theme, you may need to style .dm-link-popover and .dm-image-popover separately.
The theme is composed of SCSS partials:
File Description _variables.scssAll CSS custom property definitions _base.scss.dm-editor wrapper styles, fade-in animation_content.scssContent typography (headings, lists, links, code, images) _prosemirror.scssProseMirror required styles (gapcursor, selected nodes, tables) _toolbar.scssToolbar, buttons, dropdowns, separators _bubble-menu.scssCompact bubble menu _floating-menu.scssFloating menu _link-popover.scssLink URL input popover _color-palette.scssColor grid for text color and highlight pickers _mention.scssMention nodes and suggestion dropdown _image.scssResizable images, handles, image popover _details.scssAccordion/details with CSS grid toggle _placeholder.scssPlaceholder text _task-list.scssTask list with checkboxes _invisible-chars.scssInvisible character indicators _syntax.scssSyntax highlighting for code blocks _emoji-picker.scssEmoji picker and suggestions _table-controls.scssTable handles, cell toolbar, dropdowns themes/_light.scssLight theme class and mixin themes/_dark.scssDark theme class, auto mode, and mixin