Problem/Motivation

After upgrading to CKEditor5, I was fighting a lot with the confusing new split style dropdown. In contrast to CKE4 and what our content editor are used, we have two dropdown boxes in CKE5. With one you can only select between P, H1, H2, ... This is the headings dropdown. And then there is a style-dropdown where you can switch various classes ("styles") on or off. So it requires a lot of clicking to get e.g st.h like "h1.important" etc. Especially weird is that you can combine multiple classes "h1.important.red" etc. This is not always desirable. Thus, not only for compatibility but also usability reasons, I'd very much like to go back to the old days where you can just have a single dropdown.

— @rgpublic

Work-around if all you need is <h* class>: install https://github.com/rgpublic/ckeditor_custom_heading

Steps to reproduce

See above.

Proposed resolution

  1. ✅ Wait for https://github.com/ckeditor/ckeditor5/issues/14372 👈 Please vote with a 👍 on this issue to increase its priority for the CKEditor team: they prioritize based on demand!
  2. Allow configuring which specializations of "Heading" should be made available by using https://ckeditor.com/docs/ckeditor5/latest/features/headings.html#config... ← This would lead to an inconsistent user experience, see #9 for details.

Remaining tasks

  1. Wait for upstream feature.
  2. Add test coverage.

User interface changes

Can convert e.g. a <p> to <h2 class="fancy">.

API changes

None.

Data model changes

None.

Release notes snippet

The usability of the "Style" dropdown in CKEditor 5 has improved significantly: plain paragraphs can be converted directly to a heading, blockquote, etc. with a particular class — rather than first having to convert to the appropriate tag first and then applying a class to it using the "Style" dropdown.

Original Report

After upgrading to CKEditor5, I was fighting a lot with the confusing new split style dropdown. In contrast to CKE4 and what our content editor are used, we have two dropdown boxes in CKE5. With one you can only select between P, H1, H2, ... This is the headings dropdown. And then there is a style-dropdown where you can switch various classes ("styles") on or off. So it requires a lot of clicking to get e.g st.h like "h1.important" etc. Especially weird is that you can combine multiple classes "h1.important.red" etc. This is not always desirable. Thus, not only for compatibility but also usability reasons, I'd very much like to go back to the old days where you can just have a single dropdown.

To me surprise, the problems I described are even mentioned in the CKE5 docs:

https://ckeditor.com/docs/ckeditor5/latest/features/style.html#known-issues

"At present, the style feature may clash with other features that bring in similar content (e.g. headings). Problems with overlapping styles applied to the same element may also occur."

I was even more surprised to find that there is an alternative to easily solve most of these problems:

https://ckeditor.com/docs/ckeditor5/latest/features/headings.html#config...

It seems you can just use the headings dropdown and omit the styles dropdown altogether and use that for the different styles. Almost like it used to be. Great. Only problem: There seems to be no configuration in the UI of Drupal whatsoever for this. The headings plugin of Drupal only allows to switch on/off H1,H2, etc. but not to configure different custom styles. This is really sad - so my feature request here is to allow configuring that feature in the future :-)

Comments

rgpublic created an issue. See original summary.

wim leers’s picture

Status: Active » Postponed (maintainer needs more info)

See #3326261-37: [Style] Add tests for inability to apply styles to <div>, <ul>, <ol>, <table> etc. in CKEditor 5 — and <a> allows applying it to all elements. Many issues will be fixed in the upcoming Drupal 10.1.0 release (and in beta 2 if you're willing to install that).

I think relevant remaining issues are:

Could you please check and let me know? 🙏

rgpublic’s picture

Thanks for the pointer. I will certainly check out what comes eventually out of this and if it is useful.

For the time being I've created a simple module which allows to customize the headings exactly like it was possible in CKE4. Perhaps it is also useful for other users as a bridge technology:

https://github.com/rgpublic/ckeditor_custom_heading

rgpublic’s picture

StatusFileSize
new28.58 KB
new85 KB
wim leers’s picture

Can you please update to Drupal 10.1 and try this again? Updates in CKEditor 5 maybe have fixed the problems you were seeing.

mrogers’s picture

I don't *think* the issue is resolved in 10.1, unless I'm missing it? Is there now a way in the UI to configure headings with classes like there was in CK4, so that users can apply the block-level element *and* the style in one click?

rgpublic’s picture

@mrogers: That's right. This is not solved in 10.1. You can use my module (see above) to do just that.

wim leers’s picture

Title: Allow CKEditor5 custom headings » [upstream] [Style] Allow CKEditor 5 to *create* a <h2 class="something"> directly (instead of first <h2>, then adding a class)
Version: 9.5.x-dev » 11.x-dev
Priority: Normal » Major
Status: Postponed (maintainer needs more info) » Postponed
Issue tags: +Usability, +Needs upstream feature

After having re-read the issue summary in detail, I now see how my responses in #2 and #6 completely missed your point 🙈 Sorry about that!

