Report an issue

guideComments overview

The Comments plugin makes it possible to add comments to any part of rich-text content in CKEditor 5, including text and block elements such as embedded media or images.

Commented content is marked as highlighted and a corresponding comment is displayed in the sidebar or inline. Comments can be added, edited, deleted and replied to, allowing the users to collaborate on the same document directly in the rich-text editor.

Comment threads can be displayed in a sidebar or as inline balloons. See the Comments display mode guide to learn how to configure the display mode.

This sample automatically switches between display modes according to the screen size. Resize the window and observe how the editor changes its appearance.

The comments feature can be used together with real-time collaboration or as a standalone plugin where the comments are saved in your application using a custom integration.

A comments-only mode is available, too, if you want to limit the user permissions and only allow them to add comments to the document, but not edit it directly.

# Use as a standalone plugin

The comments plugin does not require real-time collaboration to work. If you prefer a more traditional approach with asynchronous document editing, comments can be added to CKEditor 5 just like any other plugin.

To learn how to integrate comments as a standalone plugin, refer to the Integrating comments with your application guide.

# Use with real-time collaboration

If you are using the real-time collaboration feature, refer to the Real-time collaborative features integration guide.

# Comments markup

Comments are always attached to some place in the document. To make sure that they will not be lost, the comments plugin adds some special markup to the document:

> editor.getData();
<- '<p>They are <comment id="b39dd790" type="start"></comment>awesome<comment id="b39dd790" type="end"></comment>.</p>'

The position of a comment in the content is marked with a custom <comment> tag. Separate elements for the beginning and the end of a comment are used to make it easier to process the content (e.g. before rendering it on your website).

Note that if your application filters HTML content, for example to prevent XSS, make sure to leave the <comment> tags in place when saving the content in the database. The comment markup is necessary for further editing sessions.

So, with the example content above, to display the document on your website the <comment> tags may be removed:

<p>They are awesome.</p>

When launching the editor, though, make sure to include them in the HTML:

<div id="container">
    <div id="editor">
        <p>They are <comment id="b39dd790" type="start"></comment>awesome<comment id="b39dd790" type="end"></comment>.</p>
    </div>
    <div id="sidebar"></div>
</div>

# Why is there no comments data in content?

Note that markers only store comment thread IDs. Why do they not include any content?

The reason is security. If you stored the whole comment discussion with the editor content, a malicious user could edit it, including comments written by other authors. It would be very hard to check which changes in the comments the user has done when saving data. You would need to deeply analyze the whole content of the document and compare it to the previous version. Considering that both content and comments could change at the same time and they are mixed, it would be a very hard task to be sure that only authorized changes were introduced. For those reasons, adapter integration is the recommended one.

Obviously now, when comment markers are stored in the content, one can change the comment marker positions, but these are the changes that the users are allowed to do in the editor anyway.

However, if you want to save your content together with the comments data, check A simple “load and save” integration guide which should help you.

# Characters limit

For technical reasons, each comment in the thread has a character limit set to 4000 characters. Note that comment content is stored in the HTML format, so the HTML tags (which are invisible for the user) use up some characters. Nevertheless, the 4000 characters limit allows you to create a really long comment and should be sufficient for any use case. If the limit is exceeded, the user interface will prevent the user from submitting the comment.

# Commands

The comments plugin adds a set of commands to the editor. These commands are executed when you click the toolbar button to start a new comment thread, add a comment to an existing thread, etc. You do not need to care about the commands if you are integrating the comments plugin together with the UI part. However, knowing about them might be useful if you are working on a custom UI.

The following commands are available:

  • addCommentThread – Adds a new comment thread based on the current selection. A newly created thread has no comments. This command is executed when the user clicks the “Comment” button in the editor toolbar.
  • addComment – Adds a new comment to a comment thread.
  • updateComment – Updates an existing comment.
  • removeComment – Removes a comment from a comment thread.
  • removeCommentThread – Removes a comment thread.

