# Export with inline styles

The export with inline styles feature applies the styles defined by CSS style sheets directly on HTML elements. For example, a global `<p class="red">` style defining the font color to be red, will be turned into `<p style="color: red">`. This is especially useful for email creation but may be helpful in other use cases.

> **Unlock this feature with selected CKEditor Plans**
>
> Try all premium features – no credit card needed.
>
> [Sign up for a free trial ](https://portal.ckeditor.com/checkout?plan=free)[Select a Plan](https://ckeditor.com/pricing/)

<a id="demo">

## Demo

Use the Source editing command to see changes. Check the output below to see the exported content with inline styles applied.

<!-- AI-AGENT-NOTE: An interactive demo is embedded here but is not represented in this Markdown file. If you need to see it in action, open this page in a browser (e.g. via a browser-automation MCP like Chrome DevTools or Playwright), or let the user know a live demo is available on this page. -->

Switch the tabs below to see three different outputs: the HTML tags with classes, CSS styles, and the HTML with those styles inlined. The last output shows how the exported content would look like.

<a id="export-inline-styles-code-switcher">

**HTML**

**CSS**

**HTML with inline styles**

The preview below shows the rendered content with inlined styles.

<a id="snippet-export-preview">

This demo presents a limited set of features. Visit the [feature-rich editor example](../examples/builds-custom/full-featured-editor.md) to see more in action.

<a id="installation">

## Installation

After [installing the editor](../getting-started/installation/cloud/quick-start.md), add the feature to your plugin list and toolbar configuration:

**NPM**

```js
import { ClassicEditor } from 'ckeditor5';
import { ExportInlineStyles } from 'ckeditor5-premium-features';

ClassicEditor
	.create( {
		licenseKey: '<YOUR_LICENSE_KEY>',
		plugins: [ ExportInlineStyles, /* ... */ ],
		exportInlineStyles: {
			// Configuration.
		}
	} )
	.then( editor => {
		editor.execute( 'exportInlineStyles' )
			.then( html => {
				console.log( 'Email-ready content with proper HTML attributes:', html );
			} );
		// ...
	} )
	.catch( /* ... */ );
```

**CDN**

```js
const { ClassicEditor } = CKEDITOR;
const { ExportInlineStyles } = CKEDITOR_PREMIUM_FEATURES;

ClassicEditor
	.create( {
		licenseKey: '<YOUR_LICENSE_KEY>',
		plugins: [ ExportInlineStyles, /* ... */ ],
		exportInlineStyles: {
			// Configuration.
		}
	} )
	.then( editor => {
		editor.execute( 'exportInlineStyles' )
			.then( html => {
				console.log( 'Email-ready content with proper HTML attributes:', html );
			} );
		// ...
	} )
	.catch( /* ... */ );
```

<a id="activating-the-feature">

### Activating the feature

To use this premium feature, you need to activate it with proper credentials. Refer to the [License key and activation](../getting-started/licensing/license-key-and-activation.md) guide for details.

<a id="configuration">

## Configuration

The export with inline styles feature can be configured using the `exportInlineStyles` configuration object:

```ts
ClassicEditor
	.create( {
		// ... Other configuration options ...
		exportInlineStyles: {
			stylesheets: [ '/ckeditor5-content.css' ],
			inlineCss: `
				.ck-content {
					.warning { color: red; }
					.note { background: yellow; }
				}
			`,
			stripCssClasses: true
			// ...
		}
	} )
```

<a id="stylesheets">

### Stylesheets

An array of paths (relative or absolute URLs) to CSS files that the plugin loads from the browser using `fetch()` and processes during export. The order matters — later files override styles from earlier ones.

<a id="source-files">

#### Source files

Provide the editor’s content style sheets so the exported HTML preserves the look readers see in the editor. CKEditor 5 distributes content-only style sheets in two locations:

* The `dist/ckeditor5-content.css` file from the `ckeditor5` npm package and the matching `dist/ckeditor5-premium-features-content.css` from the `ckeditor5-premium-features` npm package.
* The same files served from `https://cdn.ckeditor.com/ckeditor5/49.0.0/ckeditor5-content.css` and `https://cdn.ckeditor.com/ckeditor5-premium-features/49.0.0/ckeditor5-premium-features-content.css`.

For full background, see the [Content styles](../getting-started/setup/content-styles.md) guide.

<a id="hosting-the-css-in-your-application">

#### Hosting the CSS in your application

The `stylesheets` option uses `window.fetch()` to load each URL from the browser. The files must be served from a same-origin URL or have permissive CORS headers — bundler-only paths (for example, `import 'ckeditor5/ckeditor5-content.css'`) are not reachable. Copy or reference the files in a way that matches your application setup:

| Integration           | Where to host the file                                               | Example URL in the config                |
| --------------------- | -------------------------------------------------------------------- | ---------------------------------------- |
| Next.js (App / Pages) | Copy to `public/`, then reference from the site root.                | `'/ckeditor5-content.css'`               |
| React (Vite, CRA)     | Place in `public/` (Vite, CRA) — referenced from the site root.      | `'/ckeditor5-content.css'`               |
| Vue 3 (Vite)          | Place in `public/` and reference from the site root.                 | `'/ckeditor5-content.css'`               |
| Nuxt 3                | Place in `public/`.                                                  | `'/ckeditor5-content.css'`               |
| Angular CLI           | Add to the `assets` array in `angular.json` and reference from root. | `'/assets/ckeditor5-content.css'`        |
| Server-rendered apps  | Serve from your application’s static directory.                      | `'/static/ckeditor5-content.css'`        |
| CDN                   | Reference the CKEditor CDN URL directly (no local copy).             | See the CDN configuration example below. |

A typical configuration combining both content style sheets and an application-specific style sheet:

```js
ClassicEditor
	.create( {
		// ... Other configuration options ...
		exportInlineStyles: {
			stylesheets: [
				'/ckeditor5-content.css', // Open-source content styles.
				'/ckeditor5-premium-features-content.css', // Premium content styles (if used).
				'/styles.css' // Your application styles.
			]
		}
	} )
```

Or, when loading style sheets directly from the CKEditor CDN:

```js
ClassicEditor
	.create( {
		// ... Other configuration options ...
		exportInlineStyles: {
			stylesheets: [
				'https://cdn.ckeditor.com/ckeditor5/49.0.0/ckeditor5-content.css', // Open-source content styles.
				'https://cdn.ckeditor.com/ckeditor5-premium-features/49.0.0/ckeditor5-premium-features-content.css', // Premium content styles (if used).
				'/styles.css' // Your application styles.
			]
		}
	} )
```

If `stylesheets` is omitted, the plugin processes only the default editor content style sheets via the `'EDITOR_STYLES'` token. This token works only in legacy custom builds with webpack or DLLs. In npm and CDN setups, these default content style sheets are not inlined unless you list URLs explicitly.

> **Warning**
>
> **CSS selectors must include the `.ck-content` prefix**
>
> Styles without this prefix will be ignored during the inline styles transformation. You can use CSS nesting with `.ck-content` as the parent:
>
> For example:
>
> ```css
> /* ❌ This style will be ignored */
> .warning { color: red; }
>
> /* ✅ This style will be processed - flat approach */
> .ck-content .warning { color: red; }
>
> /* ✅ This style will be processed - nested approach */
> .ck-content {
> 	.warning { color: red; }
> }
> ```

> **Note**
>
> **Direct styles on `.ck-content` are inherited by first-level children**
>
> Any styles set directly on the `.ck-content` element will be copied to all its direct children during export. This is because the `.ck-content` element itself is synthetic and not part of the exported content.
>
> For example, if you define styles like `color: red` and `font-family: Arial` on `.ck-content`, all first-level elements such as paragraphs and lists will have these styles directly applied to them in the exported content. This inheritance only applies to first-level children, not to deeper descendants.

<a id="inline-css">

### Inline CSS

A string containing CSS rules to apply after processing the external style sheets. Useful for adding supplemental styles without external files. The option defaults to an empty string.

```js
ClassicEditor
	.create( {
		// ... Other configuration options ...
		exportInlineStyles: {
			inlineCss: `
				.ck-content {
					/* Styles directly applied to .ck-content */
					color: blue;
					font-family: Arial;

					/* Nested styles for children */
					.warning {
						color: red;
						font-weight: bold;
					}
					.highlight {
						background: yellow;
					}
				}
			`
			// ...
		}
	} )
```

<a id="strip-css-classes">

### Strip CSS classes

When set to `true`, the feature will remove the CSS classes from elements after inline styles are applied. This ensures the exported content preserves styling without depending on external style sheets. The option defaults to `false`.

```js
ClassicEditor
	.create( {
		// ... Other configuration options ...
		exportInlineStyles: {
			stripCssClasses: true
			// ...
		}
	} )
```

<a id="transformations">

### Transformations

An array of functions that allow you to modify the elements and their styles before applying inline styles. Each function receives the element and a `stylesMap` object, which contains the computed styles for that element. You can use this to add, remove, or modify styles based on your needs.

```js
ClassicEditor
	.create( {
		// ... Other configuration options ...
		exportInlineStyles: {
			transformations: [
				( element, stylesMap ) => {
					// Example transformation: Add a custom attribute to all paragraphs.
					if ( element.tagName === 'P' ) {
						element.setAttribute( 'data-paragraph', 'true' );
					}
				}
			]
			// ...
		}
	} )
```

We also provide a handy transformation helper for email creation use cases. These transformations improve compatibility with email clients by converting modern CSS properties to better-supported HTML attributes.

**NPM**

```js
import { ClassicEditor } from 'ckeditor5';
import { ExportInlineStyles, getEmailInlineStylesTransformations } from 'ckeditor5-premium-features';

ClassicEditor
	.create( {
		// ... Other configuration options ...
		exportInlineStyles: {
			// Add email-specific transformations to the editor configuration.
			transformations: getEmailInlineStylesTransformations()
			// ...
		}
	} )
	.then( editor => {
		// When exporting content, the email transformations will be applied automatically.
		editor.execute( 'exportInlineStyles' )
			.then( html => {
				console.log( 'Email-ready content with proper HTML attributes:', html );
			} );
	} )
	.catch( error => {
		console.error( error );
	} );
```

**CDN**

```js
const { ClassicEditor } = CKEDITOR;
const { ExportInlineStyles, getEmailInlineStylesTransformations } = CKEDITOR_PREMIUM_FEATURES;

ClassicEditor
	.create( {
		// ... Other configuration options ...
		exportInlineStyles: {
			// Add email-specific transformations to the editor configuration.
			transformations: getEmailInlineStylesTransformations()
			// ...
		}
	} )
	.then( editor => {
		// When exporting content, the email transformations will be applied automatically.
		editor.execute( 'exportInlineStyles' )
			.then( html => {
				console.log( 'Email-ready content with proper HTML attributes:', html );
			} );
	} )
	.catch( error => {
		console.error( error );
	} );
```

<a id="usage">

## Usage

To export the editor content with inline styles, use the [`ExportInlineStyles`](../api/module_export-inline-styles_exportinlinestyles-ExportInlineStyles.md) command:

```js
editor.execute( 'exportInlineStyles' )
	.then( ( html ) => {
		console.log( html );
	} )
	.catch( ( error ) => {
		console.error( error );
	} );
```

You can also pass configuration options directly to the command. These options will override any editor configuration settings:

```js
editor.execute( 'exportInlineStyles', {
	stylesheets: [ '/ckeditor5-content.css' ],
	inlineCss: '.ck-content .warning { color: red; }',
	stripCssClasses: true,
	transformations: [ /* custom transformations */ ]
} )
	.then( ( html ) => {
		console.log( html );
	} )
	.catch( ( error ) => {
		console.error( error );
	} );
```

The command outputs the exported content as an HTML string with inline styles applied. You can then use the content in email templates, CMS systems, or other environments where external CSS is not supported.

> **Warning**
>
> **One-way transformation**
>
> The exported content should not be loaded back to the editor. The content with inlined styles will render depending on the editor’s configuration and the UI of some features may not work correctly.
>
> If you want to save the content with inlined styles, make sure to save the `getData` output as well as `exportInlineStyles` . Always load the editor with the `getData` output.
>
> If you need to load content with inlined styles consider using the [General HTML Support (“GHS”)](html/general-html-support.md) feature. However, it may lose some of the original styling and document structure.

<a id="style-transformations">

### Style transformations

The export with inline styles feature allows you to apply custom transformations to elements before inline styles are applied. Transformations enable you to modify elements and their styles programmatically during the export process.

<a id="when-transformations-are-invoked">

#### When transformations are invoked

Transformations are called for each element in the DOM tree during the export process:

1. Child elements are processed first, before their parent elements.
2. For each element, the transformation is executed immediately before inline styles are assigned to the element.

This execution order gives you powerful control over the exported content:

* You can modify the element’s attributes and styles just before they are finalized.
* You can add or remove styles from the `stylesMap` to customize the final appearance.
* You can manipulate the element’s children (add, remove, or modify) since they are already processed when the parent’s transformation is called.
* You can even remove elements completely from the output if needed.

<a id="example-transformation">

#### Example transformation

```js
transformations: [
	( element, stylesMap ) => {
		// Add a new style.
		if ( element.tagName === 'P' ) {
			stylesMap.set( 'line-height', '1.5' );
		}

		// Remove a style.
		if ( element.classList.contains( 'no-margin' ) ) {
			stylesMap.delete( 'margin' );
		}

		// Modify child structure.
		if ( element.classList.contains( 'box' ) ) {
			// Remove unwanted child elements.
			const unwantedElements = Array.from( element.querySelectorAll( '.remove-me' ) );
			unwantedElements.forEach( el => el.remove() );

			// Add new child element.
			const disclaimer = document.createElement( 'div' );
			disclaimer.textContent = 'Important notice';
			element.appendChild( disclaimer );
		}
	}
]
```

This processing approach provides flexibility for implementing complex export logic while ensuring all styles are properly applied to the modified DOM structure.

<a id="real-world-example">

### Real-world example

Here is a simple example showing how to use this feature to export content for an email message:

```js
// Button that exports the editor content for email use.
document.querySelector( '#export-for-email' ).addEventListener( 'click', () => {
	// Get content with inline styles with configuration options.
	editor.execute( 'exportInlineStyles', {
		// Specify which root to use (useful in multi-root editors).
		rootName: 'main',

		// Override editor configuration with email-specific settings.
		stylesheets: [ './email-styles.css' ],
		inlineCss: `
			.ck-content {
				font-family: Arial, sans-serif;
				.quote { font-style: italic; }
			}
		`,
		stripCssClasses: true,

		// Apply email-specific transformations.
		transformations: [
			( element, stylesMap ) => {
				// Make all links color blue and underlined for better email client compatibility.
				if ( element.tagName === 'A' ) {
					stylesMap.set( 'color', '#0066cc' );
					stylesMap.set( 'text-decoration', 'underline' );
				}

				// Ensure all images have explicit width/height (helps with email rendering).
				if ( element.tagName === 'IMG' && !element.getAttribute( 'width' ) ) {
					element.setAttribute( 'width', '300px' );
					element.setAttribute( 'height', '100px' );
				}

				// Ensure paragraphs have margin for email spacing.
				if ( element.tagName === 'P' ) {
					stylesMap.set( 'margin-bottom', '16px' );
				}
			}
		],

		// Remove all classes to prevent dependency on external CSS.
		stripCssClasses: true
	} )
		.then( htmlWithInlineStyles => {
			// Use the exported content in your email sending logic.
			sendEmail( {
				subject: 'Newsletter',
				content: htmlWithInlineStyles,
				recipients: [ 'user@example.com' ]
			} );
		} )
		.catch( error => {
			console.error( 'Failed to export content:', error );
		} );
} );

// Example email sending function (would be replaced with your actual email API).
function sendEmail( emailData ) {
	console.log( 'Sending email with inline-styled content:', emailData );
	// Your email API call would go here:
	// emailAPI.send( emailData );
}
```

<a id="compatibility">

## Compatibility

<a id="supported-features">

### Supported features

* Basic CSS properties (`color`, `background-color`, `font-family`, etc.)
* Compound properties (`background`, `margin`, `padding`, etc.)
* CSS variables (resolved during export)
* Simple CSS selectors (`class`, `id`, `element`)

Supported pseudo-classes:

* Structural pseudo-classes:

  * `:first-child`
  * `:last-child`
  * `:nth-child()`
  * `:only-child`
  * `:empty`
  * `:nth-of-type()`
  * `:first-of-type`
  * `:last-of-type`

* Logical pseudo-classes:

  * `:matches()`
  * `:not()`
  * `:is()`

* Root pseudo-class:
  * `:root`

<a id="limited-or-unsupported-features">

### Limited or unsupported features

* `media` queries

* `@import` and `@font-face` rules

* `@keyframes` and `animation` properties

* `transition` properties

* `:before` and `:after` pseudo-elements

* Interactive state pseudo-classes:

  * `:focus`
  * `:visited`
  * `:link`
  * `:hover`
  * `:active`

* Shadow DOM and `::part()` selectors

<a id="related-features">

## Related features

Here are some other CKEditor 5 features that work well with the export with inline styles feature:

* [Email configuration helper](email-editing/email-configuration-helper.md) – Ensure email-compatible content structure and validate against email client restrictions.
* [General HTML support](html/general-html-support.md) – Add support for additional HTML elements and attributes in your content.
* [Style](style.md) – Apply predefined styles to content elements that can be exported as inline styles.
* [Layout tables](tables/layout-tables.md) – Layout tables are used to structure a web page content spatially rather than for presenting tabular data.

<a id="common-api">

## Common API

The [`ExportInlineStyles`](../api/module_export-inline-styles_exportinlinestyles-ExportInlineStyles.md) plugin registers the [`ExportInlineStyles`](../api/module_export-inline-styles_exportinlinestyles-ExportInlineStyles.md) command.

It accepts the optional `rootName` configuration parameter, which determines the editor root to use for content origin.

> **Note**
>
> We recommend using the official [CKEditor 5 inspector](../framework/development-tools/inspector.md) for development and debugging. It will give you tons of useful information about the state of the editor such as internal data structures, selection, commands, and many more.

---

Full index of the CKEditor 5 documentation: [llms.txt](../../llms.txt)
