24

I have made a rich text area made with Quill js. I have the next options for the tool bar:

new Quill('#quilljs-container', {
    modules: {
        toolbar: [
           ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
           ['blockquote', 'code-block', 'link'],

           [{ 'header': 1 }, { 'header': 2 }],               // custom button values
           [{ 'list': 'ordered'}, { 'list': 'bullet' }],
           [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
           [{ 'indent': '-1'}, { 'indent': '+1' }],          // outdent/indent
           [{ 'direction': 'rtl' }],                         // text direction

           [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
           [{ 'font': [] }],
           [{ 'align': [] }],

           ['clean']                                         // remove formatting button
       ]
    },
    theme: 'snow'
});
<!-- Style -->
<link href="https://cdn.quilljs.com/1.0.0/quill.snow.css" rel="stylesheet">

<!-- quill js container -->
<div id="quilljs-container">  </div>

<!-- Add quill js on the project -->
<script src="https://cdn.quilljs.com/1.0.0/quill.js"></script>

Currently, when I try to add more types editing the 'font' option on toolbar (e.g. 'font': ['arial']), the select options just display "Sans Serif" instead of display the "Arial" option. What I spect is see the default options ("Sans Serif", "Serif", "Monospace") plus custom options that I want to add.

Also, I have tried the customizing attributors shown on the documentation, but with my current configuration, it just display just the default options. Maybe I'm missing something.

I hope I was clear with my doubt and someone could help me.

UPDATE:

Just to be a little more clear, I am trying to add more fonts following the Quill Container configuration

Container: At the simplest level, toolbar controls can be specified by a simple array of format names.

Black
  • 18,150
  • 39
  • 158
  • 271
albertini07
  • 243
  • 1
  • 2
  • 8

6 Answers6

37

This is what you need.

The process is like this you need 4 components:

  1. A select tag with a ql-font class. This will contain the new font options.
  2. Add the new fonts to the whitelist. This has to be defined before you call the the Quill constructor in Javascript.
  3. Define the font-family for each label in the dropdown. Example: font-family: "Inconsolata"
  4. Define the content font-families that will be used in the text area. Following the example in the 3rd component: .ql-font-inconsolata { font-family: "Inconsolata";}

Update:

I read the documentation in order to help you and they mention that

At the simplest level, toolbar controls can be specified by a simple array of format names...

Alternatively, you can manually create a toolbar in HTML by passing the DOM element or selector into Quill; and that is the solution presented in this answer. On the other hand, the documentation does not mention but after trying many ways to load data using an array (without any success), I noticed that is not possible. So, here is my contribution and the reason why I posted this update. I made the equivalences (JS and HTML) for the manual implementation.

A custom toolbar can be created using HTML and a JS constructor. The constructor will receive the #toolbar-container as a toolbar in the modules section.

Then, you can generate the same structure using only HTML tags. The concept is very similar. For example:

  • If in JS we declare an array like this: ['bold', 'italic', 'underline', 'strike'] in HTML will be:
<span class="ql-formats">
    <button class="ql-bold"></button>
    <button class="ql-italic"></button>
    <button class="ql-underline"></button>
    <button class="ql-strike"></button>
</span>
  • In JS is [{ 'header': 1 }, { 'header': 2 }] in HTML will be
<span class="ql-formats">
   <button class="ql-header" value="1"></button>
   <button class="ql-header" value="2"></button>
</span>

So, here you have a complete example in this code snippet:

// Add fonts to whitelist
let Font = Quill.import('formats/font');
// We do not add Sans Serif since it is the default
Font.whitelist = ['inconsolata', 'roboto', 'mirza', 'arial'];
Quill.register(Font, true);


// We can now initialize Quill with something like this:
let quillObj = new Quill('#quilljs-container', {
  modules: {
    toolbar: '#toolbar-container'
  },
  placeholder: 'This is a font test...',
  theme: 'snow'
});
<!-- Style -->
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<style>
  /* Set dropdown font-families */
  
  #toolbar-container .ql-font span[data-label="Sans Serif"]::before {
    font-family: "Sans Serif";
  }
  
  #toolbar-container .ql-font span[data-label="Inconsolata"]::before {
    font-family: "Inconsolata";
  }
  
  #toolbar-container .ql-font span[data-label="Roboto"]::before {
    font-family: "Roboto";
  }
  
  #toolbar-container .ql-font span[data-label="Mirza"]::before {
    font-family: "Mirza";
  }
  
  #toolbar-container .ql-font span[data-label="Arial"]::before {
    font-family: "Arial";
  }
  /* Set content font-families */
  
  .ql-font-inconsolata {
    font-family: "Inconsolata";
  }
  
  .ql-font-roboto {
    font-family: "Roboto";
  }
  
  .ql-font-mirza {
    font-family: "Mirza";
  }
  
  .ql-font-arial {
    font-family: "Arial";
  }
  /* We do not set Sans Serif since it is the default font */
</style>
<link href="https://cdn.quilljs.com/1.0.0/quill.snow.css" rel="stylesheet">


<div id="standalone-container">
  <div id="toolbar-container">
    <span class="ql-formats">
      <select class="ql-font">
        <option selected>Sans Serif</option>
        <option value="inconsolata">Inconsolata</option>
        <option value="roboto">Roboto</option>
        <option value="mirza">Mirza</option>
        <option value="arial">Arial</option>
      </select>
      <select class="ql-size"></select>
    </span>
    <span class="ql-formats">
      <button class="ql-bold"></button>
      <button class="ql-italic"></button>
      <button class="ql-underline"></button>
      <button class="ql-strike"></button>
    </span>
    <span class="ql-formats">
      <select class="ql-color"></select>
      <select class="ql-background"></select>
    </span>
    <span class="ql-formats">
      <button class="ql-blockquote"></button>
      <button class="ql-code-block"></button>
      <button class="ql-link"></button>
    </span>
    <span class="ql-formats">
      <button class="ql-header" value="1"></button>
      <button class="ql-header" value="2"></button>
    </span>
    <span class="ql-formats">
      <button class="ql-list" value="ordered"></button>
      <button class="ql-list" value="bullet"></button>
      <button class="ql-indent" value="-1"></button>
      <button class="ql-indent" value="+1"></button>
    </span>
    <span class="ql-formats">
      <button class="ql-direction" value="rtl"></button>
      <select class="ql-align"></select>
    </span>
    <span class="ql-formats">
      <button class="ql-script" value="sub"></button>
      <button class="ql-script" value="super"></button>
    </span>
    <span class="ql-formats">
      <button class="ql-clean"></button>
    </span>
  </div>
</div>
<!-- quill js container -->
<div id="quilljs-container"></div>
<!-- Add quill js on the project -->
<script src="https://cdn.quilljs.com/1.0.0/quill.js"></script>
Teocci
  • 7,189
  • 1
  • 50
  • 48
  • 1
    **_"You cannot use the JavaScript constructor to create a custom font selection"_**; do you know if the Quill documentation mentions something about it? It would be even clearer. – albertini07 May 02 '17 at 13:48
  • First did you try this solution? – Teocci May 02 '17 at 13:51
  • 4
    Second, I expend one hour reading all documentation in order to help you. They mention that *At the simplest level, toolbar controls can be specified by a simple array of format names... Alternatively you can manually create a toolbar in HTML, and pass the DOM element or selector into Quill.* And that is the solution that I presented in this answer. So they do not mention that but after trying many way to load the data using the array I notices that you cannot. That is my contribution. That is why I posted an update with the equivalences (JS and HTML) – Teocci May 02 '17 at 13:59
  • Yes, and it works. What you mention is very helpful. I just want to know if that is in the documentation and I ignored it. – albertini07 May 02 '17 at 14:05
  • I appreciate your contribution and the time you spent to help on this solution, but as I mentioned, I just wanted to make it clear to people who might have this same doubt in the future. – albertini07 May 02 '17 at 14:13
  • Could you be so kind to update your answer adding your second statement (related to Quilljs) in order to make your answer as accepted? – albertini07 May 02 '17 at 14:29
  • @albertini07 I updated as you requested. Happy coding – Teocci May 02 '17 at 14:42
  • @albertini07 I know the problem has already been resolved, but I would just like to inform everybody that, besides the official website, more information about this tool with examples and questions with answers can be found at the following link: https://github.com/loagit/Quill-Examples-and-FAQ – Loa Jan 13 '20 at 19:06
12

You CAN use the JavaScript constructor to create a custom font selection.