The above commands use the following parameters:

  • threadId – The comment thread ID, which is equal to the ID of the comment thread marker.
  • commentId – The comment ID.
  • content – The comment content.

Examples:

editor.execute( 'addCommentThread', { threadId: 'thread-1' } );

// If `threadId` is not specified, `addCommentThread()` will generate a unique ID and use it:
editor.execute( 'addCommentThread' );

editor.execute( 'addComment', { threadId: 'thread-1', commentId: 'comment-1', content: '<p>foo</p>' } );

// If `commentId` is not specified, `addComment()` will generate a unique ID and use it:
editor.execute( 'addComment', { threadId: 'thread-1', content: '<p>foo</p>' } );

editor.execute( 'updateComment', { commentId: 'comment-1', content: '<p>foo</p>' } );

editor.execute( 'removeComment', { commentId: 'comment-1' } );

editor.execute( 'removeCommentThread', { threadId: 'thread-1' } );

# Comment editor customization

The editor used for adding and editing comments is also a CKEditor 5 instance. By default it uses the following list of plugins:

These plugins allow for creating the comment content with some basic styles.

However, it is possible to extend the comment editor configuration and add some extra plugins or even overwrite the entire configuration and replace the list of plugins. You can modify the comment editor configuration by using the comments.editorConfig property in the main editor configuration.

See the sample below to learn how to add the Mention plugin to the comment editor:

const MentionPlugin = ClassicEditor.builtinPlugins.find( plugin => plugin.pluginName == 'Mention' );

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        toolbar: {
            items: [ 'bold', 'italic', '|', 'comment' ]
        },
        sidebar: {
            container: document.querySelector( '#sidebar' )
        },
        comments: {
            editorConfig: {
                extraPlugins: [ MentionPlugin ],
                mention: {
                    feeds: [
                        {
                            marker: '@',
                            feed: [ '@Barney', '@Lily', '@Marshall', '@Robin', '@Ted' ],
                            minimumCharacters: 1
                        }
                    ]
                }
            }
        }
    } )
    .catch( error => console.error( error ) );

Note that additional plugins need to be a part of the same build just like the main editor plugins. They do not need to be enabled in the main editor but make sure that they are in the build. Refer to the Installing plugins guide to learn more.

See comments-with-mentions in the ready-to-use comments integration samples to find the full code sample.

# Theme customization

Using the power of CSS Variables it is really easy to override the default design of comments. This action can be done by adding an extra .css file.

CSS Variables in comments added to the document created in CKEditor 5 WYSIWYG editor.

The image above shows you which variables are responsible for every component of the comments sidebar.

# Example of comments customization with CSS Variables

With Inheritance of CSS Variables you can change the default :root values of variables in the .ck-sidebar scope. You can easily override these properties with a .css file or place your customizations directly into the <head> section of your page, but in this case you will need to use a more specific CSS selector than :root (e.g. <body>).

Check out the color sheet for the full list of customizable colors. You can also browse other files with CSS Variables in CKEditor 5.

/* Change the default yellow color of the comment marker in the content to green. */
:root {
    --ck-color-comment-marker: hsl(127, 98%, 83%);
    --ck-color-comment-marker-active: hsl(127, 98%, 68%);
}

.ck-sidebar {
    --ck-color-comment-background: #ecf5f0;
    --ck-color-comment-separator: #64ca6d;
    --ck-color-comment-remove-background: #eccbcb;

    --ck-color-comment-count: #807e81;

    --ck-color-annotation-icon: #0f5c2f;
    --ck-color-annotation-info: #1eb35c;

    --ck-annotation-button-size: 0.85em;

    --ck-user-avatar-background: #239855;
}

/* You can even change the appearance of a single element. */
.ck-sidebar .ck-comment__wrapper:first-of-type {
    --ck-color-annotation-info: #8e9822;
    --ck-user-avatar-background: #8e9822;
}

The examples above will generate the following comments designs:

Custom CSS Variables in comments added to the document created in CKEditor 5 WYSIWYG editor.