Update to CKEditor 5 v41.x
When updating your CKEditor 5 installation, ensure all the packages are the same version to avoid errors.
For custom builds, you may try removing the package-lock.json or yarn.lock files (if applicable) and reinstalling all packages before rebuilding the editor. For best results, make sure you use the most recent package versions.
Released on April 10, 2024. (See full release notes)
CKEditor 5’s latest update brings a new premium feature: the multi-level list feature. It allows for easy creation and modification of numbered lists with counters (1., 1.1., 1.1.1), crucial for clear referencing and hierarchical organization in complex documents. The feature ensures compatibility with Microsoft Word. When lists with such formatting are pasted to the editor, the numbering format and counters are retained.
No more breaking numbering of lists when they are pasted from Office. Previously whenever a list was split by paragraphs, the counter started again from 1. With our latest improvement, the counter is correctly preserved. Moreover, if you use Paste from Office Enhanced ⭐️, the paragraphs will be merged into list items to ensure proper semantic content.
⚠️ If you use the LegacyList plugin to prolong the migration to the new list implementation, bear in mind that from this release Paste from Office stops working for the lists’ implementation you are using. Migrate to List to maintain pasting lists functionality.
The menu bar is a user interface component popular in large editing desktop and online packages. It gives you access to all features provided by the editor, organized in menus and categories. It improves usability of the editor, keeping the toolbar simple and tidy. This is especially welcome in heavily-featured editor integrations.
The current release brings this battle-hardened solution to CKEditor 5! The menu bar can easily be enabled in selected editor types, comes with handy features preset, and is also highly configurable.
This release brings in a fix for keyboard navigation with the Tab key. Before, it followed the default browser behavior, which could produce somewhat random effects. For example, when the cursor was positioned at the end of the editable, the Tab keystroke could navigate you to the image caption on the top.
We changed it to an approach in which the Tab (and Shift+Tab), navigates to the next focusable field or an element outside the editor so that the users can quickly navigate fields or links on the page. The navigation in the editor itself should be done by arrows, rather.
There is one exception to the Tab behavior. When a widget is selected, the Tab key will move the selection to the first nested editable, such as the caption of an image. Pressing the Esc key, while inside a nested editable, will move the selection to the closest ancestor widget, for example: moving from an image caption to selecting the whole image widget.
- image: The CSS custom property
--ck-color-image-caption-highligted-backgroundhas been renamed to--ck-color-image-caption-highlighted-background. Please make sure to update your custom CSS accordingly. - real-time-collaboration: The username displayed next to the user marker in the edited content is no longer a CSS pseudo-element. Use the
.ck-user__marker-tooltipCSS class to customize usernames instead. - ai: When
config.ai.openAI.requestParametersorconfig.ai.aws.requestParametersare set, the set value will fully overwrite the default value. Most importantly, if you do not specify some properties inrequestParametersthey will not be set to default. For example, if you setopenAI.requestParametersto{ max_tokens: 1000 }, the request parameters will be set exactly to that object. Make sure that you pass all necessary parameters inrequestParameters. Important: this change happened in version 41.2.0 but has not been previously announced in the changelog. - upload: The
FileDialogButtonViewclass has been moved fromckeditor5-uploadtockeditor5-ui. Please update your import paths accordingly (was:import { FileDialogButtonView } from 'ckeditor5/src/upload.js';, is:import { FileDialogButtonView } from 'ckeditor5/src/ui.js';). - theme-lark: The default vertical spacing around
ButtonViewinListItemView(--ck-list-button-padding) has been reduced for better readability. This affects the presentation of various editor features that use this type of UI (headings, font size, font family, etc.). You can restore the previous value by setting--ck-list-button-padding: calc(.2 * var(--ck-line-height-base) * var(--ck-font-size-base)) calc(.4 * var(--ck-line-height-base) * var(--ck-font-size-base));in your custom styles sheet. - comments: From this release on, the UI of the Comments Archive feature is displayed in a dialog instead of a dropdown.
- revision-history: The UI for saving the new revision is displayed in a dialog instead of a dropdown.
As of this release, due to a bug that needed fixing, the legacy lists plugin (lists v1 ) is no longer compatible with the paste from Office feature. List items will be added as paragraphs instead. Please consider upgrading to the modern list plugin to avoid it.
Released on March 6, 2024. (See full release notes)
Since the beginning, collaboration has been a focal point for CKEditor 5. This release brings another highly anticipated improvement for the popular comments feature!
Now, when you cut-paste, copy-and-paste, or drag around a piece of content that includes comments, the comments will be retained. The improvement allows users to restructure their content without losing the information or discussion available in the comments.
By default, the comments are retained only on cut-and-paste and drag-and-drop actions. You can configure this behavior to be applied also on copy-paste or you can turn it off.
CKEditor 5 v41.2.0 introduces the Accessibility Help Dialog. With the hit of Alt/Option+0 in the editor, users can now access the full list of available keyboard shortcuts. A toolbar button is available as well. This feature further improves the editor’s usability and accessibility. It allows all users to navigate and operate CKEditor 5 more efficiently, thereby promoting a more inclusive user experience.
The Accessibility Help Dialog is enabled by default in the Essentials plugin pack, making it available straight away in most integrations. If your editor build does not use the Essentials pack, make sure that you add the AccessibilityHelp plugin in your configuration.
- comments: Comments will now be retained in the clipboard and pasted into the content when the user performs a cut-and-paste operation. To revert to the previous behavior (with no retaining), set the
comments.copyMarkersconfiguration property to an empty array. - ui: The contents of the
BlockToolbarandBalloonToolbartoolbars are now filled on theEditorUIReadyEventinstead ofPlugin#afterInit(). - ai: When
config.ai.openAI.requestParametersorconfig.ai.aws.requestParametersare set, the set value will fully overwrite the default value. Most importantly, if you do not specify some properties inrequestParametersthey will not be set to default. For example, if you setopenAI.requestParametersto{ max_tokens: 1000 }, the request parameters will be set exactly to that object. Make sure that you pass all necessary parameters inrequestParameters.
Released on February 7, 2024. (See full release notes)
- engine: We fixed how the missing
valueof the"class"and"style"attribute conversion is handled in theattributeToAttribute()upcast helper. Now while not providing the attribute’svalueto conversion the helper accepts and consumes all values. Previously those values were not consumed and left for other converters to convert. Note that you should use theclassesand thestylesfields for the fine-tuned conversion of those attributes instead of a catch-all"style"and"class"specified in thekeyfield. - font: The
colorSelectorViewproperty will no longer be accessible from theColorUIplugin in the@ckeditor/ckeditor5-font/src/ui/colorui.ts. - source-editing: The source editing feature will now throw an error when used with real-time collaboration as these features are not fully compatible and may lead to data loss. You will have to explicitly enable source editing for real-time collaboration by setting the
sourceEditing.allowCollaborationFeaturesconfiguration flag totrue. If you want to use both these features, please read a new guide discussing the risks and add the flag to your configuration.
Released on January 17, 2024. (See full release notes)
Below are the most important changes that require your attention when upgrading to CKEditor 5 v41.0.0.
As of the latest release, we replaced the existing list plugin (often referred to as “list v1”) with the newer and more advanced document list plugin, formerly known as document list (“list v2”).
We implemented the list v2 (document list) feature in 2022 to add support for block content in list items. It supported extending list markup via General HTML Support (GHS). It did not, however, support to-do lists. Since then we concentrated on bringing full list v1 functionality to this plugin. The newest release brings in the complete list functionality so we were ready to switch.
We introduced the new plugin in a manner that aims to be transparent for the users:
- We physically replaced the old plugin with the new one.
- But we left the namespace intact.
It means that starting with release v41.0.0 all imports of various list-related plugins will use the new version.
Unless you need to specifically use the old plugin in your integration, there is no need to make changes in the configuration.
If you do not want to use block elements in your lists, you can turn off this functionality with the configuration option instead of sticking to the old plugins.
We have replaced the old list plugins with the current ones.
With the new version becoming the default, the DocumentList plugin (and all related plugins, see the table below) was renamed to List. The old plugin was renamed to LegacyList instead. The same applies to all other list-related plugins, namely: LegacyListProperties, and LegacyTodoList.
If you included document lists in your integration and used the removePlugins option to exclude the old list plugin, it could lead to errors, such as these:
❌ CKEditorError: plugincollection-required {"plugin":"List","requiredBy":"DocumentList"}
Read more: https://ckeditor.com/docs/ckeditor5/latest/support/error-codes.html#error-plugincollection-required
This is because your integration was injecting DocumentList and DocumentListProperties plugins, and passing the removePlugins: [ List, ListProperties, TodoList ] configuration option. After the change and renaming of the plugins, these two are the same.
If you happen to encounter this error, remove all imports of DocumentList and related plugins as well as the removePlugins configuration option. Replace these with List and related plugins.
| Previous version | Current version | Comments |
|---|---|---|
| Official plugins | ||
DocumentList |
List |
Plugin renamed |
DocumentListProperties |
ListProperties |
Plugin renamed |
TodoDocumentList |
TodoList |
Plugin renamed |
AdjacentListsSupport |
AdjacentListsSupport |
Changed import path |
| Backward compatibility plugins | ||
| - | `DocumentList` | Alias for the List plugin |
| - | `DocumentListProperties` | Alias for the ListProperties plugin |
| - | `TodoDocumentList` | Alias for the TodoList plugin |
| Legacy plugins | ||
List |
LegacyList |
Plugin renamed |
ListProperties |
LegacyListProperties |
Plugin renamed |
TodoList |
LegacyTodoList |
Plugin renamed |
| Removed deprecated plugin | ||
ListStyle |
- | Use the ListProperties plugin instead. |
With the old list plugin, it was possible to create two lists of the same type but with different styles next to each other. These lists did not merge. This functionality is still available in the LegacyList.
The current List plugin merges such lists. This can be handled by using the AdjacentListsSupport plugin. However, by design, it only works for pasted content or on data load. It does not support UI operations, which is a change from the previous behavior.
We want to use this opportunity and ask the users for feedback in this GitHub issue. If you use this kind of lists, feel free to share your opinion and suggestions on the current implementation.
Among other changes, some icons were moved around the project. Check these changes if you use custom UI elements that call these icons.
The following icons were moved to the @ckeditor/ckeditor5-core package:
browse-filesbulletedlistcodeblockcolor-paletteheading1,heading2,heading3,heading4,heading5,heading6horizontallinehtmlindentnext-arrownumberedlistoutdentprevious-arrowredotabletodolistundo
The following icons were moved to the ckeditor5-collaboration package:
paint-rollerrobot-penciltable-of-contentstemplate
Some export names were changed due to the possibility of name conflicts:
- We renamed the default export of
Viewfrom the@ckeditor/ckeditor5-enginepackage toEditingView. - We renamed the export of
Modelfrom the@ckeditor/ckeditor5-uipackage toViewModel. - We renamed the default export of
UploadAdapterfrom the@ckeditor/ckeditor5-adapter-ckfinderpackage toCKFinderUploadAdapter. - We renamed the interface export of
Positionfrom the@ckeditor/ckeditor5-utilspackage toDomPoint. - We moved the
findOptimalInsertionRangefunction to theSchemaclass as a method within the@ckeditor/ckeditor5-enginepackage. The exported function of the same name from the@ckeditor/ckeditor5-widgetpackage remains unchanged and should be used while creating features and widgets.
The code we distribute in the npm packages uses the ECMAScript Module (ESM) syntax (for example, import X from 'y'). Until now it was not fully compliant with the standard and the packages were not properly marked as ES modules. Sometimes this resulted in bundlers (like Vite) and other tools (such as Vitest) failing to build or run the projects containing CKEditor 5. It required workarounds in their configuration.
This release fixes the ESM compatibility issues. CKEditor 5 packages are now fully ESM-compliant and these workarounds are no longer needed.
Until now, the form for adding a URL to the selected text accepted an empty value, leaving the href empty. We believe this is undesirable in most cases. We have added a validation to prevent adding a link if the field is empty.
However, if for some reason you want to allow empty links, you can do so using the new config.link.allowCreatingEmptyLinks configuration option added to the link plugin.
ClassicEditor
.create( editorElement, {
link: {
+ allowCreatingEmptyLinks: true
}
} )
.then( ... )
.catch( ... );
Starting with v41.0.0, the UI of the find and replace feature displays by default in a dialog window. Before, it was displayed in a dropdown panel. This change is meant to improve the overall user experience of the feature and allow content creators to make the most out of the available tools.