I am strongly inclined to mark this Closed (works as designed), because

  1. The Heading plugin supports only a class to <h1><h6>. But the Style dropdown allows adding a class to virtually any element.
  2. Once https://github.com/ckeditor/ckeditor5/issues/14372 is solved, that will be able to do what you want: you'd be able to use the Style plugin to create for example <h2 class="fancy">.
  3. the current approach is consistent with how it worked in CKEditor 4 (Heading/paragraphs is one toolbar item, Style dropdown is another toolbar item)

👆 Actually, retitling/rescoping for tracking the second point aka https://github.com/ckeditor/ckeditor5/issues/14372. I should've created an issue for this back in #3326261-51: [Style] Add tests for inability to apply styles to <div>, <ul>, <ol>, <table> etc. in CKEditor 5 — and <a> allows applying it to all elements, but forgot.

wim leers’s picture

Assigned: Unassigned » lauriii
Issue summary: View changes
Status: Postponed » Needs review
Issue tags: +Needs product manager review

Actually, let's first get feedback from @lauriii on my proposal 😇

rgpublic’s picture

@Wim-Leers:

Well, in CKE4 you could switch between P and H1.blue with just the paragraph style dropdown. Two clicks. You can't do that right now. Another difference is that say you have h1, h1.red and h1.blue. The new CKE5 style dropdown works more like a checkbox and not like a radio button. You could create h1.red.blue which is usually not what's desired.

The CKE5 style dropdown (IMHO, of course) still has a lot of very unpleasant usability flaws. Of course, they might be resolved in the future and it might very well be a sensible strategy to wait for these to be resolved - I don't want to argue against that. Nevertheless, I thought it would perhaps be a nice addition to allow to use the way more simple headline dropdown to be used for all those cases where you don't have a lot of different classes and styles and just want to have an experience similar to what we had previously in CKE4 - especially since the feature seems to be built-in already. It'd just need to be exposed in Drupal and would probably solve a lot of headaches for people trying to switch from CKE4.

wim leers’s picture

Nevertheless, I thought it would perhaps be a nice addition to allow to use the way more simple headline dropdown to be used for all those cases where you don't have a lot of different classes and styles and just want to have an experience similar to what we had previously in CKE4

Yes, I see your point. But we need to think about long-term implications of that. What you propose only works for a handful of tags. It's not a general solution.

https://github.com/ckeditor/ckeditor5/issues/14372 is a general solution.

If Drupal were to adopt what you propose, then it would be disruptive (for both the UX and configuration) to at some point switch to the generally applicable solution that https://github.com/ckeditor/ckeditor5/issues/14372 will eventually provide.

As a subsystem maintainer, I have to take the long-term view! 🕵️

Related to that long-term view: #3347721: [Style] Warn the user about styles for unsupported elements.

wim leers’s picture

It'd just need to be exposed in Drupal and would probably solve a lot of headaches for people trying to switch from CKE4.

So far, this reduction in capabilities in CKEditor 5 when compared to 4 has triggered few complaints: this issue has only half a dozen followers currently and it occasionally comes up as a question in Slack most recently on October 3.

So: please vote on https://github.com/ckeditor/ckeditor5/issues/14372 to help gauge interest! 😊

rgpublic’s picture

@Wim-Leers: I understand & makes sense! Thank you anyway for considering & detailed explanation. My module might be a stop-gap solution for some people in the mean time until a full-fledged solution comes along.

wim leers’s picture

Issue summary: View changes

My module might be a stop-gap solution for some people in the mean time until a full-fledged solution comes along.

💯

Thank you for your understanding and creating that module! 😊

Updated the issue summary to recommend that as the interim work-around for some cases 👍

aludescher’s picture

StatusFileSize
new1.26 KB

All we need is to support custom heading elements in Drupal\ckeditor5\Plugin\CKEditor5Plugin\Heading. With this patch the following code works:

/**
 * Implements hook_ckeditor5_plugin_info_alter().
 */
function MYMODULE_ckeditor5_plugin_info_alter(array &$plugin_definitions) {
  assert($plugin_definitions['ckeditor5_heading'] instanceof CKEditor5PluginDefinition);
  // Modify 'Format' options.
  $plugin_definition = $plugin_definitions['ckeditor5_heading']->toArray();
  $options =& $plugin_definition['ckeditor5']['config']['heading']['options'];
  $options[] = [
    'model' => 'paragraphSmall',
    'view' => [
      'name' => 'p',
      'classes' => 'text-small',
    ],
    'title' => t('Paragraph small'),
    'class' => 'ck-heading_paragraph_small',
  ];
  $options[] = [
    'model' => 'headingFancy',
    'view' => [
      'name' => 'h2',
      'classes' => 'fancy',
    ],
    'title' => t('Heading 2 (fancy)'),
    'class' => 'ck-heading_heading2_fancy',
  ];
  $plugin_definitions['ckeditor5_heading'] = new CKEditor5PluginDefinition($plugin_definition);
}

The new options now appear and can be enabled in the text format's Enabled Headings section.

smustgrave’s picture

Status: Needs review » Needs work

