DEV Community

Cover image for CKEditor 5 Pitfall: Don't Forget the Paragraph Plugin
Ondřej Chrastina
Ondřej Chrastina

Posted on • Originally published at ondrej.chrastina.dev

CKEditor 5 Pitfall: Don't Forget the Paragraph Plugin

When you're adding CKEditor 5 to your platform, chances are you're starting simple—maybe testing in a sandbox project or integrating through the excellent CKEditor Builder, or diving into the CKEditor Framework Crash Course.

In my case, I tried both approaches:

Both are fantastic resources. However, there's one small but crucial detail that’s easy to overlook:
💡 You need two plugins to make even a minimal CKEditor 5 setup work:

  • Essentials
  • 🚨 Paragraph (yes, it's not included in Essentials!)
ClassicEditor.create(element, {
    licenseKey: 'GPL',
    plugins: [
        Essentials, // * ✅ Essential
        Paragraph // 🚨 Paragraph 🚨 
    ]
});
Enter fullscreen mode Exit fullscreen mode

The Pitfall: Only Using Essentials

It might seem like the following setup is enough:

// Import the editor.
import {
    ClassicEditor,
    Essentials,
} from 'ckeditor5';

// Import the styles.
import 'ckeditor5/ckeditor5.css';

// Get the HTML element with the ID of 'app'.
const element = document.querySelector('#app');

// Instantiate the editor using the `create` method.
const editor = await ClassicEditor.create(element, {
    licenseKey: 'GPL',
    plugins: [
        Essentials
    ]
});
Enter fullscreen mode Exit fullscreen mode

The editor initializes, but nothing works—no content, no cursor, and no error messages either! 😱

Yes, the configuration on the image is slightly richer, but still behaves the same.
Creation of the CKEditor withouts the Paragraph plugin being used.

Take a look at this case:

“Are you missing something?”
Yes. Yes, you are!

YES, it is in the JSDoc

(alias) class Essentials
import Essentials
A plugin including all essential editing features. It represents a set of features that enables similar functionalities to a element.
It includes:

  • :ui/editorui/accessibilityhelp/accessibilityhelp~AccessibilityHelp,
  • :clipboard/clipboard~Clipboard,
  • :enter/enter~Enter,
  • :select-all/selectall~SelectAll,
  • :enter/shiftenter~ShiftEnter,
  • :typing/typing~Typing,
  • :undo/undo~Undo.

This plugin set does not define any block-level containers (such as :paragraph/paragraph~Paragraph). If your editor is supposed to handle block content, make sure to include it.

The Fix: Add the Paragraph Plugin 🎉

// Import the editor.
import {
    ClassicEditor,
    Essentials,
    Paragraph
} from 'ckeditor5';

// Import the styles.
import 'ckeditor5/ckeditor5.css';

// Get the HTML element with the ID of 'app'.
const element = document.querySelector('#app');

// Instantiate the editor using the `create` method.
const editor = await ClassicEditor.create(element, {
    licenseKey: 'GPL',
    plugins: [
        Essentials,
        Paragraph
    ]
});
Enter fullscreen mode Exit fullscreen mode

And voilà:
“Much better!”

Showcase of the working CKEditor with thew Paragraph plugin being defined.

🧠 Key Takeaway

  • Essentials plugin ≠ has everything you need for editing.
  • For a working CKEditor instance, especially one with block content, add the Paragraph plugin.
  • Always double-check the docs—even for plugins that sound... well, essential.

Keep this in mind as you build your rich text editing experiences! 💡

Top comments (0)