From the Quill Quickstart page here's the basic HTML -

    <!-- Include stylesheet -->
    <link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
    
    <!-- Create the editor container -->
    <div id="editor">
      <p>Hello World!</p>
      <p>Some initial <strong>bold</strong> text</p>
      <p><br></p>
    </div>
    
    <!-- Include the Quill library -->
    <script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>

The code required in the JavaScript initialiser is along the lines of the following:

    let Font = Quill.import('formats/font');
    Font.whitelist = ['times-new-roman', 'arial'];
    Quill.register(Font, true);

    let toolbarOptions = [
        [{ 'font': ['', 'times-new-roman', 'arial'] }],

        ['clean']                                         // remove formatting button
    ];
    
    let quill = new Quill('#editor', {
        modules: {
            toolbar: toolbarOptions
          },
        theme: 'snow'
        });

You also need to add the following to your stylesheet where the names in the CSS selectors are those names in the above JavaScript:

    /* Set droplist names - -item is the currently selected font, -label is the font's appearance in the droplist*/
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value='']::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value='']::before
    {
      content: 'Default';
    }
    
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value='times-new-roman']::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value='times-new-roman']::before
    {
      content: 'Times New Roman';
      font-family: 'Times New Roman';
    }
    
    .ql-snow .ql-picker.ql-font .ql-picker-label[data-value='arial']::before,
    .ql-snow .ql-picker.ql-font .ql-picker-item[data-value='arial']::before
    {
      content: 'Arial';
      font-family: 'Arial';
    }

    /****************************************************
    Set the font-family content used for the HTML content.
    *****************************************************/
    .ql-font-arial {
      font-family: 'Arial';
    }
    
    .ql-font-times-new-roman {
      font-family: 'Times New Roman';
    }
Anbuselvan Rocky
  • 606
  • 6
  • 22
Steve B
  • 121
  • 1
  • 6
  • I found that fonts with a dash in the key don't work when used as the initial content as the control (via HTML). aka, had to change 'times-new-roman' to 'timesnewroman' in your example – Jan Van der Haegen Mar 09 '22 at 13:23
9

FWIW, I've copied the code from Steve B and made it more generic. This way you don't need to do all the copy pasting of css rules, etc... just specify the fonts you would like adding in your fonts array.

// specify the fonts you would 
var fonts = ['Arial', 'Courier', 'Garamond', 'Tahoma', 'Times New Roman', 'Verdana'];
// generate code friendly names
function getFontName(font) {
    return font.toLowerCase().replace(/\s/g, "-");
}
var fontNames = fonts.map(font => getFontName(font));
// add fonts to style
var fontStyles = "";
fonts.forEach(function(font) {
    var fontName = getFontName(font);
    fontStyles += ".ql-snow .ql-picker.ql-font .ql-picker-label[data-value=" + fontName + "]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=" + fontName + "]::before {" +
        "content: '" + font + "';" +
        "font-family: '" + font + "', sans-serif;" +
        "}" +
        ".ql-font-" + fontName + "{" +
        " font-family: '" + font + "', sans-serif;" +
        "}";
});
var node = document.createElement('style');
node.innerHTML = fontStyles;
document.body.appendChild(node);