If we are going to commit something to core for this, think we will need to include test coverage also.

hoporr’s picture

Per comment: https://www.drupal.org/project/drupal/issues/3326261#comment-15316349
this issues here is supposed to be the catch-all issue for all remaining non-critical ck5 issues:

But this only concentrates on headlines.

I still don't see a way for this to work as it is now for <div>. What am I missing?

With H1, there is the workaround:
1) First select the headline in ck5
2) then the styles work again, and apply a style.

For divs to work, I have to go into text-source, and put a div around it.
That works for me, but for so many of my non-techical users that is a no-go. For them, there has to be a simple way in the editor to turn a section of text into a div.

I also don't want to switch to using <p> in the text instead of <div>, as a div can contain many p. Same for span.

Is there no other way right now than to edit the text-source?

hoporr’s picture

As far as div, I found that I put this extra line in ckeditor5.ckeditor5.yml:

options:
          - { model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' }
          - { model: 'div',      view: 'div', title: 'Div', class: 'ck-heading-div' }
          - { model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' }

then div at least appears as an option in the text-format form, and if I select it there it also shows in the ckedtior pulldowns for headlines.
At least that way, a person could make a section a <div> instead of a <p>.
And then this would work if the theme only has css that deals with divs (not p, span, etc).

But... it still does not work well:

The bigger problem is (and I do not see a way at all in CK5 that can do this): a div can wrap around many paragraphs, or other elements:

  • If I go into text-source mode and put a div around several <p> or whatnot, whenever I go out of source-mode then ck5 removed that div.
  • Likewise, if I use the above workaround and select multiple paragraphs in the textbox, then in the headings pulldown select "div", then ckeditor places one div around each paragraph.

At the moment I do not see a use divs correctly in ck5.

hoporr’s picture

Please consider opening another issue for ck5 and div, as that problem is slightly different than for "headline" because divs can wrap multiple elements. Alternatively change the title so that this issue does not only refer to headlines.

rgpublic’s picture

@hoporr: Yes, it won't work that way. CKE5 would need a dedicated plugin to define such a container DIV in the model and allow it to wrap other P tags. Unless such a plugin is written, you probably won't be able to make it work. Perhaps see also:

https://github.com/ckeditor/ckeditor5/issues/6462

rgpublic’s picture

Okay, I've filed:

https://www.drupal.org/project/drupal/issues/3418322

I think it's better to not modify the focus of this bug too much. Feel free everyone to subscribe / continue discussion over there.

jwilson3’s picture

wim leers’s picture

Status: Needs work » Postponed

Indicating this is blocked on upstream.

miiimooo’s picture

The solution outlined in #16 works, thanks @aludescher

To summarize, it uses a core patch to allow any tag in the ckeditor5 heading plugin, not just PS. in my use case I added an option for support for formatted text. I tried to add that then in the custom list for source editing tags so the editor wouldn't just remove them. But the text format configuration was clever and produced an error on save, since the tag is already supported by the CodeBlock ckeditor5 plugin. As a workaround I found out adding the tag with an arbitrary class bypasses that check and makes any tag work that is added in the alter hook.

taote’s picture

I applied the patch in #16 and added that function to my module and I got this error:

AssertionError: assert($plugin_definitions['ckeditor5_heading'] instanceof CKEditor5PluginDefinition) in assert()

justcaldwell’s picture

@taote you might be missing a use statement for CKEditor5PluginDefinition at the top of your module file:

use Drupal\ckeditor5\Plugin\CKEditor5PluginDefinition;

justcaldwell’s picture

The approach in #16 worked well for us — thanks @aludescher!

One note: be sure to add 'converterPriority' => 'high' to your new options, e.g.:

  $options[] = [
    'model' => 'headingFancy',
    'view' => [
      'name' => 'h2',
      'classes' => 'fancy',
    ],
    'title' => t('Heading 2 (fancy)'),
    'class' => 'ck-heading_heading2_fancy',
    'converterPriority' => 'high',
  ];

Without that, added options likely won't still be selected on subsequent edits of the content. Standard options that operate on the same element (in this case 'Heading 2') will take precedence.

matthieuscarset’s picture

I don't understand the technical decision being made at CKEditor. It is a shame we cannot convert elements to div or simply inject a div manually for styling.

Sharing this issue to all my Drupal relatives.

I have a dream we'll have a proper editing experience by the end of the decade 😅...

yonailo’s picture

#16 works for me, but I am getting this annoying warning :

Warning: Array to string conversion in Drupal\ckeditor5\Plugin\CKEditor5Plugin\Heading->enabledHeadingsToTags() (line 216 of core/modules/ckeditor5/src/Plugin/CKEditor5Plugin/Heading.php).

(under Drupal 11.3.1)

rgpublic’s picture

@yonailo: Did you see the patch in #16. Just the MYMODULE_ckeditor5_plugin_info_alter doesnt work. You need to apply the patch. It changes exactly the source code where the error occurs. It happens because $heading_keyed_by_model[$model]['view'] can be an array now whereas core usually expects it to be just a string.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.