WYSIWYG Markdown Editor for Mobile & Desktop Apps – OverType

Category: Javascript , Recommended , Text | September 5, 2025
Authorpanphora
Last UpdateSeptember 5, 2025
LicenseMIT
Views235 views
WYSIWYG Markdown Editor for Mobile & Desktop Apps – OverType

OverType is a lightweight markdown editor library that provides a WYSIWYG markdown editing experience using an invisible textarea overlay.

Most Markdown editors rely on contentEditable or complex CodeMirror implementations that introduce compatibility issues and performance overhead.

OverType takes a different approach by layering a transparent textarea over styled markdown preview.

This gives the illusion of editing rich text directly while preserving all the native browser behaviors of a standard textarea, like spellcheck, undo/redo, and superior mobile keyboard support.

Features

  • Global theming: Comes with ‘Solar’ (light) and ‘Cave’ (dark) themes that you can apply to all instances or customize.
  • Keyboard shortcuts: Includes common shortcuts like Cmd/Ctrl+B for bold and Cmd/Ctrl+I for italic.
  • Mobile optimized: The design is responsive and includes mobile-specific styles for a great experience on any device.
  • DOM persistence aware: It can recover its state from an existing DOM, which is useful for platforms like HyperClay.
  • Optional toolbar: A clean, minimal toolbar provides essential formatting options.
  • Smart list continuation: Automatically continues numbered or bulleted lists when you press Enter, similar to GitHub.
  • Framework agnostic: Works with vanilla JavaScript, React, Vue, and more without specific bindings.

How to use it:

1. Install & download OverType with NPM.

# NPM
$ npm install overtype

2. Import the OverType into your project:

import OverType from "overtype";
// OR
<script type="module">
import OverType from "../dist/overtype.esm.js";
</script>
// OR
<script src="/dist/overtype.min.js"></script>
<!-- Or from a CDN -->
<script src="https://unpkg.com/overtype/dist/overtype.min.js"></script>

3. Create a DIV container for the Markdown editor.

<div id="editor"></div>

4. Create a single editor instance with default configuration.

// ES Module
const [editor] = new OverType('#editor', {
  // options here
});
// Browser
const OT= window.OverType.default || window.OverType;
const [editor] = new OT('#editor', {
  // options here
});

5. Customize the Markdown editor with the following options.

  • fontSize: Sets the font size for the editor (e.g., '14px').
  • lineHeight: Defines the line height as a unitless value (e.g., 1.6).
  • fontFamily: Specifies the font family. A monospace font is required for proper alignment.
  • padding: Sets the inner padding of the editor (e.g., '16px').
  • theme: Applies a theme. Can be a string ('solar' or 'cave') or a custom theme object.
  • colors: An object to override specific colors of the current theme.
  • mobile: An object containing responsive styles (fontSize, padding, lineHeight) for screens 640px or narrower.
  • autofocus: A boolean that, if true, focuses the editor on initialization.
  • placeholder: Sets the placeholder text for an empty editor.
  • value: A string to set the initial markdown content.
  • autoResize: A boolean that, if true, makes the editor’s height expand and shrink with the content.
  • minHeight: The minimum height for the editor when autoResize is enabled.
  • maxHeight: The maximum height for the editor when autoResize is enabled.
  • textareaProps: An object of HTML attributes to apply to the underlying textarea (e.g., { name: 'content', required: true }).
  • toolbar: A boolean that, if true, displays the formatting toolbar.
  • smartLists: A boolean that, if true, enables GitHub-style automatic list continuation.
  • showStats: A boolean that, if true, shows the character, word, and line count bar.
  • statsFormatter: A function to customize the format of the text in the stats bar.
  • onChange: A callback function that runs whenever the editor’s content changes.
  • onKeydown: A callback function that runs on any keydown event inside the editor.
const [editor] = new OverType('#editor', {
  // Typography
  fontSize: '14px',
  lineHeight: 1.6,
  /* System-first, guaranteed monospaced; avoids Android 'ui-monospace' pitfalls */
  fontFamily: '"SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Code", Consolas, "Roboto Mono", "Noto Sans Mono", "Droid Sans Mono", "Ubuntu Mono", "DejaVu Sans Mono", "Liberation Mono", "Courier New", Courier, monospace',
  padding: '16px',
  
  // Mobile styles
  mobile: {
    fontSize: '16px',  // Prevent zoom on iOS
    padding: '12px',
    lineHeight: 1.5
  },
  
  // Native textarea properties
  textareaProps: {},
  
  // Behavior
  autofocus: false,
  autoResize: false,  // Auto-expand height with content
  minHeight: '100px', // Minimum height for autoResize mode
  maxHeight: null,    // Maximum height for autoResize mode (null = unlimited)
  placeholder: 'Start typing...',
  value: '',
  
  // Callbacks
  onChange: null,
  onKeydown: null,
  
  // Features
  showActiveLineRaw: false,
  showStats: false,
  toolbar: false,
  statsFormatter: null,
  smartLists: true  // Enable smart list continuation
});

6. Instance methods:

  • getValue(): Returns the current markdown content as a string.
  • setValue(markdown): Sets the content of the editor.
  • getRenderedHTML(process): Returns the content as HTML. If process is true, the HTML is cleaned up for display.
  • getPreviewHTML(): Returns the exact inner HTML of the preview layer.
  • setTheme(theme): Changes the editor’s theme dynamically.
  • showPlainTextarea(visible): A boolean to toggle the plain textarea view.
  • showPreviewMode(visible): A boolean to toggle the read-only preview mode.
  • focus(): Programmatically focuses the editor.
  • blur(): Programmatically removes focus from the editor.
  • showStats(visible): A boolean to dynamically show or hide the stats bar.
  • isInitialized(): Returns true if the editor has been initialized.
  • reinit(options): Re-initializes an existing editor with a new configuration object.
  • destroy(): Removes the editor instance and its associated event listeners.

7. Static Methods:

  • setTheme(theme, overrides): Sets a global theme for all current and future OverType instances.
  • init(target, options): Initializes one or more editors on the given target element(s).
  • getInstance(element): Retrieves the editor instance associated with a specific DOM element.
  • destroyAll(): Destroys all active OverType instances on the page.
  • themes: An object providing access to the built-in theme configurations (OverType.themes.solar).

FAQs:

Q: Why doesn’t OverType support images in markdown?
A: Images would break the character alignment system that makes the invisible textarea overlay work. Variable-height images would cause the textarea cursor position to misalign with the visual preview, disrupting the editing experience. This limitation enables the library’s core benefits: perfect native behavior and tiny size.

Q: Can I use custom fonts or variable-width fonts?
A: No, OverType requires monospace fonts to maintain character alignment between the textarea and preview layers. Variable-width fonts would cause cursor drift where the textarea position doesn’t match the visual text position. This constraint is fundamental to the overlay architecture.

Q: What happens when I need to display the markdown as HTML elsewhere?
A: OverType provides multiple HTML export methods. Use getRenderedHTML() for basic HTML output, getRenderedHTML(true) for post-processed HTML with consolidated lists and code blocks, or getPreviewHTML() to get exactly what the editor displays.

Related Resources:

Changelog:

v1.2.4 (09/05/2025)

  • Ensures tooltip remains visible even with aggressive parent styles
  • Bugfixes

You Might Be Interested In:


Leave a Reply