ckeditor5 icon indicating copy to clipboard operation
ckeditor5 copied to clipboard

Provide opt-out for v46+ opinionated typography defaults in .ck-content

Open jjroelofs opened this issue 1 month ago • 2 comments

📝 Provide a description of the new feature

CKEditor 5 v46+ introduced opinionated typography defaults that are explicitly applied via the .ck-content selector:

.ck-content {
  font-family: var(--ck-content-font-family);
  font-size: var(--ck-content-font-size);
  color: var(--ck-content-font-color);
  line-height: var(--ck-content-line-height);
}

These defaults create significant integration issues in CMS environments like Drupal where:

  1. Content needs to inherit typography from custom themes and modules
  2. We don't control our clients' CSS customizations
  3. Thousands of existing sites expect CKEditor content to respect site-wide typography

This is especially noticeable in our DXPR Builder module which uses the CK5 inline editor on frontend pages for WYSIWYG editing. It is important here that we don't override the user's custom theme and branding. It is also impossible for us to "fix" it in our product by setting the variables because we would not know what font-family our clients use on any given site.

I suspect it will also prove to be a problem in Drupal core: https://www.drupal.org/project/drupal/issues/3538768#comment-16359381

The problem: The .ck-content selector creates a new inheritance context that overrides site typography. Simply overriding the CSS variables with inherit, unset, or reset doesn't work because:

  • The properties themselves in .ck-content create the override
  • The specificity and cascade rules mean these properties take precedence over theme styles
  • Child elements inherit from .ck-content, not from the original document flow

This breaks typography inheritance in ways that can't be fixed without removing the properties from .ck-content itself.

Our current workaround

We've had to implement a complex build-time workaround that processes CKEditor source files. The opinionated styles appear in two separate places requiring different handling:

1. Backend (Editor UI): Modify core theme files before webpack bundling

const removeTypography = (css) => {
  ['font-family', 'font-size', 'color', 'line-height'].forEach(prop => {
    css = css.replace(
      new RegExp(`(\\.ck-content[\\s{][^}]*?)\\s*${prop}:\\s*var\\(--ck-content-${prop === 'color' ? 'font-color' : prop}\\);?`, 'g'),
      '$1'
    );
  });
  return css;
};

// Process source files before our webpack build
['node_modules/@ckeditor/ckeditor5-core/theme/core.css',
 'node_modules/ckeditor5/node_modules/@ckeditor/ckeditor5-core/theme/core.css'
].forEach(file => {
  if (fs.existsSync(file)) {
    fs.writeFileSync(file, removeTypography(fs.readFileSync(file, 'utf8')));
  }
});

2. Frontend (Content Styles): Process the pre-built ckeditor5-content.css distributed in your npm package

// Extract from node_modules/*/ckeditor5/dist/ckeditor5-content.css
// This is a pre-compiled file from CKEditor, not generated by our build
let css = fs.readFileSync('node_modules/ckeditor5/dist/ckeditor5-content.css', 'utf8');

// Neutralize CSS variables and remove typography properties
['font-family', 'font-size', 'font-color', 'line-height'].forEach(prop => {
  css = css.replace(new RegExp('--ck-content-' + prop + ':[^;]+;', 'g'), '--ck-content-' + prop + ':inherit;');
});
css = removeTypography(css);

This fragile workaround:

  • Requires maintenance with every CKEditor update
  • Manipulates node_modules post-install
  • Processes files in two separate locations
  • Adds complexity to our build pipeline
  • Could break with internal CKEditor structure changes

Proposed solution

Provide a configuration option to opt out of opinionated styles, for example:

ClassicEditor.create(element, {
  opinionatedStyles: false
})

Use case

Content Management Systems and site builders where:

  • Typography is controlled by themes/design systems outside CKEditor
  • Content must seamlessly inherit site-wide typography
  • The editor is one of many content creation tools
  • Consistent typography across all content sources is critical

Related discussion: https://github.com/ckeditor/ckeditor5/issues/18710


If you'd like to see this feature implemented, add a 👍 reaction to this post.

jjroelofs avatar Nov 25 '25 09:11 jjroelofs

Thanks a lot for the detailed report and for outlining your current workaround, we really appreciate the level of context you’ve provided here.

Regarding the typography reset: we’ve been evaluating whether mechanisms like @layer or additional stylesheets. Layers are definitely interesting from a CSS-architecture perspective, but they also introduce their own challenges, especially once you factor in environments that export inline styles, email pipelines, legacy CSS tooling, or CMS pipelines that can’t control stylesheet ordering. Additional stylesheets are quite cumbersome for new users, every new integration layer, even as small as a stylesheet, becomes broken installations and support tickets. Editor loading stylesheets or styles: we've been there in the old installation methods, and decided to drop this magical approach.

Because of this, any approach that involves additional stylesheets or layer-based cascade management may become quite problematic. That said, the topic would require research on our side.

One idea that might be worth exploring from the integrator side is whether systems with complex theming requirements (like Drupal, DXPR, etc.) could opt out of our content styles entirely and ship their own minimal content stylesheet tailored to their theme. In some scenarios this may actually provide the cleanest “inherit everything” experience without needing CKEditor to dynamically disable parts of its default styling. It’s not a trivial path, but for highly customized environments it might offer the most predictable long-term result.

I will bring up this topic internally, also @Reinmar @oleq @filipsobol you can take a look.

Witoso avatar Nov 25 '25 10:11 Witoso

One idea that might be worth exploring from the integrator side is whether systems with complex theming requirements (like Drupal, DXPR, etc.) could opt out of our content styles entirely and ship their own minimal content stylesheet tailored to their theme

I think this is the only realistic scenario.

What we perhaps could improve on our end, is organizing content styles in two groups:

  • Essential, without which features will not work at all
  • Additional, that improves the overall experience (more opinionated)

We tried to avoid the second group over the years, but that has been backfiring at us all the time. By default, the editor just did not work well.

Also, the separation between these essential content styles and opinionated ones isn't always clear. And there are dependencies between them. That's why I think it may not be possible to completely split them. Rather than that, it may happen that the best option is to better organize them within one file.

Right now, content stylesheet is automatically generated out of dozens of files. But with the new installation methods this is perhaps now more controllable for us and we could have them centralized. With that, we could document and improve readability of these styles.

In best case scenario, I'd physically split them into two essential and additional styles, e.g. by using two separate classes:

  • .ck-content-essential (or .ck-content for semi-backward compat)
  • .ck-content-opinionated (or typography/or something)

And as @jjroelofs mentioned, config.useOpionantedStyles could control whether the second class is added to the editor. And when displaying content on external websites, integrators would just pick one or two classes, as they want.

Reinmar avatar Nov 25 '25 10:11 Reinmar