Skip to main content

How do I reproduce the appearance of WYSIWYG editor content on the frontend?

Kuroco's WYSIWYG editor uses CKEditor 5.
Content created in the WYSIWYG editor contains elements and class names defined by CKEditor 5, such as <figure class="table"> for tables, <figure class="image image-style-side"> for images, and <span class="text-big"> for font sizes.

Inside the admin panel editor, CKEditor 5's "content styles" are applied to these classes.
When the content retrieved from the API is displayed as-is on the frontend, the content styles are not loaded, which causes issues such as:

  • The content looks different on the frontend from how it looks in the admin panel editor
  • CSS defined on the displaying page for classes with the same names, such as .table or .image, is applied to the content and breaks the layout

You can resolve these issues by wrapping the content in an element with class="ck-content" and loading the official CKEditor 5 content styles.
There is no need to modify the HTML or class names of the content.

How to set it up

1. Prepare content-styles.css

The full content styles are published on the following page of the CKEditor 5 official documentation.
Copy the CSS under "The full list of content styles" and save it as a file such as content-styles.css.

info

At the time of writing, the Kuroco admin panel uses CKEditor 5 v41.3.1.
The CKEditor 5 version may change with Kuroco updates, but the content styles are not expected to change significantly.
For v42.0.0 and later, a ckeditor5-content.css file containing only the content styles is also available from the CDN.
Example: https://cdn.ckeditor.com/ckeditor5/48.5.0/ckeditor5-content.css

All selectors in content-styles.css start with .ck-content.
Therefore, loading this CSS does not affect the styles of the page outside elements with the ck-content class.

/* Excerpt from content-styles.css */
.ck-content .table {
margin: 0.9em auto;
display: table;
}
.ck-content .table table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
height: 100%;
border: 1px double hsl(0, 0%, 70%);
}
.ck-content .table table td,
.ck-content .table table th {
min-width: 2em;
padding: .4em;
border: 1px solid hsl(0, 0%, 75%);
}

2. Place the CSS on the frontend and load it

Place the saved content-styles.css in your frontend project and load it on the pages that display the content.
You can also upload it to the File Manager and load it from its KurocoFiles URL.

<link rel="stylesheet" href="/path/to/content-styles.css" type="text/css">

3. Wrap the content in an element with the ck-content class

Output the value of the WYSIWYG field retrieved from the API inside an element with class="ck-content".

<div class="ck-content">
<!-- Output the HTML of the WYSIWYG field retrieved from the API here -->
</div>

Example for Nuxt.js:

<template>
<div v-if="response">
<h1>{{ response.details.subject }}</h1>
<!-- eslint-disable-next-line vue/no-v-html -->
<div class="ck-content" v-html="response.details.ext_01"></div>
</div>
</template>
caution

Replace response.details.ext_01 with the WYSIWYG field of your own content structure.

4. Verify the display

Save content with a table, image, and font sizes in the admin panel WYSIWYG editor, and display it on the frontend.
Confirm that the display on the frontend matches the display inside the editor.

Avoiding conflicts with the CSS of the displaying page

Even after loading content-styles.css, if the displaying page has CSS targeting generic class names such as .table or .image, that CSS is also applied to the content inside ck-content.
Because the selectors in content-styles.css (e.g. .ck-content .table) have higher specificity than the page's .table, properties set by content-styles.css are not overridden.
The layout breaks because properties set only by the page's CSS (e.g. width, margin-bottom, or padding and border-top on td) remain applied to the content.

To avoid conflicts without changing the HTML or class names of the content, you can use one of the following approaches.

Override individually

Add CSS that cancels the affected styles, using selectors that start with .ck-content.

.ck-content .table table td,
.ck-content .table table th {
border-top: 0;
vertical-align: top;
}

This is suitable when the affected parts are limited, but it must be updated whenever the page's CSS changes.

Render inside a Shadow DOM

Render the content inside a Shadow DOM and load content-styles.css within it.
Selectors on the displaying page do not match elements inside the Shadow DOM, so duplicated class names have no effect.
Because the content is unaffected regardless of the HTML or class names used by content editors, no follow-up override CSS is required.

<div id="cms-content"></div>

<script>
const host = document.getElementById('cms-content');
const root = host.attachShadow({ mode: 'open' });
root.innerHTML = `
<link rel="stylesheet" href="/path/to/content-styles.css">
<div class="ck-content">${html}</div>
`;
</script>
caution

Set html to the value of the WYSIWYG field retrieved from the API.
Inherited properties such as fonts and text color are still inherited from the displaying page. To block these as well, add :host { all: initial; } to the CSS inside the Shadow DOM and set the required font properties on .ck-content.

note

The above is not a Kuroco-specific setting; it is handled by your frontend implementation.
The class names output by the WYSIWYG editor cannot be changed in Kuroco's settings.

Sharing the same CSS with the admin panel editor

If you add your own CSS for the frontend (e.g. .ck-content .style-button { ... }), setting the same CSS file in [Custom CSS] of the content structure applies the same styles inside the admin panel WYSIWYG editor as well.
For the setup steps, see Applying custom CSS to the Kuroco admin panel WYSIWYG editor.


Support

If you have any other questions, please contact us or check out Our Slack Community.