Frontend Development 28 min read

Building a Canvas‑Based Rich Text Editor Similar to Word

This tutorial walks through creating a lightweight, canvas‑driven rich‑text editor that mimics Word’s layout and editing features, covering data structures, page rendering, text measurement, line calculation, cursor handling, keyboard input, deletion, line breaks, and selection using plain JavaScript and HTML5 canvas.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Building a Canvas‑Based Rich Text Editor Similar to Word

The article introduces a canvas‑based approach to building a rich‑text editor, contrasting it with typical DOM‑based implementations that rely on the DOM . It starts by defining a JSON data model where each character is stored with style attributes such as value , color , size , bold , italic , etc.

A CanvasEditor class is created, initializing container, data, and options like page dimensions, padding, and line height. The createPage method generates a canvas element for each page, and renderPagePaddingIndicators draws the four corner guides.

Row computation is performed in computeRows , where a temporary canvas measures each character using ctx.measureText . The method records width, height (including actualBoundingBoxAscent and actualBoundingBoxDescent ), original height, and maximum descent to support vertical centering and line‑height scaling.

During rendering, renderRow draws background, underline, strikethrough, and the text itself, adjusting the y‑coordinate to vertically center characters based on the calculated heights. The cursor is rendered as a thin div positioned with setCursor , and its blinking is handled by a timer.

Keyboard interaction is managed through a hidden textarea for focus. The onInput handler inserts typed characters (preserving the style of the surrounding element), while onKeydown processes backspace ( delete ) and Enter ( newLine ) to modify the JSON data and re‑render the view.

Selection is implemented by tracking mouse down, move, and up events. The current selection range is stored in this.range , and renderRow paints a semi‑transparent rectangle over elements whose indices fall within the computed range, using rangeColor and rangeOpacity . The editor also hides the cursor when a selection exists and clears the selection when the cursor is set.

Finally, the article notes that while basic editing, styling, cursor, and selection are functional, many advanced features such as copy/paste, arrow‑key navigation, drag‑and‑drop, images, tables, and links remain to be implemented for a production‑ready editor.

frontendJavaScriptCanvasRich Text Editortext renderingHTML5
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.