How to create Rich Text Editor in js?

This article shares how to create a simple Rich Text Editor Tool with HTML CSS and JavaScript

A Rich Text Editor (RTE) is a type of text editor that allows users to format text, insert images and other multimedia, and create tables and other complex layouts without having to write any HTML or CSS code. RTEs are often used to create web content, but they can also be used to create documents for print or other purposes.

This project will be the most memorable in your web development career. Because you are going to learn to create a rich text editor with a dark theme. Also, I am sharing the source code here. If you like the project, don't forget to share it with your friends.

Here are some of the advantages of using a rich text editor in JavaScript

  • Ease of use: Rich text editors provide a WYSIWYG (what you see is what you get) interface, making it easy for users to create and edit formatted text without having to learn HTML or CSS.
  • Flexibility: JavaScript-based rich text editors can be customized to meet the specific needs of your application. For example, you can add or remove features, change the toolbar layout, and integrate with other JavaScript libraries.
  • Performance: JavaScript-based rich text editors are generally very fast and responsive, even when editing complex documents.
  • Portability: JavaScript-based rich text editors can be used on any platform that supports JavaScript, including web browsers, mobile devices, and desktop applications.

Here are some specific examples of how rich text editors in JavaScript can be used

  • Creating blog posts and articles: Rich text editors can be used to create and edit formatted text for blog posts and articles, including adding images, videos, and other media.
  • Building web applications: Rich text editors can be used to build web applications that allow users to create and edit formatted content, such as wikis, forums, and content management systems (CMSs).
  • Developing mobile apps: Rich text editors can be used to develop mobile apps that allow users to create and edit formatted content, such as note-taking apps and word processors.

Some popular JavaScript-based rich text editors include

  • TinyMCE
  • CKEditor
  • Quill
  • Froala Editor
  • JQTE

Overall, JavaScript-based rich text editors are a powerful and versatile tool for creating and editing formatted text in a variety of applications.

files and folders for the WYSIWYG HTML editor

You want to create three files (indux.html, style.css and ) in a folder. 


<!DOCTYPE html>
<html lang="en">

    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">

    <div class="main">
            <h1>Blog writer</h1>

        <div class="textBlog">
            <form action="#" method="POST">
                <div class="options">

                    <!-- Text Format -->
                    <button type="button" id="bold" class="option-button format">
                    <button type="button" id="italic" class="option-button format">
                    <button type="button" id="underline" class="option-button format">
                    <button type="button" id="strikethrough" class="option-button format">
                    <button type="button" id="superscript" class="option-button script">
                    <button type="button" id="subscript" class="option-button script">
                    <!-- List -->
                    <button type="button" id="insertOrderedList" class="option-button">
                    <button type="button" id="insertUnorderedList" class="option-button">
                    <!-- Undo/Redo -->
                    <button type="button" id="undo" class="option-button">
                    <button type="button" id="redo" class="option-button">

                    <!-- Link -->
                    <button type="button" id="createLink" class="adv-option-button">

                    <button type="button" id="unlink" class="option-button">

                    <!-- Alignment -->

                    <button type="button" id="justifyLeft" class="option-button align">
                    <button type="button" id="justifyCenter" class="option-button align">

                    <button type="button" id="justifyRight" class="option-button align">

                    <button type="button" id="justifyFull" class="option-button align">

                    <button type="button" id="indent" class="option-button spacing">

                    <button type="button" id="outdent" class="option-button spacing">

                    <!-- Headings -->

                    <select id="formatBlock" class="adv-option-button">
                        <option value="H1">H1</option>
                        <option value="H2">H2</option>
                        <option value="H3">H3</option>
                        <option value="H4">H4</option>
                        <option value="H5">H5</option>
                        <option value="H6">H6</option>

                    <!-- Color -->

                    <div class="input-wrapper">
                        <input type="color" id="foreColor" class="adv-option-button">
                        <label for="foreColor">Font Color</label>

                    <div class="input-wrapper">
                        <input type="color" id="backColor" class="adv-option-button">
                        <label for="backColor">Highlight Color</label>
                <div name="mainContent" class="textCon" spellcheck="true" id="text-input" contenteditable="true">

    <div class="count">
        <div class="maincou">
            Post Words: <span id="pword" class="colorWord pword words">0</span>

    <script src="main.js"></script>

        document.getElementById('text-input').addEventListener('input', function () {
            var text = this.textContent,
                count = text.trim().replace(/s+/g, ' ').split(' ').length;
            document.querySelector('.words').textContent = count;


* {
    margin: 0%;
    padding: 0%;
    box-sizing: border-box;
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;

body {
    background-color: rgb(6, 6, 20);
    color: rgb(139, 140, 141);

.textBlog {
    max-width: 800px;
    margin: auto;
    border: 1px solid rgb(126, 119, 119);
    border-radius: 12px;
    padding: 30px;

.textCon {
    height: 400px;
    overflow: auto;
    border: none;
    background-color: rgb(13, 13, 37);
    border-radius: 10px;
    outline: none;
    color: rgb(173, 169, 169);
    font-size: 20px;
    padding: 10px 20px;
    font-weight: 520;

.textCon p {
    padding: 15px 0 15px 0;

.textCon b {
    font-weight: 900;

.buttons {
    color: rgb(169, 173, 169);
    background-color: rgb(50, 0, 187);
    padding: 8px;
    font-size: 19px;
    font-weight: 800;
    border: none;
    margin: 20px 20px 20px 0;
    border-radius: 5px;

.buttons:hover {
   background-color: rgb(221, 221, 221);
    color: black;

::selection {
    background-color: rgb(255, 102, 0);
    color: white;

.count {
   position: absolute;
    top: 35px;
    left: 33px;
    display: inline-block;
    position: fixed;

.maincou {
    width: 300px;
    border: 2px solid rgb(255, 255, 255);
    color: rgb(224, 224, 224);
    background-color: rgb(11, 57, 207);
    border-radius: 30px;
    padding: 20px;
    font-weight: 600;

.colorWord {
    font-weight: 800;
    margin-left: 10px;
    color: rgb(255, 255, 255);

.textCon::-webkit-scrollbar {
    width: 4px;

.textCon::-webkit-scrollbar-track {
    background-color: rgb(51, 51, 51);

.textCon::-webkit-scrollbar-thumb {
    background-color: rgb(52, 89, 253);

.options button,
.options select {
    padding: 10px;
    background-color: blue;
    border: none;
   margin-bottom: 15px;
    color: white;
    outline: none;
    font-weight: 700;

.options button:hover,
.options select:hover {
    color: black;
    background-color: white;

.active {
    background-color: #e0e9ff;


let optionsButtons = document.querySelectorAll(".option-button");
let advancedOptionButton = document.querySelectorAll(".adv-option-button");
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");
//Initial Settings
const initializer = () => { 

  //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 => {
    let option = document.createElement("option");
    option.value = value;
    option.innerHTML = value;

  //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(, false, null);


//options that require value parameter (e.g colors, fonts)
advancedOptionButton.forEach((button) => {
  button.addEventListener("change", () => {
    modifyText(, false, button.value);

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(, false, userLink);
  } else {
    userLink = "http://" + userLink;
    modifyText(, 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
        if (!alreadyActive) {
         //highlight clicked button
      } else {
        //if other buttons can be highlighted


const highlighterRemover = (className) => {
  className.forEach((button) => {


window.onload = initializer();

WordPress Theme Editor


Post a Comment