var toolbarOptions = [
    ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
    ['blockquote', 'code-block'],

    [{ 'header': 1 }, { 'header': 2 }],               // custom button values
    [{ 'list': 'ordered'}, { 'list': 'bullet' }],
    [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
    [{ 'indent': '-1'}, { 'indent': '+1' }],          // outdent/indent
    [{ 'direction': 'rtl' }],                         // text direction

    [{ 'size': ['small', false, 'large', 'huge'] }],  // custom dropdown
    [{ 'header': [1, 2, 3, 4, 5, 6, false] }],

    [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
    [{ 'font': fontNames }],
    [{ 'align': [] }],

    ['clean']                                         // remove formatting button
];

// Add fonts to whitelist
var Font = Quill.import('formats/font');
Font.whitelist = fontNames;
Quill.register(Font, true);

var quill = new Quill('#editor', {
    modules: {
        toolbar: toolbarOptions
    },
    theme: 'snow'
});
Thomas
  • 1,967
  • 2
  • 15
  • 22
7

Had to make some updates to @Thomas' answer, but the code below automates things nicely in Quill v1.3.6. If you have a short list of fonts then the required CSS is trivial; but if you have a larger and/or dynamic list you'll want to automate as follows:

// Specify Quill fonts
var fontList = ['Arial', 'Courier', 'Garamond', 'Tahoma', 'Times New Roman', 'Verdana'];
var fontNames = fontList.map(font => getFontName(font));
var fonts = Quill.import('attributors/class/font');
fonts.whitelist = fontNames;
Quill.register(fonts, true);

// Add fonts to CSS style
var fontStyles = "";
fontList.forEach(function(font) {
    var fontName = getFontName(font);
    fontStyles += ".ql-snow .ql-picker.ql-font .ql-picker-label[data-value=" + fontName + "]::before, .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=" + fontName + "]::before {" +
        "content: '" + font + "';" +
        "font-family: '" + font + "', sans-serif;" +
        "}" +
        ".ql-font-" + fontName + "{" +
        " font-family: '" + font + "', sans-serif;" +
        "}";
});

// Configure Quill editor options
var toolbarOptions = [
    [{ 'font': fonts.whitelist }],
    ['bold', 'italic', 'underline'],
    ['clean'] 
];

var quill;
$(function() {
    // Append the CSS stylesheet to the page
    var node = document.createElement('style');
    node.innerHTML = fontStyles;
    document.body.appendChild(node);

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

// Generate code-friendly font names
function getFontName(font) {
    return font.toLowerCase().replace(/\s/g, "-");
}

The relevant link to the Quill docs is https://quilljs.com/guides/how-to-customize-quill/#customizing-attributors, although the examples provided here are rather incomplete.

OfficeAddinDev
  • 1,105
  • 3
  • 15
  • 29
  • I took your example and transposed it into react with Class Components in typescript. I had fun with the typings. – JF Gagnon Jan 10 '23 at 16:13
3

Accepted answer is mostly great but it's important to notice, that formats/font is actually wrong and doesn't work with tested Quill 1.3.7.

What worked for me was:

let fonts = Quill.import("formats/font");

let fonts = Quill.import("attributors/style/font");
fonts.whitelist = ["initial", "sans-serif", "serif", "monospace"];
Quill.register(fonts, true);

Ilia Ross
  • 13,086
  • 11
  • 53
  • 88
2

Was able to get to this code thanks to this answer here . I found a better answer, just update your js and css with the code I have below

// add an array of values
const fontFamilyArr = ["Roboto Condensed", "Times New Roman", "Calibri", "Calibri Light", "Sans-Serif"];
let fonts = Quill.import("attributors/style/font");
fonts.whitelist = fontFamilyArr;
Quill.register(fonts, true);

const fontSizeArr = ['10px', '11px', '12px', '14px', '18px', '24px'];
var Size = Quill.import('attributors/style/size');
Size.whitelist = fontSizeArr;
Quill.register(Size, true);

var toolbarOptions = [
  [{
    'size': fontSizeArr
  }],
  [{
    'font': fontFamilyArr
  }]
];

var quill = new Quill('#mail-body-editor', {
  modules: {
    toolbar: toolbarOptions
  },
  theme: 'snow',
  placeholder: 'Please provide the content of your mail here'
});
/*Adding the values from the array which has the values as data-values*/


/*for font-size*/

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value]::before {
  content: attr(data-value) !important;
}


/*for font-family*/

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value]::before {
  content: attr(data-value) !important;
}

.ql-snow .ql-picker.ql-font {
  width: 150px !important;
  white-space: nowrap;
}
<!DOCTYPE html>
<html lang="en">

<body>
  <link href="//cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
  <link href="//cdn.quilljs.com/1.3.6/quill.bubble.css" rel="stylesheet">
  <script src="//cdn.quilljs.com/1.3.6/quill.min.js"></script>
  <div id="mail-body-editor"></div>

</body>

</html>
  • Hey, welcome to StackOverflow! Could you please edit your post for more details? Why is your answer the correct answer? – Chris van Chip Oct 20 '21 at 07:32
  • 1
    hey @ChrisvanChip, in the accepted answer we have to add html code along with the necessary font-styling through css, with the method I've mentioned, you have to just provide an array of font-names which u need and initialise it and you're done. Hope this clarifies my post – KIRAN KUMAR Nov 24 '21 at 15:03