Using Quill.js To Build A WYSIWYG Editor For Your Website


Remember how basic the Facebook status update used to be? 

Status Box WYSIWYG Editor Quill

Now, that same space contains an array of sophisticated text styling options that let users fully express what’s on their minds. This evolution has been driven by rich-text editors like Quill, which allow visitors to fully customise their content: from embedding photos and videos to adding emoticons. In this article, Scalable Path’s Andres Canal gives us step by step guide to installing and customising this open-source javascript tool.

A few weeks ago, I found myself in need of a simple, yet extendable, WYSIWYG HTML editor. A fully functional text editor is a complex piece of software, and writing one from scratch would not have been the best use of my time. I’m a big believer in not reinventing the wheel and making use of other people’s open source code. But this mindset requires its own skill set: knowing how to quickly and efficiently evaluate options.

Evaluating WYSIWYG Editor options

The first thing I did was to google ’WYSIWYG Editor’. As expected, the results were overwhelming. I found dozens of different options, in various states of maintenance and quality:

Alloy Editor, Aloha Editor, CKEditor, Content Tools, Etherpad, grande.js, jodit, Medium Editor, Medium.js, Mobiledoc Kit, Pell, Pen Editor, Quill.js, Squire, Scribe, Slate JS, Substance, TinyMCE, Trix, Trumbowyg and wysihtml.

Wow. Where to start?

As a front-end developer, you’re likely familiar with this situation. Every tech stack decision requires sorting through an ever-increasing number of frameworks, preprocessors, Javascript versions and so on. Let’s take a slight detour from Quill.js to chat about evaluating software. Over time, I’ve developed a system-of-sorts for quickly doing this, which may be useful to you.

Spoiler Alert: I choose Quill.js at the end!

Software Evaluation Process

  1. Available options: Start by pulling together as many options as you can. While no search is complete without checking Google, I tend to refine my options on Github.
  2. Popularity: A popular project on Github means exactly what you expect it to. Namely, that there are lots of people questioning, contributing and supporting it. This activity tends to result in more reliable software. You can check the popularity of any project by looking at how many stars it has, how many issues are opened, how many pull requests are pending, and how many contributors worked on the project. The editor with the most amount of stars on Github was Quill.js.
  3. Maintenance: Software becomes dated and buggy when not maintained. A nice proxy for this is to check when the last commits were made. If this was 4 years ago, I would go with another option. When carrying out my own evaluation, Quill.js was being updated weekly – a very good sign.
  4. Users: Some projects are backed by big players who will have a vested interest in ensuring the project is maintained. Quill.js is used by many established brands including Linkedin, Salesforce, Asana, Front, Slack, Gusto and Buffer.
  5. Tests: I love tests. A really well-tested project counts for a lot in my eyes. It not only implies that the software does what is supposed to do, but also that the developer himself has a rigorous methodology. The metric used to measure how much code is executed when tests are run is called test coverage. The bigger the coverage the better, but be careful, 100% coverage doesn’t mean the product has no bugs. Unfortunately, in the case of Quill.js, I couldn’t see any coverage reports on Github. Instead, I checked if the build was being successfully compiled without problems – which it is.
  6. Downloads: Many package managers share their download statistics. For example, if you want to check the statistics related to an npm package, you can go to https://www.npmjs.com/package/name-of-package. Quill.js is downloaded around a quarter of million times per month. For comparison, Pell, another popular editor, receives only around 3,000 downloads a month. Notice how I’m comparing Quill’s popularity compared to another editor here. It makes sense to compare vertically – not horizontally across the wider software ecosystem – because great software can be built to solve highly niche issues.

WYSIWYGI HYML editor Quill.js stats

Image 2: Quill.js Download Stats

Getting Quill.js up and running

Now we have settled on Quill.js as our WYSIWYG editor of choice, let’s look at integrating it into our site, which is a pretty straightforward task as it turns out.

