- Minimal code editor in JavaScript
- contenteditable
- handling cursor
- a fly in the ointment
- Rich Text Editor using HTML, CSS & JavaScript
- Project Description
- HTML Code for Rich Text Editor
- CSS Code for Rich Text Editor
- JavaScript Code for Rich Text Editor
- Output
- Live Preview of Rich Text Editor using HTML, CSS & JavaScript (Source Code)
- Rich Text Editor With Javascript
- Video Tutorial:
- Project Folder Structure:
- HTML:
- CSS:
- Javascript:
Minimal code editor in JavaScript
How would one write a code editor in JavaScript? A long time ago one would take a regular textarea to handle user input and would create another div that would do syntax highlighting etc. However, this approach quickly becomes unusable when someone opens it on mobile. That’s why CodeMirror has been rewritten to use contenteditable and many other editors followed this approach.
contenteditable
Contenteditable, as the name suggests, allows users to edit the contents of the element using the browser-native techniques — all shortcuts for text selection and navigation work as expected, so does the clipboard and other minor editing features.
Let’s try making a tiny code editor using a single contenteditable div and a bit of JavaScript.
We start with a minimal markup in a single HTML file. The only element we would need is a div:
At this point, our editor behaves much like textarea - one can type, select or edit text.
Let’s drop in some rudimentary syntax highlighting. It can be a function that takes a DOM element, iterates over all its children (in our case — lines) and wraps the keywords or other meaningful tokens into additional markup that would help styling and highlighting it with CSS:
If we now apply the function to our editor - we would see that the code inside looks not so boring anymore, numbers and keywords look bolder and stand out, while comments and strings look italic.
handling cursor
However, as soon as we start editing the text — the highlighting remains static, so we need to re-apply our function every time the contents of the editor change. Now, if you start listening to the key presses and call the js(el) function on each of them — you will see the cursor behaves weirdly. It jumps to the start position every time. Thus, we need to save cursor position before applying the highlighter and restore it later.
To get caret position one may use the following function:
It basically takes the current selection from the editor (a cursor is a zero-width selection where start and end are at the same position), and returns the position of its end. To restore the caret we would have to do something more tricky, we need to recursively iterate the child nodes of the highlighted text inside the editor and find the one containing the caret, and restore the selection range there:
Now we should be able to listen to key-up events and highlight contents of the editor without losing the caret position:
A nice bonus here would be line numbers. Of course, one can render a column of small divs, each containing a line number aligned with a row in a contenteditable and manipulate them every time line count changes. But with CSS counters this can be achieved with almost no code:
Here’s how it looks like, with no additional styling:
Not bad for a low-code solution?
a fly in the ointment
Why did I have to filter out key presses to apply highlighting only after some printable character was typed? Unfortunately, Chrome seems to calculate cursor position when a newline is added or removed, also when someone moves caret with arrow keys or selects some text with hotkeys — calling setCaret() would rather prevent his intentions.
A possible alternative here would be to use a different type of contenteditable attribute, contenteditable=»plaintext-only» . This is not standardized yet, however Chrome and WebKit browsers support it. This, however, would make it impossible to use CSS for line numbers, and one would have to re-implement it in JavaScript.
So, on the one hand, it seems to be possible to write a lightweight code editor in under 50 lines of vanilla JavaScript. But for a more featureful and production-ready code editor one should probably use battle-tested implementations, like CodeMirror or VSCode’s Monaco.
If you are willing to experiment further with contenteditable approach and minimal code — the single-HTML gist is available here, or here is the jsfiddle — https://jsfiddle.net/zserge/gkbjv47n/.
I hope you’ve enjoyed this article. You can follow – and contribute to – on Github, Mastodon, Twitter or subscribe via rss.
Rich Text Editor using HTML, CSS & JavaScript
Hello everyone. Welcome to today’s tutorial on Codewithrandom. We’ll learn how to make Rich Text Editor which will generate a text editor in which the user can change the font color can make the character bold & italic can set the font size undo & redo etc. This project will is good for beginners and help them to build their front-end development skills. In Today’s session, We will use HTML, CSS, and JavaScript to complete this Rich Text Editor Project.
Project Description
Step 1
The HTML (Hypertext Markup Language) will help us to create the structure for the list with some necessary attributes and elements to make Rich Text Editor Project.
Step 2
Then we will use CSS (Cascading Stylesheet) which will help us to style or design the project with suitable padding and alignment in the Rich Text Editor Project.
Do you want to learn HTML to JavaScript? 🔥
If yes, then here is our Master Frontend: Zero to Hero eBook! 📚 In this eBook, you’ll learn complete HTML, CSS, Bootstrap, and JavaScript from beginner to advance level. 💪 It includes 450 Projects with source code.
Step 3
At last we will use JS (JavaScript) which will add a logic to make the Rich Text Editor Project responsive from the user end.
I hope you have got an idea about the project.
HTML Code for Rich Text Editor
First we’ll start with creating the structure of the Rich Text Editor project for that as you can see the above code we have used all the necessary elements & attributes to setup the structure. Let us know code the CSS part to add styling and aligned the tags.
[email protected] superscript">
CSS Code for Rich Text Editor
Second comes the CSS code in which we have styled for the structure we have padded as well as aligned the Rich Text Editor project so that it is properly situated and doesn’t get messy with suitable CSS elements. Now we have created the structure using HTML and styled the webpage using CSS its time to add the functionality using JavaScript in this project.
* < padding: 0; margin: 0; box-sizing: border-box; >body < background-color: #338cf4; >.container < background-color: #ffffff; width: 90vmin; padding: 50px 30px; position: absolute; transform: translate(-50%, -50%); left: 50%; top: 50%; border-radius: 10px; box-shadow: 0 25px 50px rgba(7, 20, 35, 0.2); >.options < display: flex; flex-wrap: wrap; align-items: center; gap: 15px; >button < height: 28px; width: 28px; display: grid; place-items: center; border-radius: 3px; border: none; background-color: #ffffff; outline: none; color: #020929; >select < padding: 7px; border: 1px solid #020929; border-radius: 3px; >.options label, .options select < font-family: "Poppins", sans-serif; >.input-wrapper < display: flex; align-items: center; gap: 8px; >input[type=»color»] < -webkit-appearance: none; -moz-appearance: none; appearance: none; background-color: transparent; width: 40px; height: 28px; border: none; cursor: pointer; >input[type=»color»]::-webkit-color-swatch < border-radius: 15px; box-shadow: 0 0 0 2px #ffffff, 0 0 0 3px #020929; >input[type=»color»]::-moz-color-swatch < border-radius: 15px; box-shadow: 0 0 0 2px #ffffff, 0 0 0 3px #020929; >#text-input < margin-top: 10px; border: 1px solid #dddddd; padding: 20px; height: 50vh; >.active
JavaScript Code for Rich Text Editor
Last stage of the project the JavaScript in which we have added the logical and coded as per the requirement with some conditions. We have made each define function responsive from the user end and added logic to it so that it can figure out when to execute. Let us see the Final Output of the project Rich Text Editor using HTML, CSS & JavaScript (Source Code).
let optionsButtons = document.querySelectorAll(".option-button"); let advancedOptionButton = document.querySelectorAll(".adv-option-button"); let fontName = document.getElementById("fontName"); let fontSizeRef = document.getElementById("fontSize"); let writingArea = document.getElementById("text-input"); let linkButton = document.getElementById("createLink"); let alignButtons = document.querySelectorAll(".align"); let spacingButtons = document.querySelectorAll(".spacing"); let formatButtons = document.querySelectorAll(".format"); let scriptButtons = document.querySelectorAll(".script"); //List of fontlist let fontList = [ "Arial", "Verdana", "Times New Roman", "Garamond", "Georgia", "Courier New", "cursive", ]; //Initial Settings const initializer = () => < //function calls for highlighting buttons //No highlights for link, unlink,lists, undo,redo since they are one time operations highlighter(alignButtons, true); highlighter(spacingButtons, true); highlighter(formatButtons, false); highlighter(scriptButtons, true); //create options for font names fontList.map((value) =>< let option = document.createElement("option"); option.value = value; option.innerHTML = value; fontName.appendChild(option); >); //fontSize allows only till 7 for (let i = 1; i //default size fontSizeRef.value = 3; >; //main logic const modifyText = (command, defaultUi, value) => < //execCommand executes command on selected text document.execCommand(command, defaultUi, value); >; //For basic operations which don't need value parameter optionsButtons.forEach((button) => < button.addEventListener("click", () =>< modifyText(button.id, false, null); >); >); //options that require value parameter (e.g colors, fonts) advancedOptionButton.forEach((button) => < button.addEventListener("change", () =>< modifyText(button.id, false, button.value); >); >); //link linkButton.addEventListener("click", () => < let userLink = prompt("Enter a URL"); //if link has http then pass directly else add https if (/http/i.test(userLink)) < modifyText(linkButton.id, false, userLink); >else < userLink = "http://" + userLink; modifyText(linkButton.id, false, userLink); >>); //Highlight clicked button const highlighter = (className, needsRemoval) => < className.forEach((button) => < button.addEventListener("click", () => < //needsRemoval = true means only one button should be highlight and other would be normal if (needsRemoval) < let alreadyActive = false; //If currently clicked button is already active if (button.classList.contains("active")) < alreadyActive = true; >//Remove highlight from other buttons highlighterRemover(className); if (!alreadyActive) < //highlight clicked button button.classList.add("active"); >> else < //if other buttons can be highlighted button.classList.toggle("active"); >>); >); >; const highlighterRemover = (className) => < className.forEach((button) =>< button.classList.remove("active"); >); >; window.onload = initializer();
Output
Live Preview of Rich Text Editor using HTML, CSS & JavaScript (Source Code)
See the Pen
Text by Harsh Sawant (@harshh9)
on CodePen.
We have Successfully created our Rich Text Editor using HTML, CSS & JavaScript (Source Code). You can use this project for your personal needs and the respective lines of code are given with the code pen link mentioned above.
If you find out this Blog helpful, then make sure to search code with random on google for Front End Projects with Source codes and make sure to Follow the Code with Random Instagram page.
Rich Text Editor With Javascript
Hey everyone. Welcome to today’s tutorial. In today’s tutorial, we will learn how to create a rich text editor. To build this project, we need HTML, CSS and Javascript. This tutorial is best suited for javascript intermediates.
If you would like to try other projects to improve your javascript skills, check out this playlist here. It consists of 70+ javascript projects. The complexity of these projects varies from easy to advanced. Thus these projects are suitable for beginners as well as experts.
The project consists of a text field that the user can type. Above this text field, we have an options section. In the options section, there are a variety of buttons and dropdowns. The user can use these options to modify the text. These options include:
- Text Formatters – Bold, Italic, Underline, Strikethrough.
- List Options – Ordered List, Unordered list.
- Undo and Redo Button
- Add Link and Remove Link Button.
- Alignment Option Buttons – Align Left, Align Right, Align Center, and Justify.
- Headings Dropdown – H1 To H6
- Fonts Family Dropdown – 6 Different Fonts
- Font Size Dropdown – Sizes ranging from 1 to 7.
- Options to change text color and highlight color.
Video Tutorial:
If you prefer to learn by coding along to a video tutorial rather than reading this blog post, check out the video here down below. Also subscribe to my youtube channel where I post new tips, tricks and tutorials related to web development regularly.
Project Folder Structure:
Now before we move to the actual coding, let us take a look at the project folder structure. We create a project folder called – ‘Rich Text Editor’. Inside this folder, we have three files – index.html, style.css and script.js. These files are the HTML document, the stylesheet and the script file.
HTML:
We start with the HTML code. Firstly copy the code below and paste it into your HTML document. This creates the layout necessary for our project.
CSS:
Next, we style our project using CSS. Now copy the code provided to you below and paste it into your stylesheet.
* < padding: 0; margin: 0; box-sizing: border-box; >body < background-color: #338cf4; >.container < background-color: #ffffff; width: 90vmin; padding: 50px 30px; position: absolute; transform: translate(-50%, -50%); left: 50%; top: 50%; border-radius: 10px; box-shadow: 0 25px 50px rgba(7, 20, 35, 0.2); >.options < display: flex; flex-wrap: wrap; align-items: center; gap: 15px; >button < height: 28px; width: 28px; display: grid; place-items: center; border-radius: 3px; border: none; background-color: #ffffff; outline: none; color: #020929; >select < padding: 7px; border: 1px solid #020929; border-radius: 3px; >.options label, .options select < font-family: "Poppins", sans-serif; >.input-wrapper < display: flex; align-items: center; gap: 8px; >input[type=»color»] < -webkit-appearance: none; -moz-appearance: none; appearance: none; background-color: transparent; width: 40px; height: 28px; border: none; cursor: pointer; >input[type=»color»]::-webkit-color-swatch < border-radius: 15px; box-shadow: 0 0 0 2px #ffffff, 0 0 0 3px #020929; >input[type=»color»]::-moz-color-swatch < border-radius: 15px; box-shadow: 0 0 0 2px #ffffff, 0 0 0 3px #020929; >#text-input < margin-top: 10px; border: 1px solid #dddddd; padding: 20px; height: 50vh; >.active
Javascript:
Finally, we implement the logic using javascript. For this copy the code below and paste it into your script file.
let optionsButtons = document.querySelectorAll(".option-button"); let advancedOptionButton = document.querySelectorAll(".adv-option-button"); let fontName = document.getElementById("fontName"); let fontSizeRef = document.getElementById("fontSize"); let writingArea = document.getElementById("text-input"); let linkButton = document.getElementById("createLink"); let alignButtons = document.querySelectorAll(".align"); let spacingButtons = document.querySelectorAll(".spacing"); let formatButtons = document.querySelectorAll(".format"); let scriptButtons = document.querySelectorAll(".script"); //List of fontlist let fontList = [ "Arial", "Verdana", "Times New Roman", "Garamond", "Georgia", "Courier New", "cursive", ]; //Initial Settings const initializer = () => < //function calls for highlighting buttons //No highlights for link, unlink,lists, undo,redo since they are one time operations highlighter(alignButtons, true); highlighter(spacingButtons, true); highlighter(formatButtons, false); highlighter(scriptButtons, true); //create options for font names fontList.map((value) =>< let option = document.createElement("option"); option.value = value; option.innerHTML = value; fontName.appendChild(option); >); //fontSize allows only till 7 for (let i = 1; i //default size fontSizeRef.value = 3; >; //main logic const modifyText = (command, defaultUi, value) => < //execCommand executes command on selected text document.execCommand(command, defaultUi, value); >; //For basic operations which don't need value parameter optionsButtons.forEach((button) => < button.addEventListener("click", () =>< modifyText(button.id, false, null); >); >); //options that require value parameter (e.g colors, fonts) advancedOptionButton.forEach((button) => < button.addEventListener("change", () =>< modifyText(button.id, false, button.value); >); >); //link linkButton.addEventListener("click", () => < let userLink = prompt("Enter a URL"); //if link has http then pass directly else add https if (/http/i.test(userLink)) < modifyText(linkButton.id, false, userLink); >else < userLink = "http://" + userLink; modifyText(linkButton.id, false, userLink); >>); //Highlight clicked button const highlighter = (className, needsRemoval) => < className.forEach((button) => < button.addEventListener("click", () => < //needsRemoval = true means only one button should be highlight and other would be normal if (needsRemoval) < let alreadyActive = false; //If currently clicked button is already active if (button.classList.contains("active")) < alreadyActive = true; >//Remove highlight from other buttons highlighterRemover(className); if (!alreadyActive) < //highlight clicked button button.classList.add("active"); >> else < //if other buttons can be highlighted button.classList.toggle("active"); >>); >); >; const highlighterRemover = (className) => < className.forEach((button) =>< button.classList.remove("active"); >); >; window.onload = initializer();
That’s it for this tutorial. If you face any issues while creating this project you can download the source code by clicking on the download button below. Also, if you have any queries, suggestions or feedback drop them in the comments below.
Happy Coding.