Starting position:
When configuring a text format with CKEditor you can add the "Styles" button. You can add your "Style dropdown" options afterwards on the configuration page (e.g. "span.cke-color-red|red text").
To give your class definition some "life" you can add some CSS code (e.g. ".cke-color-red { color: red; }") to a custom CSS file in your theme. (I would always recommend to use a separate CSS file for your CKEditor styles.)
So far, so good.
That means the first part of my initial question "How to add custom CSS for CKEditor styles to rendered WYSIWYG content AND (node) add / edit forms with CKEditor textareas" is easy: the rendered content will get the red color in the example above.

But what about the add / edit form...
By default the CSS won't get into the CKEditor iFrame. So an editor can't see the styles in the WYSIWYG area. But I (and my customers) want to get this kind of "preview" while editing the content in the form.
https://www.drupal.org/developing/api/8/ckeditor names 2 solutions to get the CSS code into the CKEditor iFrame.
The "Bartik sample" solution is very easy by adding only 2 lines in your THEME.info.yml file:

ckeditor_stylesheets:
  - path/to/my-ckeditor-styles.css

But this solution seems not to work if you are using the admin theme for your (node) add / edit forms which is a common use case.

The 2nd solution is implementing hook_ckeditor_css_alter() which also works if you are using the admin theme for content editing.

I created a custom module (together with some README instructions) for one of my clients that scans for a special named CSS file in the default theme to add it via hook_ckeditor_css_alter() to cover both cases: content editing with the default theme and with the admin theme.

So I found a solution for the problem, but my question is: Is there an easier way to solve this problem?
I think that a lot of Drupal users will run into the same trouble.

If no one has an idea, but others are interested in my solution I could post my code (which could be improved by making the CSS filename flexible via an admin backend configuration page). And maybe "performance" could be a critical point if the CKEditor is used in a comment form that is nearly on every page and also accessible for anonymous users.

Conclusion:
The intention of this post is to start a discussion about an easy solution for non-programmers to get the expected user experience when editing WYSIWYG form elements. I found (and documented) a solution that I can share with the community if no better solutions exist.

I added a related issue #2645100 but I think it doesn't cover the described Problem with CKEditor "Styles".

Thanks in advance for any comments.

Comments

M_Z created an issue. See original summary.

wim leers’s picture

Category: Feature request » Support request
Status: Active » Fixed

What Drupal 8 supports

Actually, Drupal 8 already supports this exact use case.

In fact, Bartik uses it!

ckeditor_stylesheets:
  - css/base/elements.css
  - css/components/captions.css
  - css/components/table.css
  - css/components/text-formatted.css

Bartik is a front-end theme. Seven is the admin theme. When using /node/add/article or /node/3/edit, you're using the admin theme. But CKEditor will load the ckeditor_stylesheets the front-end theme (Bartik by default) defines in the CKEditor iframe instance.

Your statements

But this solution seems not to work if you are using the admin theme for your (node) add / edit forms which is a common use case.

This is not true. I suspect you made a small mistake or ran into a caching problem. What you did was correct, and should definitely work. It works for Bartik. Check for yourself in a vanilla Drupal 8 installation.

I created a custom module (together with some README instructions) for one of my clients that scans for a special named CSS file in the default theme to add it via hook_ckeditor_css_alter() to cover both cases: content editing with the default theme and with the admin theme.

So I found a solution for the problem, but my question is: Is there an easier way to solve this problem?
I think that a lot of Drupal users will run into the same trouble.

Totally agreed that that should not be necessary!

P.S.: You said you can add some CSS code (e.g. ".cke-color-red { color: red; }") to a custom CSS file in your theme — but I'd strongly advise against using cke-color-red as a selector, because it's A) not really CKEditor-specific even though the name suggests otherwise, B) non-semantic. Call it "important" or "callout" or something like that, but not "color red".

Conclusion

Again, I'm certain that this was caused by a silly typo, or by a caching problem. Themes' *.info.yml files are not re-read on every request. After modifying YAML files, clear all caches.

Also, to make it clearer, I updated the documentation: https://www.drupal.org/node/2617470/revisions/view/9442027/9442067.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

ali_b’s picture

Is it possible to make it work with adminimal theme?