Start by including Quill.js and Quill.js.snow.css to an HTML file:

<html>
  <head>
    <link href="https://cdn.quilljs.com/1.3.4/quill.snow.css" rel="stylesheet"> 
    <script src="https://cdn.quilljs.com/1.3.4/quill.js"></script>
  </head>
  <body></body>
</html>

Now let’s add a <div> with the id attribute set to “editor” into the <body> tag. This is where our editor is going to live.

<body>
    <div id="editor"></div>
</body>

Now let’s add a script section to the bottom of the HTML file and initialize Quill. To do this we have to tell Quill the id of the div where we want the editor to be added.

<script>
  var quill = new Quill('#editor', {
    theme: 'snow'
  });
</script>

OK, we’re good to go! Drag the file into your browser and you should see the default Quill.js editor view.

Quill WYSIWYG HTML editor

Let’s customize the toolbar and specify the styles we want it to display. To do this, we provide an array of our desired styles to Quill’s constructor. As shown here:

<script>
  var toolbarOptions = [
    ['bold', 'italic']
  ]
  var quill = new Quill('#editor', {
    modules: {
      toolbar: toolbarOptions
    },
    theme: 'snow'
  });
</script>

We only want to only support ‘bold’ and ‘italic’, so those are the options we provide to the constructor. If you want to see all the possible styles supported by quill’s toolbar you can go to the toolbar section in Quill’s documentation. Your toolbar should now look like this:

Italic and Bod only WYSIWYG HTML editor Quill

If your editor will be used within a commenting engine, you’ll need a way to access the generated HTML. So let’s see how we can log the contents to the console. First, let’s add a button inside our <body> tag. This button is going to call a function and log the content of the editor.

<body>
  <div id="editor"></div>
  <button onclick="logHtmlContent()">Log content as HTML</button>
</body>

Next, we will create a toolbar with the following options: font size, font color and background color. We will also add the logHtmlContent()function. This will be called when a user taps the ‘Log content as HTML’ button we added below the WYSIWYG HTML editor.

<script>
  var toolbarOptions = [
    ['bold', 'italic'],
    [{ 'size': ['small', false, 'large', 'huge'] }],
    [{ 'color': [] }, { 'background': [] }]
  ]
  var quill = new Quill('#editor', {
    modules: {
      toolbar: toolbarOptions
    },
    theme: 'snow'
  });
  function logHtmlContent() {
    console.log(quill.root.innerHTML);
  }
  </script>

Here we go:

Highlight WYSIWYG HTML editor Quill

When tapping on the ‘Log content as HTML’ we get the following:

<p><span class="ql-size-large" style="background-color: rgb(0, 0, 0); color: rgb(255, 255, 255);">This</span> <span class="ql-size-small">is</span> a <span class="ql-size-huge" style="background-color: rgb(230, 0, 0); color: rgb(255, 255, 255);">text</span> <span class="ql-size-large" style="background-color: rgb(0, 138, 0); color: rgb(255, 255, 255);">message</span>.</p>

For some formats, Quill.js uses inline style on the HTML nodes. For others, it uses custom CSS classes. This is important because if you are saving these in a database, your CSS will have to support Quill’s CSS formats like ql-size-huge and ql-size-large .

Quill developed their own format, called Delta, to describe content and changes. It’s a human and machine-readable description of your text editor, but without the complexity of HTML. While covering it is beyond the scope of this document, you can dig deeper yourself by checking out their documentation.

Extending Quill.js to support custom formats

Once you start familiarizing yourself with Quill.js, you may want to use formats that are not provided by default. For example, let’s say you want to add support for highlighted text using HTML’s <mark> tag.

Quill.js document model is called Parchment. Think of it as a custom DOM: little building blocks that, when put together in a certain order, build a document. So depending on the custom format we want to add, we will need to extend one of these ‘blocks’. In the parchment world, these building blocks are called “Blots”.

We’ll start by adding a ‘Mark’ button to the toolbar, that when clicked, surrounds the selected text with <mark></mark> tags.

let Inline = Quill.import('blots/inline'); 
class MarkBlot extends Inline { } 
MarkBlot.blotName = 'mark'; 
MarkBlot.tagName = 'mark'; 
Quill.register(MarkBlot);

The above snippet is pretty easy to understand. We start by extending a class, setting a name for the blot, and its associated HTML tag, then registering that blot so it can be added to the editor.

We now need to create a button to toggle the custom format. This time, to add the button to the toolbar, we will create our toolbar in plain HTML. We’ll use this method instead of the previous method where we sent Quill an array of formats. To accomplish this, let’s create a <div> to hold our toolbar and add the buttons as shown below:

<div id="toolbar">
  <button class="ql-bold"></button>
  <button class="ql-italic"></button>
  <button class="ql-mark">Mark</button>
</div>

Inside this <div> we need to add a button for each format we want to support. Using a ql-blot-name so Quill.js can figure out which blot to use for the selected text.

Once done, we need to initialize Quill. This time we need to provide Quill with the id of the toolbar we just created. This is the id of the div that contains the toolbar buttons:

var quill = new Quill('#editor', {
  modules: {
    toolbar: {
      container: '#toolbar'
    }
  },
  theme: 'snow'
});

Refresh your browser and you should see your new functional Mark button. Try it out!

Mark button WYSIWYG HTML editor Quill

Let’s raise the bar a bit here and create a truly custom style. “How about a text selection with a dotted border?” Good, I was hoping you would say that.

To do this we are going to use Attributors. In Parchment an Attributor is a lightweight way of representing formats. There are different types of attributors: here we are going to choose one that lets us apply a class to a selected element.

const Parchment = Quill.import('parchment')
 var boxAttributor = new Parchment.Attributor.Class('box', 'line', {
 scope: Parchment.Scope.INLINE,
 whitelist: ['solid', 'double', 'dotted']
 });
 Quill.register(boxAttributor);

The above constructor receives three parameters: attributor name, key name and a configuration JSON. We are creating a class attributor, which means that a class will be added to a node. In our example, the classes will be: line-solid, line-double and line-dotted.

Now we need to add the buttons that are going to apply the classes to our previously defined toolbar:

<button class="ql-box" value="double">Dou</button>
<button class="ql-box" value="solid">Line</button>
<button class="ql-box" value="dotted">Dot</button>

Each new button has two attributes. The class tells Quill.js which attributor is going to be applied when clicked. The value defines which class the button is going to apply. These value options have to be previously defined when creating the attributor in the configuration JSON.  

Before we test this, let’s define the new CSS classes that will apply the format to our selections:

<style>
  .line-dotted {
    border-style: dotted;
  }
  .line-solid {
    border-style: solid;
  }
  .line-double {
    border-style: double;
  }
</style>

OK, let’s refresh the page and see our new styles in action:

Multiple styles WYSIWYG HTML editor Quill

For reference, the HTML for the above styling looks like:

Exported code from WYSIWYG HTML editor Quill

Those of you paying attention may be wondering “Why didn’t he just create a new blot called BoxBlot?” Great question. A blot creates a node, and we don’t want to create a node as they are used to group information and give semantic meaning. Here, we simply want to apply a format which is best done with an attribute.

While all three of our new buttons work, only one can be applied at any one time, so they should really be grouped together. Besides being just better UX practice, it will also serve to declutter the toolbar.

<div id="toolbar">
  <button class="ql-bold"></button>
  <button class="ql-italic"></button>
  <select class="ql-box">
    <option selected>None</option>
    <option value="double">Double</option>
    <option value="solid">Solid</option>
    <option value="dotted">Dotted</option>
  </select>
</div>

Next, we have to add the following CSS rules (I came up with these rules after inspecting how Quill.js was building the fonts drop-down):

