Export to PDF
The export to PDF feature lets you generate a PDF file directly from the editor.
This is a premium feature and you need a license for it on top of your CKEditor 5 commercial license. Contact us to receive an offer tailored to your needs.
You can also sign up for the CKEditor Premium Features 30-day free trial to test the feature.
If this feature is used without authentication, the resulting document will be watermarked.
# Demo
The demo below lets you generate a PDF file based on the editor’s content. Edit the document, then click the export to PDF toolbar button to save the content as a PDF.
The Flavorful Tuscany Meetup
Welcome letter
Dear Guest,
We are delighted to welcome you to the annual Flavorful Tuscany Meetup. We hope you will enjoy the program as well as your stay at the Bilancino Hotel.
Please find attached the full schedule of the event.
The annual Flavorful Tuscany meetups are always a culinary discovery. You get the best of Tuscan flavors during an intense one-day stay at one of the top hotels in the region. All the sessions are led by top chefs passionate about their profession. I would recommend saving the date in your calendar for this one!
Angelina Calvino, food journalist
Please arrive at the Bilancino Hotel reception desk at least half an hour earlier to ensure that the registration process goes as smoothly as possible.
We look forward to welcoming you to the event.
Victoria Valc
Event Manager
Bilancino Hotel
The Flavorful Tuscany Meetup Schedule
Saturday, July 14 | |
---|---|
9:30 AM - 11:30 AM |
Americano vs. Brewed - “know your coffee” with:
|
1:00 PM - 3:00 PM |
Regional delicacies of Tuscany - live cooking Incorporate the freshest ingredients |
5:00 PM - 8:00 PM | Tuscan vineyards at a glance - wine-tasting with Frederico Riscoli |
This demo presents a limited set of features. Visit the feature-rich editor example to see more in action.
# How it works
The PDF export feature collects the HTML generated with the editor.getData()
method and the default editor content styles combined with the styles provided by you in the configuration. It then sends them to the CKEditor Cloud Services HTML to PDF converter service. The service generates a PDF file and returns it to the user’s browser so they can save it in the PDF format on their disk.
The crucial aspect of this feature is its configuration. To ensure that the generated PDF looks as close as possible to the same content displayed in the WYSIWYG editor, the feature must be carefully configured.
The complementary pagination feature allows you to see where page breaks would be after you export the document to PDF. Thanks to the live preview, the user can fine-tune the structure of the output document when editing it. The pagination feature also shows you the page count and lets you navigate between the document pages.
# Before you start
This is a premium feature and you need a license for it. If you do not have one yet, contact us.
You can also sign up for the CKEditor Premium Features 30-day free trial to test the feature.
After you purchase a license, follow the steps below, as explained in the Export to PDF quick start guide:
- Log into the CKEditor Ecosystem customer dashboard.
- Create the token endpoint needed for authorization.
- Install and configure the CKEditor 5 export to PDF plugin.
# Installation
⚠️ New import paths
Starting with version 42.0.0, we changed the format of import paths. This guide uses the new, shorter format. Refer to the Packages in the legacy setup guide if you use an older version of CKEditor 5.
After installing the editor, add the feature to your plugin list and toolbar configuration:
import { ClassicEditor } from 'ckeditor5';
import { ExportPdf } from 'ckeditor5-premium-features';
ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ ExportPdf, /* ... */ ],
toolbar: [ 'exportPdf', '|', /* ... */ ],
exportPdf: {
tokenUrl: 'https://example.com/cs-token-endpoint',
stylesheets: [
'path/to/editor-styles.css',
'path/to/my-styles.css'
],
fileName: 'my-file.pdf',
converterOptions: {
format: 'A4',
margin_top: '20mm',
margin_bottom: '20mm',
margin_right: '12mm',
margin_left: '12mm',
page_orientation: 'portrait'
}
}
} )
.then( /* ... */ )
.catch( /* ... */ );
# Configuration
For more technical details, please check the plugin configuration API.
The configuration is the key to allow the HTML to PDF converter service to generate PDF documents that look as close as possible to the content created in the rich-text editor.
The configuration consists of 3 main parts:
- The converter options that tell the HTML to PDF converter service what is the format of the page (A4, Letter), the page orientation, etc.
- The style sheets sent to the service. They allow styling the content in the PDF document with the same styles that are applied to the content in the editor.
- The content styles used in the editor when rendered on the page.
These options need to stay in sync. For example:
- The style sheets sent to the service must define the same typography that is used in the editor.
- The editor’s content container should be styled in a way that reflects the page size and margins defined in the converter options.
- All web fonts defined on the page where the editor is used must be sent to the service as well.
Read on to learn how to achieve this.
# Default configuration
This is the default configuration of the PDF export feature for CKEditor 5.
{
exportPdf: {
stylesheets: [
'EDITOR_STYLES'
],
fileName: 'document.pdf',
converterUrl: 'https://pdf-converter.cke-cs.com/v1/convert',
converterOptions: {
format: 'A4',
margin_top: '0mm',
margin_bottom: '0mm',
margin_right: '0mm',
margin_left: '0mm',
page_orientation: 'portrait',
header_html: undefined,
footer_html: undefined,
header_and_footer_css: undefined,
wait_for_network: true,
wait_time: 0
},
dataCallback: ( editor ) => editor.getData()
}
}
# EDITOR_STYLES
option
The EDITOR_STYLES
value for the stylesheets
configuration option is the default one, but it will not work with the new installation methods introduced in v42.0.0, which are currently shown as the default in the documentation. We have retained it for backward compatibility, but because the new setup loads stylesheets separately from the editor, it will not work with this string.
The rule of thumb is if you want the export to preserve the styles, always add the style sheets with the content styles of the editor. Their path depends on your application setup, for example:
{
exportPdf: {
stylesheets: [
'./ckeditor5-content.css'
'./styles.css'
],
// ...
}
}
In the snippet above, we assume both style sheets are available via the relative path on the client side. For example, some frameworks allow to place files in the public
folder.
# Plugin options
For some use cases the default configuration will suffice. As you can see in the example above, you can improve how your PDF file will look by adjusting the PDF export plugin configuration.
-
You can set the paths (relative or absolute URLs) to the style sheets that should be included during the HTML to PDF conversion. Prior to the version 42.0.0 of the editor, if you wanted to extend editor’s default content styles, you had to pass a special
'EDITOR_STYLES'
token before a path to your custom styling. This special string is only supported in the legacy setup now (custom builds with webpack or DLLs).Note: The order of the paths matters. If you have custom elements or have overridden the default editor’s content styles, the paths to your file(s) should go after the
'EDITOR_STYLES'
token. See the examples in theconfig.exportPdf.stylesheets
documentation. -
Sets the name for the generated PDF file (together with the extension). The default name is
document.pdf
. You can see it called in the default configuration listing above.This option, however, also allows for using a callback to generate a dynamic file name. In the example below, the document’s title will be used as the file name of the generated PDF file.
// Dynamic file name. const exportPdfConfig = { fileName: () => { const articleTitle = document.querySelector( '#title' ); return `${ articleTitle.value }.pdf`; } }
-
By default, the PDF export feature is configured to use the CKEditor Cloud Services HTML to PDF converter service to generate the PDF files. You can, however, use this option to provide the URL to an on-premises converter. Contact us if you need this feature.
-
A token URL or a token request function. This field is optional and you should use it when you require a different
tokenUrl
for the export to PDF feature. You can skip this option if you use thecloudServices
configuration to provide the sametokenUrl
. In most cases you will probably want to provide the token incloudServices
, as other plugins like Easy Image or real-time collaboration will use this token as well. In this guide, to explicitly show that this value is needed, we leave it the insideexportPdf
configuration. -
config.exportPdf.converterOptions
The plugin allows you to provide a custom HTML to PDF converter configuration.
-
By default, the plugin uses
editor.getData()
to gather the HTML sent to the conversion service. You can use this option to customize the editor’s data. For example, use this setting to enable highlighting tracked changes in the exported PDF file.dataCallback: editor => editor.getData( { showSuggestionHighlights: true } ),
The config.exportPdf.dataCallback
option may be useful when:
- Handling multi-root editor.
- Handling track changes suggestions preview.
- Adding a watermark to the document.
# HTML to PDF converter features
# Images
Currently, the plugin only supports absolute URLs as well as the Base64
format for images. See the converter documentation.
# Web fonts
If you are using web fonts via an @import
or @font-face
declaration, you can pass the path(s) to the .css
file(s) containing them to the config.exportPdf.stylesheets
. The order of the provided paths matters – you should list style sheets with web font declarations first. For more technical details, check the API documentation and converter documentation.
# Header and footer
The converter lets you set the document’s header and footer similarly to Microsoft Word or Google Docs.
const converterOptions = {
margin_top: '15mm',
margin_bottom: '15mm',
margin_right: '15mm',
margin_left: '15mm',
header_html: '<div class="styled">Header content</div>',
footer_html: '<div class="styled-counter"><span class="pageNumber"></span></div>',
header_and_footer_css: '#header, #footer { background: hsl(0, 0%, 95%); } .styled { font-weight: bold; text-align: center; } .styled-counter { font-size: 1em; color: hsl(0, 0%, 60%); }',
}
Note:
- To ensure that the header or footer is displayed, the margin must be big enough to accommodate it. In the code above,
margin_top
corresponds with the header andmargin_bottom
– with the footer. In this example, the height of both elements will equal15mm
. - You can set a background for the header and footer. To achieve this, use the
#header
or#footer
selector in theheader_and_footer_css
option. Do not use these IDs in theheader_html
orfooter_html
options to avoid duplication. These elements are provided by the HTML to PDF converter.
As you can see in the example above, you can even set the pageNumber
. But there is more – for details, refer to the converter’s documentation.
# Other
- By default, the generated PDF file is encoded with
UTF-8
. - By default, the converter sets
color-adjust: exact;
. This means that your PDF document will preserve colors, images, and styles as you can see them in the editor. - The generated document can be watermarked. See the example and demo in the section below.
# Examples
Check out some configuration examples that will show you how to customize the export to PDF feature. In the first example, you will learn how to add custom styling. The second example will show you how to set the page format. In the third one, you can see how to use web fonts in your configuration.
# Re-using custom editor styling
The default configuration of the ExportPdf
plugin attaches the default editor content styles to the HTML content sent to the converter.
However, if you need to, you can also set paths to additional CSS files. Let us assume that you already have a my-custom-editor-styles.css
with your custom styling for the editor content that you use on your website, but you also want to include these styles in the generated PDF file.
Here is the example code:
import { ClassicEditor } from 'ckeditor5';
import { ExportPdf } from 'ckeditor5-premium-features';
ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ ExportPdf, /* ... */ ],
toolbar: [ 'exportPdf', '|', /* ... */ ],
exportPdf: {
stylesheets: [
'path/to/editor-styles.css',
'path/to/my-styles.css'
],
fileName: 'my-document.pdf'
}
} )
.then( /* ... */ )
.catch( /* ... */ );
This is how the corresponding editor styles may look like:
/* my-custom-editor-styles.css */
/* Custom link color. */
.ck.ck-content a {
color: purple;
}
/* Custom header styling. */
.ck.ck-content h1 {
border-bottom: 2px solid;
}
/* Another custom styling... */
/* ... */
With these settings, the content in the generated PDF file should have the same styling as it has in the WYSIWYG editor.
You are not obligated to use .ck.ck-content
selectors to style your content. If your implementation contains custom CSS classes, you can use them instead.
# Setting the page format
Consistency is an important factor. To make sure that the editor content and the generated PDF file look the same, you need to match their format settings. You can change your existing style sheet or use a new one, for example, format.css
. By default, the CKEditor Cloud Services HTML to PDF converter is set to A4 format, but you may change this setting in your configuration.
Assuming that you want to create a document in the US Letter format, with the standard margins (19mm
for each side), here is the example code you can use:
import { ClassicEditor } from 'ckeditor5';
import { ExportPdf } from 'ckeditor5-premium-features';
ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ ExportPdf, /* ... */ ],
toolbar: [ 'exportPdf', '|', /* ... */ ],
exportPdf: {
stylesheets: [
'path/to/editor-styles.css',
'path/to/my-styles.css'
],
fileName: 'my-document.pdf',
converterOptions: {
// Document format settings with proper margins.
format: 'Letter',
margin_top: '19mm',
margin_bottom: '19mm',
margin_right: '19mm',
margin_left: '19mm',
page_orientation: 'portrait'
}
}
} )
.then( /* ... */ )
.catch( /* ... */ );
This example focuses only on preparing the editable to match the converter settings. As a result, the appearance of your editor may change. Depending on your editor type and implementation or even some inherited global styles like box-sizing
, applying new padding
values may change the size of the editor on your website.
For this example, box-sizing: border-box
was implemented to make sure that the editor’s width would not change.
Now set the corresponding editor styles:
/* format.css */
/* Styles for the editable. */
.ck.ck-content.ck-editor__editable {
/* US Letter size. */
width: 215.9mm;
/* Padding is your document's margin. */
padding: 19mm;
/* You do not want to change the size of the editor by applying the new padding values. */
box-sizing: border-box;
/* ... */
}
With these settings, the content in the generated PDF file should have the same US Letter format layout as it has in the editor.
# Providing web font styles
This time you want to add a web font to your plugin. Let us assume that the editor is used on a page with certain typography, so the content in the editor inherits the font styles from the page. As such, these styles need to be passed to the HTML to PDF converter service.
The example below uses a web font from the Google Fonts service. For your convenience, the @import
declaration and any font styles needed for your website are kept in a separate file, for example, fonts.css
.
/* fonts.css */
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;700&display=swap');
html, body {
font-family: "Source Sans Pro", sans-serif;
/* ... */
}
/* ... */
This allows you to use the web font settings in the plugin, without any additional tweaks. Just pass the path to the file in the config.exportPdf.stylesheets
configuration option.
The order matters here. Font declarations should be at the beginning of the style sheets’ array. Otherwise, there is no guarantee that the font styling will be applied to the PDF file. Refer to the config.exportPdf.stylesheets
API documentation for more details.
import { ClassicEditor } from 'ckeditor5';
import { ExportPdf } from 'ckeditor5-premium-features';
ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ ExportPdf, /* ... */ ],
toolbar: [ 'exportPdf', '|', /* ... */ ],
exportPdf: {
stylesheets: [
'path/to/fonts.css',
'path/to/editor-styles.css',
'path/to/my-styles.css'
],
// More configuration of the export to PDF feature.
// ...
}
} )
.then( /* ... */ )
.catch( /* ... */ );
Thanks to this, the editor inherits the font settings and you can be sure that they will be applied in the generated PDF file as well.
Take a look at another example of a fonts.css
file. Suppose that your website uses the Source Sans Pro
font as before but this time you want the Inter
font to be used in the WYSIWYG editor. The file should look like this:
/* fonts.css */
/* Import the web font for your website. */
@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;700&display=swap');
/* Import the web font for your editor. */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
/* Use the Source Sans Pro web font in your website. */
html, body {
font-family: "Source Sans Pro", sans-serif;
/* ... */
}
/* Use the Inter web font in your editor. */
.ck.ck-content.ck-editor__editable {
font-family: "Inter", sans-serif;
/* ... */
}
/* ... */
Having the file set like this for your website and just re-using it in config.exportPdf.stylesheets
makes the whole setup as simple as possible.
# Adding a watermark to the document
Apart from adding a header and a footer, there is also the possibility of adding a watermark to the generated document. This can be achieved by utilizing config.exportPdf.dataCallback
.
To do this, you need to get the data that is being sent to the converter first and update it with a watermark markup:
exportPdf: {
// More configuration of the export to PDF.
// ...
dataCallback: ( editor ) => {
return `
${ editor.getData() }
<div class="watermark">Draft document</div>
`;
},
// More configuration of the export to PDF.
// ...
}
Then update the custom CSS file with the proper styles:
.watermark {
font-size: 50px;
opacity: 0.5;
color: black;
position: fixed;
left: 20%;
top: 50%;
transform: rotate(25deg);
letter-spacing: 10px
}
Below you can see a simplified demo with the final result. Click the toolbar button to generate the document with a watermark.
The Famous Einstein Quote that never was
You might have come across the following quote in the past few years:
Everybody is a genius. But if you judge a fish by its ability to climb a tree, it will live its whole life believing that it is stupid.
Albert Einstein
It has been most popular on Facebook and other social networks, where people share it aplenty. No wonder: it is neat, it sounds smart, and, let’s be frank, Albert is one hell of a figure! The truth is not as neat, though. And mindlessly forwarding the quote isn’t exactly smart. That’s because Einstein never said that. The quote comes from the 2004 book The Rhythm of Life: Living Every Day with Passion and Purpose by Mathew Kelly, published almost 50 years after Albert’s death in 1955.
Kelly was likely inspired by an essay by Amos E. Dolbear of Tufts titled “An Educational Allegory,” describing animals educated to work on their weakest features instead of their strongest ones. There is also the 1903 “Jungle School Boards” fable that tells a story of a monkey, a kangaroo, and an elephant who cannot agree on the curriculum for their animal school — should all the little animals be taught tree-climbing, jumping, or looking wise?
In the late 1940s, something that appears to be an amalgam of the two was published and later reprinted with various changes in the 1960s. The idea evolved for decades and got mixed up with a few other quotes about being a genius originating back in the 1970s. Finally, Kelly wrote in his 2004 book:
Albert Einstein wrote, “Everybody is a genius. But if you judge a fish by its ability to climb a tree, it will live its whole life believing that it is stupid.” The question I have for you at this point of our journey together is, “What is your genius?”
Why he attributed this to Albert Einstein remains unclear. The fact is, the quote got popular. But, apparently, not everyone is a genius when it comes to fact-checking and sources.
# Known issues
Not all CKEditor 5 plugins and features are compatible with export to PDF at the moment. Here is a list of known issues:
- Media embed – Not supported.
- MathType – Not fully supported yet. Right now the plugin parses the data but not the formatting. Feel free to contact us if you are interested in this feature.
# Related features
- The complementary pagination feature provides live preview of the document’s page breaks, ensuring the output document looks correct.
- If you would like to export your content to an editable format, using the export to Word feature will allow you to generate
.docx
files out of your editor-created content. - If you would like to use the track changes feature and show suggestion highlights in the PDF, refer to the Saving data with suggestion highlights section.
# Common API
The ExportPdf
plugin registers:
-
The
'exportPdf'
button. -
The
'exportPdf'
command implemented byExportPdfCommand
.You can execute the command using the
editor.execute()
method. However, if you want to use the command directly (not via the toolbar button), you need to specify the options or gather them from the configuration. Otherwise, the command will not execute properly.An example code to use the command directly should look like this:
// Start generating a PDF file based on the editor content and the plugin configuration. const config = editor.config.get( 'exportPdf' ); editor.execute( 'exportPdf', config );
Every day, we work hard to keep our documentation complete. Have you spotted outdated information? Is something missing? Please report it via our issue tracker.
With the release of version 42.0.0, we have rewritten much of our documentation to reflect the new import paths and features. We appreciate your feedback to help us ensure its accuracy and completeness.