To bring the earlier user experience back, you can use the config.findAndReplace.uiType configuration option:
ClassicEditor
.create( editorElement, {
+ findAndReplace: {
+ uiType: 'dropdown'
+ }
} )
.then( ... )
.catch( ... );
The migration from a dropdown panel to a dialog window brought some changes to the DOM structure of the UI. Customizations based on certain CSS selectors may not work anymore and may require adjustments.
- The UI header element (
div.ck-form__header) is no longer available inside the form element (form.ck-find-and-replace-form). You should apply the CSS customizations to the header element of the dialog instead (.ck.ck-dialog .ck.ck-form__header). - The
fieldset.ck-find-and-replace-form__findelement was removed from the form element (form.ck-find-and-replace-form). Its contents were distributed between new containers:- The “Find in text” input field, and the “Previous result” and “Next result” buttons were moved to the
div.ck-find-and-replace-form__inputselement. - The “Find” button was moved to the
div.ck-find-and-replace-form__actionselement.
- The “Find in text” input field, and the “Previous result” and “Next result” buttons were moved to the
- The
fieldset.ck-find-and-replace-form__replaceelement was removed. Its contents were distributed between new containers:- The “Replace with” input field was moved to the
div.ck-find-and-replace-form__inputselement. - The “Replace” and “Replace all” buttons were moved to the
div.ck-find-and-replace-form__actionselement.
- The “Replace with” input field was moved to the
- The “Advanced options” dropdown (rendered as the
div.ck-options-dropdownelement) was replaced with the collapsible component (rendered as thediv.ck-collapsibleelement). Switch buttons inside (“Match case” and “Whole words only”) remain unchanged.
Starting with v41.0.0, the UI of the AI assistant feature will display by default in a dialog window. It was displayed in the balloon panel before.