.ql-snow .ql-picker.ql-box .ql-picker-label::before,
.ql-snow .ql-picker.ql-box .ql-picker-item::before {
    content: 'None'
}

.ql-snow .ql-picker.ql-box .ql-picker-label[data-value="solid"]::before,
.ql-snow .ql-picker.ql-box .ql-picker-item[data-value="solid"]::before {
    content: "Solid";
}

.ql-snow .ql-picker.ql-box .ql-picker-label[data-value="double"]::before,
.ql-snow .ql-picker.ql-box .ql-picker-item[data-value="double"]::before {
    content: "Double";
}

.ql-snow .ql-picker.ql-box .ql-picker-label[data-value="dotted"]::before,
.ql-snow .ql-picker.ql-box .ql-picker-item[data-value="dotted"]::before {
    content: "Dotted";
}

.ql-snow span.ql-picker.ql-box {
    width: 8em;
}

We’re done! The end result should look like this:

Styles dropdown WYSIWYG HTML editor Quill

Summary

We started off the article with a rundown of the process I use to evaluate software with a focus on picking a WYSIWYG editor. As talented developers keep adding to the myriad of software options in the market, it becomes more and more important to be able to quickly and efficiently filter through them. The wrong choice can leave you in development hell: having to deal with buggy or unsupported products.

It’s that evaluation process which initially led me to the excellent Quill.js. The bulk of this article demonstrated not just how easy it is to set up, but how extensible and adaptable it is. If you want to provide your visitors with the rich text styling options they are becoming used to, I encourage you to try and work through the examples above. To do so, just head over to CodePen where I’ve stored all the code and functional examples of this project. Good luck!

 

  • Kris Merckx

    Quill is great. I thought. Until I start to use it. It even does not support tables. Does your “editable” content contains a HTML-table? Quill automatically removes it. Unbelievable. “Too difficult to implement”, the developers says. How could a simple table be too difficult? Ok, … but… why removing existing tables just to hold on to that also strange “DELTA/JSON”-thing. Without “a small hack” you can’t even get the HTML content.

    • Mario Putzo

      Quill is not for you. Try something more on the presentation side.

      • Kris Merckx

        Strange reaction. I don’t need “something on the presentation side”. You even don’t know me or what my needs are 🙂 I simply don’t understand that people develop a HTML-WYSIWYG-editor that doesn’t support tables. It’s a great tool, but I think that is a huge lack. It’s like an HTML-editor that removes all the hyperlinks.

        • Mario Putzo

          I think you took my comment as a negative response, which is not, I guess that’s why you think I should know you to say that Quill is probably not what you need – at least in this instance. If you read their docs describing the rationale behind its architecture you’ll find that they are more interested in characters and text in general, than its presentation per se, or tabular data. You are right actually in that tables aren’t only for presentation, they can also represent tabular data, something that Quill doesn’t seem to be willing to address. It is of course not nice that it just removed tables, rather than doing *something* with them. I think the architecture is aimed at “rich text” rather than a WYSIG editor. Nothing wrong with wanting the latter, I myself am struggling to make a decision as I care more about the textual structure (and Deltas) or the way I can display it. I am talking about a specific project here and I think I’ll opt for the former as I am keen to see concurrent editing but we probably have different needs. Nothing.. personal!

    • Andres

      Hi @krismerckx:disqus!! Thanks for reading and thanks for commenting. One of the cool things about open source and git (and github) is that you can just fork the repo and create your own version/flavour of Quill that supports tables!!

      About the “delta/json” format that’s extremely useful for some applications. For example I built this web app (andresinaka.github.io/Transformer/) that is using Quill and the delta format was extremely useful for this application.

      There is no silver bullet in the tech world!

    • Have you tried Froala? People tell us it’s one of the best WYSIWYG editors. It’s quite strange it has been omitted in the alternative options.

      • JP Stones

        I will look into it. thanks Diana