This article covers adding the Quill rich text editor to a Laravel Blade view.

The short answer: load two files from a CDN and write one line of new Quill(). No server-side setup and no build step.

Published in 2021 and revised in September 2026. The Quill 1.3.6 used originally has been superseded by the 2.0 line, released in 2024, and both the CDN host and the URLs have changed. Every snippet below is updated to 2.0.3, and the last section covers what breaks when upgrading from 1.x.

Adding Quill to a Blade view

Load the CDN files in the head, then add a div for the editor and a line of script in the body.

Quill can be downloaded from GitHub, but a CDN is simpler here. Quill 2.0 is distributed through jsDelivr at cdn.jsdelivr.net/npm/quill@2.0.3/dist/. The cdn.quilljs.com URLs used by 1.x do not serve 2.0 files, so copying them from an older guide will not work.

<head>
    <script src="https://cdn.jsdelivr.net/npm/quill@2.0.3/dist/quill.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/quill@2.0.3/dist/quill.snow.css" rel="stylesheet">
</head>
<body>
    <div id="quill_editor"></div>
    <script>
      const quill = new Quill('#quill_editor', {
        theme: 'snow'
      });
    </script>
</body>

That is the whole integration.

The Quill rich text editor rendered in a Laravel Blade view

What each part does

The CDN in the head

Two files are required: the JavaScript, and a stylesheet for the theme you use. Quill ships two themes, and each has its own stylesheet.

<script src="https://cdn.jsdelivr.net/npm/quill@2.0.3/dist/quill.js"></script>
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.3/dist/quill.snow.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/quill@2.0.3/dist/quill.bubble.css" rel="stylesheet">

The editor container in the body

Quill turns an existing element into an editor. Give it an id to target.

<div id="quill_editor"></div>

Creating the editor

Pass the selector and an options object. theme is the only one required to get started.

const quill = new Quill('#quill_editor', {
  theme: 'snow'
});

Switching themes

Quill has two themes: snow shows a fixed toolbar above the editor, bubble shows one only when text is selected.

snow

The toolbar sits above the editing area at all times. It is the more conventional choice and works well on desktop.

The Quill editor using the snow theme

bubble

The toolbar appears next to the selection and is hidden otherwise. It saves vertical space, which suits narrow screens.

The Quill editor using the bubble theme

Customising the toolbar

Pass a toolbar array under modules to choose which buttons appear and how they are grouped.

Each inner array becomes a visual group in the toolbar.

const toolbarOptions = [
  [{ 'header': [1, 2, 3, 4, false] }],
  [{ 'align': [] }],
  ['bold', 'italic', 'underline'],
  [{ 'color': [] }, { 'background': [] }],
  [{ 'list': 'ordered' }, { 'list': 'bullet' }],
  [{ 'indent': '-1' }, { 'indent': '+1' }],
  ['image'],
  ['video'],
  ['link']
];

const quill = new Quill('#quill_editor', {
  modules: {
    toolbar: toolbarOptions
  },
  placeholder: 'Write your content here',
  theme: 'snow'
});
A customised Quill toolbar with grouped buttons

Leaving out buttons is as important as adding them. A toolbar offering every option encourages inconsistent formatting; restricting it to what your templates actually render keeps stored content predictable.

Saving the content to Laravel

Quill does not submit its content with a form on its own. Add a hidden input and fill it on submit.

Quill edits the contents of a <div>, which is not a form control and is therefore never posted. Move the value across just before submission:

<form method="POST" action="/posts" id="post_form">
    @csrf
    <div id="quill_editor"></div>
    <input type="hidden" name="body" id="body">
    <button type="submit">Save</button>
</form>

<script>
const quill = new Quill('#quill_editor', { theme: 'snow' });

document.getElementById('post_form').addEventListener('submit', function () {
    document.getElementById('body').value = quill.getSemanticHTML();
});
</script>

getSemanticHTML() is new in Quill 2.0. It returns HTML with Quill’s internal classes stripped out, which is what you want for storage. The 1.x habit of reading quill.root.innerHTML includes those internal classes and is a poor fit for content you intend to render elsewhere.

When rendering it back out, Blade escapes by default. Use {!! !!} to output HTML — but rendering user input unescaped is an XSS risk, so sanitise it either before storing or before display.

{!! $post->body !!}

To load existing content into the editor, use dangerouslyPasteHTML() after initialisation:

quill.clipboard.dangerouslyPasteHTML(@json($post->body));

Upgrading from Quill 1.x to 2.0

Beyond the CDN URLs, the structure of the stored HTML changes. If you already have content saved from 1.x, your display CSS may break.

▼Key changes

Item Quill 1.x Quill 2.0
CDN cdn.quilljs.com/1.3.6/ cdn.jsdelivr.net/npm/quill@2.0.3/dist/
Lists <ul> and <ol> All <ol>, with the type in an attribute
Code blocks A dedicated element <div>
Reading HTML root.innerHTML getSemanticHTML() added
Internet Explorer Supported Dropped
Type definitions @types/quill needed Bundled; remove the package

Lists are the change most likely to bite. In 2.0 unordered lists are emitted as <ol> with the type carried in an attribute. If your display CSS targets ul, bullets saved after the upgrade will look different from ones saved before it.

Check that your rendering CSS does not assume ul before upgrading a site with existing content, because old and new markup will coexist.

The strict and scrollingContainer options were removed, and the clipboard’s pasteHTML is gone. Code carried over unchanged from 1.x tends to fail on those three.

Going further

To widen the font and size choices in the toolbar, see customising font-family in Quill and customising font-size in Quill. Both use the same registration pattern.

If you are still setting up the Laravel side, building a Laravel and Blade environment with Docker covers the environment this editor sits in.

ABOUT ME
りん
On this blog, I mainly share information about web development and programming, along with my daily thoughts and what I’ve learned. I aim to create a blog that lets readers enjoy both technology and everyday life, so I also include topics about daily experiences, books, and gourmet. I’d be delighted if you could drop by casually and find something useful or enjoyable here.