The migration from a dropdown panel to a dialog window brought some changes to the DOM structure of the UI. Customizations based on certain CSS selectors may not work anymore and may require adjustments.
- The UI header element (
div.ck-form__header) is no longer available inside the form element (form.ck-ai-form). You should apply CSS customizations to the header element of the dialog instead (.ck.ck-dialog .ck.ck-form__header).
- ai: From this release on, the UI of the AI Assistant feature is displayed in a dialog instead of a balloon. See #14973.
- find-and-replace: From this release on, the UI of the find and replace feature is displayed by default in a dialog instead of a dropdown. To bring the previous user experience back, you can use the
config.findAndReplace.uiTypeconfiguration option. See #14973. - list: The
AdjacentListsSupportplugin is moved from thedocumentlistdirectory to thelistdirectory. See #14942.
- adapter-ckfinder: Rename export of the
UploadAdapterclass toCKFinderUploadAdapter. See #15511. - ai: The layout of the UI changed. Customizations based on certain CSS selectors may not work anymore because of a different DOM structure in the UI. Learn more about the scope of changes. See #14973.
- ckfinder: Moved the
browseFilesicon to thecorepackage and added it to theiconsobject exported from it. See #15511. - ckbox: Moved the
browseFilesicon to thecorepackage and added it to theiconsobject exported from it. See #15511. - code-block: Moved the
codeBlockicon to thecorepackage and added it to theiconsobject exported from it. See #15511. - core: Bumped the TypeScript version to 5.0. See #15452.
- engine: Renamed export of the
Viewclass toEditingView. See #15511. - engine: Moved the
findOptimalInsertionRangefunction to theSchemaclass as a new method. See #15511. - find-and-replace: The layout of the UI changed. Customizations based on certain CSS selectors may not work anymore because of a different DOM structure in the UI. Learn more about the scope of changes. See #14973.
- heading: Moved the
heading1,heading2,heading3,heading4,heading5, andheading6icons to thecorepackage and added them to theiconsobject exported from it. See #15511. - horizontal-line: Moved the
horizontalLineicon to thecorepackage and added it to theiconsobject exported from it. See #15511. - html-embed: Moved the
htmlicon to thecorepackage and added it to theiconsobject exported from it. See #15511. - indent: Moved the
indentandoutdenticons to thecorepackage and added them to theiconsobject exported from it. See #15511. - link: Added validation to the URL field to disallow empty URLs by default. See #12501.
- list: All old list plugins are now prefixed with
Legacy(including directory names):List->LegacyList,ListProperties->LegacyListProperties,TodoList->LegacyTodoList,ListEditing->LegacyListEditing,ListUtils->LegacyListUtils,ListPropertiesEditing->LegacyListPropertiesEditing,TodoListEditing->LegacyTodoListEditing. See #14942. - list: The document list plugins are no longer prefixed with
Document(including directory names):DocumentList->List,DocumentListProperties->ListProperties,TodoDocumentList->TodoList,DocumentListEditing->ListEditing,DocumentListUtils->ListUtils,DocumentListPropertiesEditing->ListPropertiesEditing,DocumentListPropertiesUtils->ListPropertiesUtils,TodoDocumentListEditing->TodoListEditing. See #14942. - list: The
ListStyleplugin was removed since it had been deprecated for a while. Use theListPropertiesplugin instead. See #14942. - list: Moved the
bulletedList,numberedList, andtodoListicons to thecorepackage and added them to theiconsobject exported from it. See #15511. - table: Moved the
tableicon to thecorepackage and added it to theiconsobject exported from it. See #15511. - ui: Moved the
colorPalette,previousArrow, andnextArrowicons to thecorepackage and added them to theiconsobject exported from it. See #15511. - ui: The
--ck-z-modalCSS custom property was renamed to--ck-z-panel. We recommend updating custom CSS and integrations that use this custom property to avoid presentation issues. See #14973. - ui: The view collection (
focusables) required byFocusCycler#constructor()must only contain views implementing theFocusableViewinterface. Failing to do so will result in a TypeScript error. If your custom code createsFocusCyclerinstances, make sure that all views passed infocusablesimplement thefocus()method. See #14973. - ui: The font size of the
FormHeaderViewcomponent was increased. This change affects the look of the find and replace and table styling features as well as custom user interfaces that use this component. See #14973. - ui: The type of
AriaLiveAnnouncerPolitenesschanged (previouslyenum, now a constantobject). See #14973. - ui: The
#nextand#previousproperties of aFocusCyclerwill now point to the same view if there is only one focusable view (previouslynull). This change may affect integrations that use this helper to manage advanced focus navigation in dynamic UIs. See #14973. - undo: Moved the
undoandredoicons to thecorepackage and added them to theiconsobject exported from it. See #15511. - utils: Renamed the
Positioninterface toDomPoint. See #15511.