Document outline
The document outline feature displays the list of sections (headings) of the document next to the editor. The outline updates automatically as the user works on the document. It offers quick navigation to a specific section upon clicking.
This premium feature is a part of the Productivity Pack available only for customers with a commercial license. Contact us for more details.
You can also sign up for the CKEditor Premium Features 30-day free trial to test the feature.
# Demo
When the feature is enabled and configured, the outline can be displayed next to the document as presented below. The placement of the outline is configurable and depends on the HTML structure of the integration. The demo below showcases one of the recommended integrations but more are possible. See the demo code to learn more.
This demo presents a limited set of features. Visit the feature-rich editor example to see more in action.
# Demo code
For the best user experience the document outline feature requires some effort from integrators. Because it renders independently from the rest of the editor user interface (toolbar, edited content), its placement, dimensions, and behavior (like toggling) depend on the layout and functionality of the web page.
The presented demo is a custom UI built on top of the DecoupledEditor
(similar to the document editor). The editor in this demo loads:
- A set of common editor plugins (
Essentials
,Bold
,Heading
, etc.). - The
DocumentOutline
plugin. - A custom
DocumentOutlineToggler
plugin created for this particular demo to allow toggling the visibility of the outline (learn more in the step-by-step tutorial).
You can find the entire integration code below. To run it, see how to build the editor from source.
View the editor configuration script
import { DecoupledEditor } from '@ckeditor/ckeditor5-editor-decoupled';
import { Alignment } from '@ckeditor/ckeditor5-alignment';
import { Autoformat } from '@ckeditor/ckeditor5-autoformat';
import { Bold, Code, Italic, Strikethrough, Subscript, Superscript, Underline } from '@ckeditor/ckeditor5-basic-styles';
import { BlockQuote } from '@ckeditor/ckeditor5-block-quote';
import { CloudServices } from '@ckeditor/ckeditor5-cloud-services';
import { CodeBlock } from '@ckeditor/ckeditor5-code-block';
import { DocumentOutline } from '@ckeditor/ckeditor5-document-outline';
import { EasyImage } from '@ckeditor/ckeditor5-easy-image';
import { Essentials } from '@ckeditor/ckeditor5-essentials';
import { FontBackgroundColor, FontColor, FontFamily, FontSize } from '@ckeditor/ckeditor5-font';
import { Heading } from '@ckeditor/ckeditor5-heading';
import { HorizontalLine } from '@ckeditor/ckeditor5-horizontal-line';
import { Image, ImageCaption, ImageResize, ImageStyle, ImageToolbar, ImageUpload } from '@ckeditor/ckeditor5-image';
import { Indent, IndentBlock } from '@ckeditor/ckeditor5-indent';
import { Link } from '@ckeditor/ckeditor5-link';
import { List, ListProperties } from '@ckeditor/ckeditor5-list';
import { MediaEmbed } from '@ckeditor/ckeditor5-media-embed';
import { PageBreak } from '@ckeditor/ckeditor5-page-break';
import { Paragraph } from '@ckeditor/ckeditor5-paragraph';
import { RemoveFormat } from '@ckeditor/ckeditor5-remove-format';
import { SelectAll } from '@ckeditor/ckeditor5-select-all';
import { SpecialCharacters, SpecialCharactersEssentials } from '@ckeditor/ckeditor5-special-characters';
import { Table, TableCellProperties, TableProperties, TableToolbar } from '@ckeditor/ckeditor5-table';
import { ButtonView } from '@ckeditor/ckeditor5-ui';
const DOCUMENT_OUTLINE_ICON = '<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M5 9.5a.5.5 0 0 0 .5-.5v-.5A.5.5 0 0 0 5 8H3.5a.5.5 0 0 0-.5.5V9a.5.5 0 0 0 .5.5H5Z"/><path d="M5.5 12a.5.5 0 0 1-.5.5H3.5A.5.5 0 0 1 3 12v-.5a.5.5 0 0 1 .5-.5H5a.5.5 0 0 1 .5.5v.5Z"/><path d="M5 6.5a.5.5 0 0 0 .5-.5v-.5A.5.5 0 0 0 5 5H3.5a.5.5 0 0 0-.5.5V6a.5.5 0 0 0 .5.5H5Z"/><path clip-rule="evenodd" d="M2 19a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H2Zm6-1.5h10a.5.5 0 0 0 .5-.5V3a.5.5 0 0 0-.5-.5H8v15Zm-1.5-15H2a.5.5 0 0 0-.5.5v14a.5.5 0 0 0 .5.5h4.5v-15Z"/></svg>';
const COLLAPSE_OUTLINE_ICON = '<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M11.463 5.187a.888.888 0 1 1 1.254 1.255L9.16 10l3.557 3.557a.888.888 0 1 1-1.254 1.255L7.26 10.61a.888.888 0 0 1 .16-1.382l4.043-4.042z"/></svg>';
// A custom simplified plugin to allow toggling the visibility of the outline.
function DocumentOutlineToggler( editor ) {
const button = new ButtonView( editor.locale );
const documentOutlineContainer = editor.config.get( 'documentOutline.container' );
const demoContainer = documentOutlineContainer.closest( '.demo-container' );
button.set( {
label: 'Toggle document outline',
class: 'ck-document-outline-toggle',
tooltip: 'Hide document outline',
tooltipPosition: 'se',
icon: COLLAPSE_OUTLINE_ICON
} );
button.on( 'execute', () => {
// Toggle a CSS class on the demo container to manage the visibility of the outline.
demoContainer.classList.toggle( 'collapsed' );
// Change the look of the button to reflect the state of the outline.
if ( demoContainer.classList.contains( 'collapsed' ) ) {
button.icon = DOCUMENT_OUTLINE_ICON;
button.tooltip = 'Show document outline';
} else {
button.icon = COLLAPSE_OUTLINE_ICON;
button.tooltip = 'Hide document outline';
}
// Keep the focus in the editor whenever the button is clicked.
editor.editing.view.focus();
} );
button.render();
// Append the button next to the outline in its container.
documentOutlineContainer.appendChild( button.element );
}
// Start the editor.
DecoupledEditor.create( document.querySelector( '.editor-content' ), {
plugins: [
Alignment,
Autoformat,
BlockQuote,
Bold,
CloudServices,
Code,
CodeBlock,
DocumentOutline,
DocumentOutlineToggler,
EasyImage,
Essentials,
FontBackgroundColor,
FontColor,
FontFamily,
FontSize,
Heading,
HorizontalLine,
Image,
ImageCaption,
ImageResize,
ImageStyle,
ImageToolbar,
ImageUpload,
Indent,
IndentBlock,
Italic,
Link,
List,
ListProperties,
MediaEmbed,
PageBreak,
Paragraph,
RemoveFormat,
SelectAll,
SpecialCharacters,
SpecialCharactersEssentials,
Strikethrough,
Subscript,
Superscript,
Table,
TableCellProperties,
TableProperties,
TableToolbar,
Underline
],
toolbar: [
'undo',
'redo',
'|',
'heading',
'|',
'fontFamily',
'fontSize',
'fontColor',
'fontBackgroundColor',
'|',
'bold',
'italic',
'underline',
'removeFormat',
'-',
'link',
'uploadImage',
'insertTable',
'blockquote',
'codeBlock',
'mediaEmbed',
'|',
'alignment',
'|',
'numberedList',
'bulletedList',
'indent',
'outdent'
],
shouldNotGroupWhenFull: true,
image: {
toolbar: [ 'imageStyle:inline', 'imageStyle:wrapText', 'imageStyle:breakText', '|', 'imageTextAlternative' ]
},
table: {
contentToolbar: [ 'tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties' ],
tableToolbar: [ 'bold', 'italic' ]
},
documentOutline: {
container: document.querySelector( '.document-outline-container' )
},
cloudServices: {
// This demo includes the Easy Image feature. Provide correct configuration values to use it.
tokenUrl: 'https://example.com/cs-token-endpoint',
uploadUrl: 'https://your-organization-id.cke-cs.com/easyimage/upload/'
// Read more about Easy Image - https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/easy-image.html.
// For other image upload methods see the guide - https://ckeditor.com/docs/ckeditor5/latest/features/images/image-upload/image-upload.html.
}
} ).then( editor => {
document.querySelector( '.toolbar-container' ).appendChild( editor.ui.view.toolbar.element );
window.editor = editor;
} ).catch( err => {
console.error( err.stack );
} );
View the page layout and styles
<div class="demo-container">
<div class="toolbar-container"></div>
<div class="document-outline-container"></div>
<div class="editor-content-wrapper">
<div class="editor-content">
<p>Initial content of the editor</p>
</div>
</div>
</div>
<style>
/* ----------------------- Demo layout styles ------------------------------ */
.demo-container {
display: grid;
grid-template-columns: minmax(250px,.5fr) 1.5fr;
grid-template-rows: auto 1fr;
gap: 0px 0px;
grid-template-areas:
"Toolbar Toolbar"
"Sidebar Content";
background: var(--ck-color-base-foreground);
border: 1px solid var(--ck-color-base-border);
margin: 1.5em 0;
/* The max height of the editor content wrapper before it becomes scrollable. */
--demo-content-height: 800px;
}
.demo-container .toolbar-container {
grid-area: Toolbar;
box-shadow: 0 2px 3px hsla(0, 0%, 0%, 0.078);
/* Makes the shadow display over the editor content. */
position: relative;
}
/* Adjust borders of the toolbar to fit well into the layout. Avoid duplicated borders. */
.demo-container .toolbar-container > .ck.ck-toolbar {
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
border-top: 0;
border-left: 0;
border-right: 0;
}
.demo-container .editor-content-wrapper {
grid-area: Content;
max-height: var(--demo-content-height);
overflow-y: auto;
/* Center the editor content in this grid area. */
display: flex;
justify-content: center;
align-items: flex-start;
}
.demo-container .document-outline-container {
grid-area: Sidebar;
max-height: var(--demo-content-height);
overflow-y: auto;
display: flex;
flex-direction: column;
padding: var(--ck-spacing-large) 0 0;
/* Customize the default font size of the outline */
--ck-document-outline-base-font-size: 1em;
}
/* ------------ DocumentOutlineToggler plugin styles ------------------- */
/* Styles of the topmost demo container when the outline gets collapsed. */
.demo-container.collapsed {
grid-template-columns: 50px 1fr;
}
/* Styles of the outline when it gets collapsed. */
.demo-container.collapsed .document-outline-container .ck-document-outline {
width: 0px;
margin: 0;
padding: 0;
overflow: hidden;
height: 0;
}
/* Styles of the outline collapse button. */
.demo-container .document-outline-container .ck-document-outline-toggle {
align-self: flex-start;
opacity: .5;
margin-left: var(--ck-spacing-large);
border-radius: 100%;
}
.demo-container .document-outline-container .ck-document-outline-toggle:hover {
opacity: 1;
}
/* ----------------------- Content styles ------------------------------ */
/* Styles of the editor content container to make it look like a sheet of paper. */
.ck.ck-content {
max-width: calc( 210mm + 2px );
min-height: calc( 210mm + 2px );
height: auto;
padding: 20mm 12mm;
box-sizing: border-box;
background: hsl( 0, 0%, 100% );
box-shadow: 0 2px 8px hsla( 0, 0%, 0%, .08 );
margin: calc( 2 * var(--ck-spacing-large) );
overflow: hidden;
flex: 1 1 auto;
}
.ck.ck-content,
.ck.ck-content.ck-focused {
border: 1px solid hsl( 0, 0%, 88% );
box-shadow: 0 2px 8px hsla( 0, 0%, 0%, .08 );
}
/* Vertical rhythm of the blocks in the editor content below. */
.ck.ck-content h2 {
font-size: 2.06em;
line-height: 1.58em;
padding-top: 0.455em;
margin-bottom: 0.333em;
}
.ck.ck-content h3 {
font-size: 1.75em;
line-height: 1.86em;
padding-top: 0.571em;
margin-bottom: 0.357em;
}
.ck.ck-content h4 {
font-size: 1.44em;
line-height: 1.13em;
padding-top: 0.217em;
margin-bottom: 0.913em;
}
.ck.ck-content h5 {
font-size: 1.19em;
line-height: 1.37em;
padding-top: 0.368em;
margin-bottom: 1.00em;
}
.ck.ck-content p {
font-size: 1.00em;
line-height: 1.63em;
padding-top: 0.500em;
margin-bottom: 1.13em;
}
</style>
# Installation
This feature is enabled by default in the superbuild only.
To add the document outline feature to your editor, install the @ckeditor/ckeditor5-document-outline
package:
npm install --save @ckeditor/ckeditor5-document-outline
Then add the DocumentOutline
plugin to your plugin list and configure it:
import { DocumentOutline } from '@ckeditor/ckeditor5-document-outline';
DecoupledEditor
.create( document.querySelector( '#editor' ), {
plugins: [ DocumentOutline, /* ... */ ],
// Provide activation key (see explanation below)
licenseKey: 'your-license-key',
documentOutline: {
container: document.querySelector( '.document-outline-container' ),
}
} )
.then( /* ... */ )
.catch( /* ... */ );
Read more about installing plugins.
# Activating the feature
To use this premium feature, you need to activate it with proper credentials. Refer to the License key and activation guide for details.
# Configuration
For more technical details, check the plugin configuration reference.
# Configuring the container
The container element is essential for the document outline to render. You should pass the reference to the container element in the config.documentOutline.container
configuration option.
documentOutline: {
// Make sure the .document-outline-container element exists when the editor is being created.
container: document.querySelector( '.document-outline-container' )
}
# Customizing the look
The look of the document outline can be customized using CSS classes and custom properties. In the demo below, the following customizations were applied:
- The indentation of outline items was reduced (custom properties:
--ck-document-outline-indent-level-[2-3]
). - The active item color was changed (
--ck-document-outline-item-active-color
custom property). - The font size and line height were reduced for a more compact look (
.ck-document-outline__item
CSS class). - Different bullets were added for each level for better readability (
.ck-document-outline__item_level-[2-3]
CSS classes).
View the document outline customization code
.customization-demo {
--ck-document-outline-indent-level-2: 1.1em;
--ck-document-outline-indent-level-3: 2.2em;
--ck-document-outline-item-active-color: hsl(340deg 82% 52%);
}
.customization-demo .ck-document-outline__item {
line-height: 1.1em;
}
.customization-demo .ck-document-outline__item::before {
margin: 0 .2em 0 0;
}
.customization-demo .ck-document-outline__item.ck-document-outline__item_level-2::before,
.customization-demo .ck-document-outline__item.ck-document-outline__item_level-5::before {
content: "•";
}
.customization-demo .ck-document-outline__item.ck-document-outline__item_level-3 {
font-size: .9em;
}
.customization-demo .ck-document-outline__item.ck-document-outline__item_level-3::before,
.customization-demo .ck-document-outline__item.ck-document-outline__item_level-6::before {
content: "‣";
}
.customization-demo .ck-document-outline__item.ck-document-outline__item_level-4,
.customization-demo .ck-document-outline__item.ck-document-outline__item_level-5,
.customization-demo .ck-document-outline__item.ck-document-outline__item_level-6 {
font-size: .8em;
}
.customization-demo .ck-document-outline__item.ck-document-outline__item_level-4::before {
content: "⁃";
}
# Related features
Here are some more CKEditor 5 features that can help you navigate the content of the editor:
- Table of contents – Insert a table of contents widget into the document.
- Content minimap – Navigate the document using a miniature overview map placed next to the editor.
- Pagination – See the live preview of the document’s page breaks and quickly navigate between pages.
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.