Report an issue

Comments overview

The comments feature lets you add comments to any part of your content, including text, and block elements such as embedded media or images. This is a great way of communication for many authors working on the same document.

Unlock this feature with a CKEditor Paid Plan. Sign up for a free trial, or select the Plan that provides access to all the premium features you need.

# Demo

Test the comments feature in the editor below. Select a passage or a word you need to comment and use the toolbar button Comments to add a comment. Use the sidebar to check the existing ones, and delete comments or comment threads. You can also resolve threads to declutter the sidebar and find them later in the comment archive dropdown Comments archive.

This demo presents a limited set of features. Visit the feature-rich editor example to see more in action.

Commented content is marked as highlighted and a corresponding comment balloon 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. Comments threads can be either deleted or resolved. The latter provides a way to archive comments that are no longer relevant, reducing clutter and making it easier to focus on the most important feedback. Users can access the comments archive from the toolbar and use it to view and restore archived comments if necessary. It helps to simplify the feedback management process. Comments markers are moved along with the content on cut-and-paste and drag-and-drop actions.

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

The sample demo above 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. You can read more about CKEditor 5’s collaboration features and their real-life implementations in this dedicated blog post.

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

# Integration

# Use as a standalone plugin

The comments plugin does not require real-time collaboration to work. If you prefer a more traditional approach to document editing, the 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 collaboration features integration guide.

# Learn more

# Configuration

The configuration details for the comments feature can be found in the CommentsConfig API reference.

# Comments with mentions

It is possible to configure the Mentions feature to work with the Comments feature. Here you can find a detailed description of that process.

# Comments markup

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

  • The <comment-start> and <comment-end> tags are added if the comment starts/ends in text,
  • otherwise, the following attributes are added to elements:
    • data-comment-start-before,
    • data-comment-end-after,
    • data-comment-start-after,
    • data-comment-end-before.

After resolving the comment thread the corresponding markers are no longer highlighted, however, they are still kept in the content. When you activate the annotation displayed in the comments archive, the content will be scrolled to the beginning of the marker, highlighting them at the same time.

If you wish to omit HTML markup for resolved threads in the data (for example, when you export the document), use ignoreResolvedComments flag when you retrieve the document data:

editor.getData( { ignoreResolvedComments: true } );

Read more about the marker-to-data conversion to understand what data you may expect.

# Examples of the possible markup

Comment on text:

<p>They are <comment-start name="b39dd790"></comment-start>awesome<comment-end name="b39dd790"></comment-end>.</p>

Comment on an image:

<figure class="image" data-comment-end-after="b39dd790" data-comment-start-before="b39dd790">
    <img src="foo.jpg">
    <figcaption>Image caption.</figcaption>
</figure>

If your application filters HTML content, for example, to prevent XSS, you need to make sure to leave the comments tags and attributes in place when saving the content in the database. The comment markup is necessary for further editing sessions.

If you need to display the document data without the comments, you can simply remove the comments markup from the document data:

<p>They are awesome.</p>

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

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

# Saving the data with comment highlights

By default, the data returned by editor.getData() contains the markup for the comments as described above. It does not provide the markup that visually shows the comment highlights in the data (similarly to how they are shown in the editor).

It is possible to change the editor output using the showCommentHighlights option passed in editor.getData(). When set, the editor output will return comments similarly to how they are present inside the editor:

editor.getData( { showCommentHighlights: true } );

Will return:

<p>
    <span class="ck-comment-marker">
        Foo
    </span>
    bar
</p>

The output data generated using the showCommentHighlights option cannot be used to load the editor data (it cannot be passed to editor.setData())!

This feature should be used for preview purposes and can be used, for example, together with the export to PDF feature.

The export to PDF feature can be integrated with the comment highlights as shown below:

{
    exportPdf: {
        // More configuration of the Export to PDF.
        // ...
        dataCallback: editor => editor.getData( {
            showCommentHighlights: true
        } )
    }
}

# Comments attributes

The comments attributes are custom data that can be set and used by features built around comments. They may be used to indicate the urgency or severity of comments, categorize them into thematic fields, and so on. You can use attributes to store your feature data with other comment data.

comment.setAttribute( 'isImportant', true );

You can group multiple values in an object, using dot notation:

comment.setAttribute( 'customData.type', 'image' );
comment.setAttribute( 'customData.src', 'foo.jpg' );

Attributes set on the comment can be accessed through the attribute property:

const isImportant = comment.attributes.isImportant;
const type = comment.attributes.customData.type;

You can also observe the attributes property or bind other properties to it:

myObj.bind( 'customData' ).to( comment, 'attributes', attributes => attributes.customData );

Whenever setAttribute() or removeAttribute() is called, the attributes property is re-set, and observables are refreshed. Using these fires the update method in an adapter.

# Comments thread attributes

Similarly, comment thread attributes are custom data that can be set and used by features built around comments. Use it to store your feature data with other comment thread data. You can also group multiple values in an object, using dot notation:

commentThread.setAttribute( 'customData.isImportant', true );

Attributes set on the comment can be accessed through the attribute property:

const isImportant = commentThread.attributes.customData.isImportant;

You can also observe the attributes property or bind other properties to it:

myObj.bind( 'customData' ).to( commentThread, 'attributes', attributes => attributes.customData );

Whenever setAttribute() or removeAttribute() is called, the attributes property is re-set, and observables are refreshed.

# Why comment content is not stored in the document data?

Note that the markers only store the comment thread IDs. They do not include any content for security reasons. If you stored the complete comment discussion with the editor content, a malicious user could edit it, including comments written by other authors. It would be difficult to check which changes in the comments were done by the user when saving data. You would need to analyze the whole content of the document and compare it with the previous version. Considering that both content and comments could change at the same time and they are mixed, it would be a hard task to ensure that only authorized changes were introduced. For these reasons, adapter integration is the recommended solution.

However, if you want to save your content together with the comments data, check the 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 65000 characters. Note that comment content is stored in the HTML format, so the HTML tags (which are invisible to the user) use up some of the character limit. If the limit is exceeded, the user interface will prevent the user from submitting the comment.

# API overview

Check the comments API documentation for detailed information about the comments API. Making yourself familiar with the API may help you understand the code snippets.

# Comments annotations customization

The comments annotations are highly customizable. Please refer to the Annotation customization guide to learn more.

# Comments-only mode

You can run the editor in the “comments-only” mode. In this mode, the user can add, edit and remove comments but is unable to edit the document content or change the document data otherwise.

# Comments for multiple editors

If your application displays multiple editors on one page, you might want to use the context feature. It will, among others, let you display comments from all editors inside one sidebar.

# Comments outside the editor

The comments feature can be also used on regular form-fields or HTML elements. Thanks to that, you can allow for commenting on all elements of your application and provide a unified user experience and interface. See the Comments outside the editor guide to learn more.