How to Build Your Own Text Editor in the Browser?
A programmer's work is about solving problems. Programming languages are our tools. By using them we can create new solutions, but also new tools. Text editors are definitely such tools. Today we will try to write our own.

From this article you will learn:
- Can we edit the content of HTML tags other than form elements?
- How can we use the browser API to edit text inside divs?
- How can we write a simple text editor?
Surely each of you has worked with a text editor at least once in your life, such as MS Word, Open Office, or Google Docs. Personally, I work with Google Docs and Bear every day - in my opinion, definitely the most pleasant text editors.
Some time ago I wondered how to prepare a simple but functional text editor in an easy way. I naturally started my search with the technology I work with every day, meaning JavaScript, HTML, and CSS.
It turned out to be very simple.
The Power of HTML Attributes
Even though I have worked with web technologies for many years, I learn something every day. And yes, HTML, underestimated by many people, also hides its secrets. One of them is the very interesting contenteditable attribute.
According to the information I found, this attribute makes every HTML element editable. By combining the power of this attribute with JavaScript events, we can get an advanced text editor in our browser or build a desktop application for writing content by using Electron. It all comes down to one line:
<div contenteditable="true">
this is the editable field of our text editor
</div>Simple, right?
document.execCommand
We already have a text field we can operate on. It turns out that along with adding the contenteditable attribute, the execCommand method in the document object has been unlocked for our use. Thanks to this function, we can perform various operations that will appropriately modify selected text, insert additional elements, or affect the current line. Sounds great! This will let us make our text editor fully functional.
document.designMode
We can also edit the whole document by changing the value of designMode in the document object. designMode accepts two values: on and off. The default value is off.
Options and Support
So the question is, what options do we have available?
You can find the full list of available commands here. But so that things are not too colorful, let us look at browser support. Before I looked at caniuse.com, I assumed that IE would not support too many operations. And to my great surprise, IE, just like Chrome, Safari, or Firefox, supports execCommand quite well. IE has a problem only with a few commands, such as insertBrOnReturn, defaultParagraphSeparator, and, below version 9, with copy and cut. Other than that, the rest looks quite good.
A Bit of Code
Preparing the HTML structure for our editor is not very demanding. We need only two things: a place that will be editable and buttons that will trigger the right commands.
<div>
<nav>
<ul>
<li class="app-nav-item">
<button class="app-btn"><i class="fas fa-align-right"></i></button>
</li>
...
</ul>
</nav>
<main class="app-editor" contenteditable="true">
This is an example text.
</main>
</div>Notice that I added a few CSS classes that will style our editor appropriately. In addition, I used the Font Awesome library to add a few icons, because why not - it will look a little more pro. :)
A Bit of JS Magic
After finishing the HTML structure and styling the project, it is time to add a few lines of JS. What should our JavaScript code do? First of all, it should check which command was clicked by the user and execute execCommand with the right parameters. So - let us do it.
Let us assign the right commands to our buttons. I used HTML data- attributes for this:
<button class="app-btn" data-command="cut"><i class="fas fa-cut"></i></button>Then, in the JS file, I fetched all buttons and created an array from them, because the querySelectorAll method does not actually return an array, but an array-like object:
const buttons = Array.from(document.querySelectorAll('button[data-command]'));The only thing left is to assign to each button the right method that will be called after clicking. Let us use one of the array methods for this: forEach.
buttons.forEach(btn => {
btn.addEventListener('click', function () {
document.execCommand(btn.dataset.command, true, '');
})
});Summary
And that is basically the end. Of course, this code can still be expanded. A few bugs can be fixed and it can be optimized. But our goal has been achieved. I encourage you to keep working on this code. Try to complete the task below.




Comments (0)
No one has posted anything yet, but that means.... you may be the first.