dkre’s picture

#4 you have the specify...

ckeditor_stylesheets:
- path-to-your-css

...in your frontend theme.

-

This is still confusing. The assumption is that this would be something set from your administration theme *not* your front-end theme. Setting 'ckeditor_stylesheets' in your admin themes .info.yml is ignored.

This doesn't make a great deal of sense. You make a setting in one theme to effect the another, unless you're breaking normal convention and not using an admin theme for content creation/editing.

fkelly12054@gmail.com’s picture

Faced with the same issue, I just modified the elements.css file in Bartik. (bartik/css/base ...) It is already pointed to by the info.yml file. However, this raises another issue: if you use the tar.gz files for a live update and replace /core/themes/bartik with the latest version it will overwrite your changes. This of course is also true even if you pointed to a new file with the info.yml (the info.yml would get overwritten). So I copy my elements.css off to safety in my themes directory at the same level as core (where contrib themes go) and do a quick compare of elements.css between the version from the updated drupal version and the "old" one, then copy my elements.css file back into core/themes/bartik. Not ideal but it works. (I know real developers don't update their sites live from the tar.gz but I'm not a real developer and if someday I trash my site briefly the world is not coming to an end).

Am now looking at a similar issue in views. You can add a custom style for a field being displayed in views. But where to put the style? I'm thinking that down the road I may have to study up on using a custom theme that doesn't get updated automagically. It would be nice if there was a site-wide place to put custom styles that would be protected from automatic updates instead and would be available on every page load.

Incidentally, the link to:
https://www.drupal.org/node/2617470/revisions/view/9442027/9442067
shows all the code for the revisions. Maybe that was intended? but
https://www.drupal.org/node/2617470
might be a less confusing link to follow.

thomas.frobieter’s picture

I don't really like this solution. Way to complicated for normal users. We should add the simple textfield inside the textformat settings agin, to include css files.

sgp913’s picture

For some reason, the themename_ckeditor_css_alter function is not taking (8.3.7) for an admin theme...is that second solution only applicable to modules? If so, this is needlessly complicated since it would be preferable to just put the ckeditor_stylesheets info in the theme.info.yml, which is what I had originally done at first until today when I realized it wasn't working...

I want to make some adjustments that are only available on the admin side, such as a marker to show a <wbr /> tag and some other minor things to assist content development.

mrpauldriver’s picture

Yes to #7. Why make it hard when it doesn't need to be?

I get the thinking that the iframe styling should be reflective of the front end theme so that content editors see a realistic WYSIWYG preview, but this does not fit with the use case of just wanting to tidy up the editor. For example, changing the default font from Georgia to something else.

phuang07’s picture

Suggested in #2 works for me. And I agree that it is confusing.

plato1123’s picture

I almost feel like a contrib module would be less confusing, or a checkbox related to ckeditor somewhere.

gomez_in_the_south’s picture

One challenge we had is that our site was setup to style certain elements based on DOM elements that weren't present in the CKEditor window.

In addition to using the `ckeditor_stylesheets` directive in the themes info.yml file (as mentioned above), we also needed to insert some additional classes in the ckeditor view so that the necessary CSS rules would be applied.

To do this, I used the following hook in a custom module:

/**
 * Implements hook_editor_js_settings_alter().
 */
function MYMODULE_editor_js_settings_alter(array &$settings) {
  // Add the necessary class to the WYSIWYG editor, so that the it matches the front end.
  // Note that 'full_html' reflects the name of the text format used. 
  $settings['editor']['formats']['full_html']['editorSettings']['bodyClass'] = "whatever-class-you-want";
}
trackleft2’s picture

praveenarobox’s picture

usmanjutt84’s picture

You can also add a new css file using a hook

function hook_ckeditor_css_alter(array &$css, Editor $editor) {
  $css[] = \Drupal::service('extension.list.module')->getPath('mymodule') . '/css/mymodule-ckeditor.css';
}

see more at https://git.drupalcode.org/project/drupal/-/blob/9.5.x/core/modules/cked...

smulvih2’s picture

#15 worked for me for adding CSS from custom module.

yovanny.gomez.oyola’s picture

#15 worked for me. I was able to add a new CSS from my custom module.