Add a full-featured rich text editor to your website in under 30 seconds.
RTE is a single JavaScript file with no dependencies. It injects its own CSS, creates the toolbar, editor area, export bar, and status bar — all from one <script> tag.
Download rte.js and include it in your project:
<script src="rte.js"></script>
npm install rte-rich-text-editor
Then use it in your project:
// CommonJS
const RTE = require('rte-rich-text-editor');
// ES Modules
import RTE from 'rte-rich-text-editor';
<script src="https://unpkg.com/rte-rich-text-editor/rte.js"></script>
Place rte.js in your static assets directory and reference it with a relative or absolute path.
<!-- 1. Create a container -->
<div id="editor"></div>
<!-- 2. Include the script -->
<script src="rte.js"></script>
<!-- 3. Initialize -->
<script>
const editor = RTE.init('#editor');
</script>
You can also pass a DOM element directly:
const el = document.getElementById('my-editor');
const editor = RTE.init(el);
Pass an options object as the second argument to RTE.init():
const editor = RTE.init('#editor', {
placeholder: 'Write your story...', // Custom placeholder text
height: '400px', // Minimum editor height
});
| Option | Type | Default | Description |
|---|---|---|---|
placeholder | String | "Start typing something amazing..." | Placeholder text shown when the editor is empty |
height | String | null | Minimum height of the editor area (CSS value, e.g. "400px") |
The toolbar is organized into logical groups separated by dividers:
| Group | Controls | Description |
|---|---|---|
| Block Format | Dropdown | Paragraph, H1, H2, H3, H4 |
| Font Family | Dropdown | 9 font families: Arial, Georgia, Times New Roman, Courier New, Verdana, Trebuchet MS, Comic Sans MS, Impact |
| Font Size | Dropdown | 7 size levels from Tiny to Max |
| Inline Format | B I U | Bold, Italic, Underline, Strikethrough, Superscript, Subscript |
| Colors | 🎨 🖍️ | Text color picker, Background highlight picker (40 swatches + custom hex) |
| Alignment | SVG icons | Left, Center, Right, Justify |
| Lists | 📝 🔢 | Bullet list, Numbered list, Indent, Outdent |
| Insert | 🔗 🖼️ 🎬 🔊 😀 📊 | Link, Unlink, Image, Video, Audio, Emoji, Table |
| Block | 💬 💻 ➖ | Blockquote, Code block, Horizontal rule |
| Utility | ↩️ ↪️ 🧹 🗑️ | Undo, Redo, Clear formatting, Clear all |
| Shortcut | Action |
|---|---|
Ctrl+B | Toggle bold |
Ctrl+I | Toggle italic |
Ctrl+U | Toggle underline |
Ctrl+Z | Undo |
Ctrl+Shift+Z | Redo |
Ctrl+Y | Redo |
Ctrl+S | Save as HTML file (download) |
On macOS, use Cmd instead of Ctrl.
Each media type can be inserted in three ways:
Additionally, you can paste images from your clipboard (e.g., screenshots) and they'll be embedded automatically.
Both the text color and highlight pickers offer:
#ff6600), named (tomato), rgb, etc.Select text first, then pick a color. The color is applied to the selection immediately.
Click the 📊 table button to open the visual grid selector. Hover over the grid to choose dimensions (up to 6×6), then click to insert.
Tables are inserted with:
After insertion, click inside any cell to edit its content. Standard text formatting works inside table cells.
The built-in export bar at the bottom of the editor provides one-click access to:
| Button | Description |
|---|---|
Save HTML | Downloads a complete, standalone .html file with embedded styles. Opens correctly in any browser. |
Save Text | Downloads a plain .txt file with just the text content. |
Copy HTML | Copies rich HTML to your clipboard. Paste into Gmail, Google Docs, Word, etc. and formatting is preserved. |
Copy Text | Copies plain text to your clipboard. |
Email | Opens your default email client with the editor content in the email body. |
Print | Opens a styled print preview. Use your browser's "Save as PDF" option to create a PDF. |
JSON | Copies a JSON object to your clipboard containing html, text, wordCount, charCount, and createdAt fields. |
You can also use Ctrl+S to quickly save an HTML file.
RTE provides a full JavaScript API to extract content for saving to your backend. See the API Reference for complete details.
// Get content and POST to your API
document.getElementById('save-btn').addEventListener('click', async () => {
const response = await fetch('/api/documents', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(editor.getJSON())
});
});
// Load saved HTML into the editor
const response = await fetch('/api/documents/123');
const data = await response.json();
editor.setHTML(data.html);
// Auto-save on every change
editor.onChange = (data) => {
console.log(data.words, 'words');
console.log(data.chars, 'characters');
// debounce and save...
};
RTE outputs raw HTML. If your application allows untrusted users to create or edit content, you must sanitize the output server-side before storing or rendering it to other users.
Use a proven HTML sanitizer such as DOMPurify (client-side) or sanitize-html (server-side):
// Server-side (Node.js)
const sanitizeHtml = require('sanitize-html');
const clean = sanitizeHtml(editor.getHTML(), {
allowedTags: sanitizeHtml.defaults.allowedTags.concat(['img', 'h1', 'h2']),
allowedAttributes: { ...sanitizeHtml.defaults.allowedAttributes, img: ['src', 'alt'] },
});
// Client-side
const clean = DOMPurify.sanitize(editor.getHTML());
Your sanitizer should strip or reject:
javascript: links (e.g. <a href="javascript:...">)onclick, onerror, onload, etc.)<script>, <iframe>, <object>, <embed>, and <form> tagsdata: URIs in links (except for embedded images if intended)Never ship API keys in client-side code. Use the aiProxy option to route AI requests through your own server, which keeps the key secret. See the Pro documentation for details.
RTE uses CSS custom properties (variables) on the .rte-wrap element. Override them to match your brand:
.rte-wrap {
--rte-radius: 10px; /* Border radius */
--rte-border: #d0d5dd; /* Border color */
--rte-bg: #ffffff; /* Background */
--rte-toolbar-bg: #f8f9fb;/* Toolbar background */
--rte-hover: #e8ecf1; /* Button hover */
--rte-active: #d4dae3; /* Button active */
--rte-accent: #6366f1; /* Accent / brand color */
--rte-shadow: 0 2px 12px rgba(0,0,0,.08);
--rte-font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
For example, to make the editor match a dark theme:
.rte-wrap {
--rte-bg: #1a1a2e;
--rte-toolbar-bg: #16213e;
--rte-border: #334155;
--rte-hover: #1e3a5f;
--rte-active: #0f3460;
--rte-accent: #e94560;
--rte-shadow: 0 2px 12px rgba(0,0,0,.3);
}
.rte-content { color: #e2e8f0; }
.rte-btn { color: #cbd5e1; }