Skip to content

Allow enabling all types of editors on paragraph-like root #762

Closed

Description

@Reinmar

Developers should be able to initialize the editor on a paragraph-like roots. For example, someone may want to make content of just an <h1> element editable:

<h1 id=editor>Title...</h1>
<script>
    InlineEditor.create( document.getElementById( 'editor' ) )
        .then( ... )
        .catch( ... );
</script>

The inline type of editors are most often to be used in such a cases and there's even a ticket for InlineEditor already (https://github.com/ckeditor/ckeditor5-editor-inline/issues/3 and https://github.com/ckeditor/ckeditor5-editor-inline/issues/5). But this requirement applies also to BalloonEditor and I may imagine that someone might want to enable ClassicEditor in such a mode. So, since most of the work is needed in the common part of the code base (core, engine), I'd say that the solution could be generic to all kinds of editors from day one.

In case of editors which upcast existing DOM elements (like inline and balloon editors), the information about the type of element (whether it's div-like or paragraph-like) can be taken from that element itself. But in case of the classic editor it will need to be specified in the config. The config option could work for all editors, overriding the upcasted element.

What's kinda tricky here is mapping DOM element name to schema item name so we can create a model root with the right name. However, I think that this should be enough, taken that the automatic behaviour will be overridable by configuration anyway:

const paragraphLikeElements = [ 'p', 'h1', ... ];

getRootName( domElementName ) {
    if ( paragraphLikeElements.includes( domElementName ) { 
        return '$block';
    } else {
        return '$root';
    }
}

Defaulting to the generic $block item for all p/h1/etc elements should be enough.


Add 👍 to this post if you'd like this feature to be implemented.

Activity

  1. added
    type:featureThis issue reports a feature request (an idea for a new functionality or a missing option).
    on Jan 8, 2018
  2. Reinmar commented on Mar 6, 2018

    @Reinmar
    MemberAuthor

    I wrote a few words about how this can be achieved with minimal changes to existing editor creators: https://stackoverflow.com/questions/48896019/ckeditor5-inline-build-puts-a-p-tag-inside-of-an-h1-tag-how-do-i-disable-this/49130552#49130552

    I'm curious if it'd work.

  3. added this to the milestone on Jul 18, 2018
  4. claviska commented on Oct 20, 2018

    @claviska

    Here's a fiddle based on that suggestion. It does prevent new paragraphs from being created, but without the appropriate root there's still a child paragraph in the content.

    https://jsfiddle.net/v81yndc7/2/

    This is a hugely important feature for any app doing serious inline editing. It's not uncommon for headings, paragraphs, and even spans to be made editable.

  5. Reinmar commented on Feb 11, 2019

    @Reinmar
    MemberAuthor

    We'll need to update https://github.com/ckeditor/ckeditor5/pull/1494/files#r255422201 after p-level editors are a thing.

  6. modified the milestones: , on Sep 5, 2019
  7. Reinmar commented on Sep 5, 2019

    @Reinmar
    MemberAuthor

    The state of things

    There's been some work in this area and it looks really promising.

    Discussions:

    Branches:

    Results:

    image

    image

    Related tickets:

    Plans

    Those tests make us believe that there's not that much to do to enable such type of editors. I'm moving this up the waiting list.

    The todo list:

    • Final decision regarding whether $inlineRoot is the right direction.
    • Minimal tests in every feature for their integration with $inlineRoot.
    • Updating the inline, balloon and decoupled editors with the element name check. Tests.
    • Documentation.
  8. ange007 commented on Apr 16, 2020

    @ange007

    Are there any movements in this direction?

  9. wc-matteo commented on Jun 12, 2020

    @wc-matteo

    I would be interested in this as well

  10. modified the milestones: , on Nov 10, 2020
  11. 21 remaining items

  12. bryanjamesmiller commented on Nov 16, 2023

    @bryanjamesmiller

    Thanks for the reply @Witoso , I appreciate the response. If you look at this https://jsfiddle.net/gratiafide/zvaLebx5/ you will see the following problem:
    Screenshot at Nov 16 14-16-12

  13. Witoso commented on Nov 17, 2023

    @Witoso
    Member

    I see, yes, this is what needs to be fixed on our side. I don't see any workarounds that could be applied.

  14. bryanjamesmiller commented on Nov 17, 2023

    @bryanjamesmiller

    @Witoso are there any event hooks that we can use to remove the "p" tags before the HTML gets inserted?

  15. Witoso commented on Nov 23, 2023

    @Witoso
    Member

    None that I know of. @niegowski?

  16. mlncn commented on Nov 30, 2023

    @mlncn

    It looks like the restricted editing feature could be used for some of these use cases.

    Make a template that has <h1>[Title]</h1> and one could in theory count on CKEditor5 producing only that heading with no paragraphs. Some server-side validation would still have to confirm this though, whereas the approach outlined in this issue would be more amenable to simpler validation and sticking the result into an H1.

    One annoyance is possibly being forced to have placeholder text, though maybe with only one editing option it can be blank and people's cursor would go there automatically. Another likely annoyance is trying to hide the "editing toolbar button" as it is irrelevant with only one editable portion.

    Also, regarding this issue not getting a lot of upvotes— it is really hard to find. This use case comes up anytime one has structured data (so, at least, it comes up a lot in Drupal and some other more powerful/complex content management systems).

  17. bryanjamesmiller commented on Jan 23, 2024

    @bryanjamesmiller

    @mlncn it seems like a pretty common issue to me as a basic install like this will cause it - https://jsfiddle.net/gratiafide/zvaLebx5/ this should be fixed as it's a major problem for some of us - #762 (comment)

  18. mlncn commented on Jan 24, 2024

    @mlncn

    Oh i absolutely agree.

    My current workaround in Drupal is to make a text format that only allows paragraph tags (no other block elements like titles) and then strip those paragraph tags out with a module we made just to deal with CKEditor5's recalcitrance here: Strip paragraph tags filter.

  19. FLEdev commented on Feb 26, 2024

    @FLEdev

    I am integrating a audio / video extension within Drupal CMS and CKeditor5. After defining the schema and using the proposed definitions, everytime there is a

    wrapper tag around those elements:

    Is there any way to avoid this? The Proposed .createRoot is not available at the upcast model wrapper - using:

    schema.register('cke5MediaAudioWrapper', {
    allowWhere: "$block",
    isLimit: true,
    isObject: true,
    isBlock: true,
    isSelectable: false,
    allowChildren: ['cke5MediaAudio', 'cke5MediaAudioPreview'],
    allowAttributes: [
    'class',
    'data-settings'
    ],
    });

    schema.register('cke5MediaAudio', {
      isObject: true,
      isContent: true,
      isBlock: true,
      allowIn: ['cke5MediaAudioWrapper'],
      allowChildren: '$text',
      allowAttributes: [
       'data-media-name',
       'data-type',
       'loop',
       'preload',
       'name',
       'src',
      ]
    });
    
    conversion.for("upcast").elementToElement({
      view: {
        name: "div",
        classes: ['c-audioplayer']
      },
      model: "cke5MediaAudioPreview",
    });
    conversion.for('downcast').elementToElement( {
      model: 'cke5MediaAudioPreview',
      view:  {
        name: 'div',
        classes: ['c-audioplayer']
      }
    });
    

    // or:

    conversion.for("upcast").elementToElement({
    view: {
    name: 'audio',
    attributes: [
    'data-media-name',
    'autoplay',
    'loop',
    'name',
    'preload',
    'src'
    ]
    },
    //converterPriority: "high",
    model: ( viewElement, { writer } ) => {
    const entityAttributes = {
    'data-media-name': viewElement.getAttribute('data-media-name'),
    'autoplay': viewElement.getAttribute('autoplay'),
    'data-type': viewElement.getAttribute('data-type'),
    'loop': viewElement.getAttribute('loop'),
    'name': viewElement.getAttribute('name'),
    'preload': viewElement.getAttribute('preload'),
    'src': viewElement.getAttribute('src'),
    };
    return writer.createElement( 'cke5MediaAudio', entityAttributes);
    }
    });

  20. FLEdev commented on Feb 26, 2024

    @FLEdev

    @Witoso : any idea how to avoid adding "p" tags into "non wrapping" elements like "audio/video" or generally how to avoid such behaviour?
    As far I understand, there is no preprocess function/hook to change this. Also the "autoParagraph" setting is not available (see: #762).

  21. Reinmar commented on Apr 10, 2026

    @Reinmar
    MemberAuthor

    Just FYI, we're working in several sub-initiatives to fully enable paragraph-like and even span-like editors.

    The most recent work that's happening is:

  22. andrzejkala commented on Jun 11, 2026

    @andrzejkala
    Contributor

    This one has been on the radar since 2018, with 44 👍 and a steady stream of "we need this too" from people building CMS fields, layout builders, and templated editing surfaces.

    Thank you for keeping it alive and for the detailed real-world use cases along the way - they shaped where this landed. 🙌

    With the last two releases of CKEditor 5 we can finally say that it’s now possible to enable all types of editors on a paragraph-like root 🎉

    For the details, see the documentation on setting up Inline roots.

    Below is a per-release breakdown of this feature's development.

    v48.1.0

    This release introduced the model side. config.root.modelElement (single-root) and config.roots.<name>.modelElement (multi-root) choose the schema item for a root, defaulting to $root, with a new generic $inlineRoot item for inline-only content and modelAttributes available on all editor types - classic, inline, balloon, decoupled, and multi-root.

    Closed issues

    v48.2.0

    Second release added the view side, release-noted as "Editor roots on paragraph-like elements." config.root.element / config.roots.<name>.element now accept a tag-name string like 'h1' or a ViewRootElementDefinition (tag, CSS classes, inline styles, attributes), so a root can be created as a heading, paragraph, or custom block without an existing DOM node (<textarea> and <input> excluded).

    We’ve also made sure that our built-in features understand the concept of inline roots and work with them seamlessly. The only outlier at the moment are the images, mentioned in the Known issues section below

    Closed issues

    Known issues

    Inline images are temporarily disabled inside inline-only roots; proper support for inserting and managing them there is still being implemented.

    Additional Links

    RFC’s

  23. added this to the upcoming milestone on Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:dxThis issue reports a developer experience problem or possible improvement.squad:coreIssue to be handled by the Core team.support:2An issue reported by a commercially licensed client.type:featureThis issue reports a feature request (an idea for a new functionality or a missing option).

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions