Contribute to this guide

guideTables

The Table feature offers table creation and editing tools that help content authors bring tabular data into their documents. Tables help organize the content in a distinct, visual way that stands out from the text and is more easily readable for certain types of information. They are perfect for listing, grouping, and otherwise organizing data sets or for providing information in a clear, efficient way.

Tables are great for schedules, timetables, price lists or menus; for listing terms and conditions or providing troubleshooting solutions. They also visually break and provide relief from large body texts. CKEditor 5 offers all necessary functionality to produce advanced, visually appealing and highly efficient tables.

You may look for more interesting details in the Tables in CKEditor 5 blog post after reading this guide.

# Demos

# Basic table features

The editor bellow shows the basic set of table features focusing on the structure and semantics. Use the Insert table toolbar button Insert table in the editor below to create new tables. Focus any cell in the table to display the toolbar with buttons that will help you further shape the structure of the table.

Click anywhere inside the table to invoke the table toolbar. The features available in there allow users to add or remove columns Table column and rows Table row and merge or split cells Table cell. It is also worth noting that you will find them out–of–the–box in all ready–to–use editor builds.

The ultimate table of spaceflight:

Presented below is a list of the first countries to send a human into space. Listed below these are countries able to launch their own manned spacecraft (the other listed astronauts were sent to space onboard a foreign spacecraft).

Countries that sent their citizen into space

Country

Date of launch

Name

Spacecraft

USSR 1961 Yuri Gagarin Vostok-1
USA 1961 Alan Shepard Mercury-Redstone 3
Czechoslovakia 1978 Vladimír Remek Soyuz 28
Poland 1978 Mirosław Hermaszewski Soyuz 30
East Germany 1978 Sigmund Jähn Soyuz 31

Countries capable of sending their own manned spacecraft

Country

Capable since

First astronaut

Current spacecraft

USSR/Russia 1961 Yuri Gagarin Soyuz MS
USA 1961 Alan Shepard Crew Dragon
China 2003 Yang Liwei Shenzhou

# Table and cell styling tools

In addition to the default table features described in the previous section, the editor below comes with some additional tools that will help you modify the look of tables and table cells, for instance, their border color and style, background color, padding, or text alignment. The table Table properties and cell properties Cell properties are available from the table toolbar on click, just like basic table features.

The planet of robots

Humans have always searched for new places to explore and new ways to get where they wanted. Where no human could (yet) go, we would send robots to do a job for us. Mars, one of our closest neighbours, is currently home to quite a few robotic devices, some of which are able to move around freely, roaming the wild, red sands and relaying their experience back to the mother planet.

Color coding for missions
Failed Successful In progress Planned
Country/Agency Rover Date of landing Operational time Distance travelled Notes
Soviet Union
PROP-M rover November 27, 1971 0 days 0 km Lost when it crash-landed on Mars
Soviet Union
PROP-M rover December 2, 1971 0 days 0 km Lost when Mars 3 lander stopped communicating about 20 seconds after landing
United States
Sojourner July 4, 1997 85 days 100 m (330 ft) First successful rover on Mars
United States
Spirit January 4, 2004 2269 days 7.73 km (4.80 mi)  
United States
Opportunity January 25, 2004 5498 days 45.16 km (28.06 mi) The longest distance traveled by any rover and the most days operated
United States
Curiosity January 25, 2012 3214 days 24.85 km (15.44 mi)
as of 4 March 2021
Currently active
United States
Perseverance February 18, 2021 96 days 322 m (1,056 ft)
as of 14 May 2021
Currently active
China
Zhurong May 14, 2021 11 days   Currently active
Europe
Rosalind Franklin 2023 (planned) 420 days (planned)   Planned to launch 2022
Data source: Wikipedia

Put the caret anywhere inside the table to invoke the table toolbar. Then click the “Table properties” button in the toolbar to open a pop–up with multiple options that will allow you to shape the look of the entire table. If you click the “Cell properties” button, a similar interface will appear with styling options for individual table cells.

Learn more about configuring color palettes in the table styling pop–up interfaces.

By default, table styling tools are not included in the ready–to–use editor builds and must be installed separately. See the installation section to learn how to enable them in your editor.

# Table caption

The TableCaption plugin adds support for table captions. These work very much like image captions — the caption informs the reader about the content of the table. Using captions is also beneficial from the accessability point of view as they would be read by screen readers.

Click on the table caption in the demo to edit it or use the table toolbar button Table caption to toggle the caption on and off.

Name Mass (1024kg) Diameter (km) Gravity (m/s2) Length of day (hours) Distance from Sun (106km) Mean temperature (°C)
Mercury 0.330 4,879 3.7 4222.6 57.9 167
Venus 4.87 12,104 8.9 2802.0 108.2 464
Earth 5.97 12,756 9.8 24.0 149.6 15
Mars 0.642 6,792 3.7 24.7 227.9 -65
Jupiter 1898 142,984 23.1 9.9 778.6 -110
Saturn 568 120,536 9.0 10.7 1433.5 -140
Uranus 86.8 51,118 8.7 17.2 2872.5 -195
Neptune 102 49,528 11.0 16.1 4495.1 -200
Data about the planets of the Solar System. Planetary facts taken from Nasa's Planetary Fact Sheet - Metric.

By default, the table caption feature is not included in the ready–to–use editor builds and must be installed separately. See the installation section to learn how to enable it in your editor.

By default, the table caption is placed above the table. You can change the placement by setting caption-side in your content styles for the .ck-content .table > figcaption style. Changing it to caption-side: bottom will display the caption below the table.

# Nesting tables

Starting from version 27.1.0 CKEditor 5 allows nesting tables inside other table’s cells. This may be used for creating advanced charts or layouts based on tables. The nested table can be formatted just like a regular one.

You can test this feature in the demo below by adding a table in the “abandoned” section that was left blank at the bottom of the main table. To nest a table, simply click in the selected cell and use the “Insert table” button in the toolbar to insert a new, nested table into an existing one.

American spacecraft

Status Name and service time
discontinued
Mercury 1961-1963
Gemini 1965-1966
Apollo 1968-1975
Space shuttle 1981-2011
in use
Crew Dragon since 2020
planned
Boeing Starliner planned 2021 or 2022
Orion planned 2023
abandoned

If you would like to block the possibility to nest tables in your editor, see the Disallow nesting tables section to learn how to disable this functionality.

# Table selection

The TableSelection plugin introduces support for the custom selection system for tables that lets you:

  • Select an arbitrary rectangular table fragment — a few cells from different rows, a column (or a few of them) or a row (or multiple rows).
  • Apply formatting or add a link to all selected cells at once.

The table selection plugin is loaded automatically by the Table plugin and can be tested in the demos above.

# Installation

# Basic table features

The basic table features are enabled by default in all builds. The installation instructions are for developers interested in building their own, custom rich text editor.

To add only the basic table features to your editor, install the @ckeditor/ckeditor5-table package:

npm install --save @ckeditor/ckeditor5-table

Then add the Table and TableToolbar plugins to your plugin list and configure the table toolbar:

import Table from '@ckeditor/ckeditor5-table/src/table';
import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ Table, TableToolbar, Bold, ... ],
        toolbar: [ 'insertTable', ... ],
        table: {
            contentToolbar: [ 'tableColumn', 'tableRow', 'mergeTableCells' ]
        }
    } )
    .then( ... )
    .catch( ... );

# Default table headers

In order to make every inserted table to have n number of rows and columns as table headers by default, set an optional table config property defaultHeadings as follows:

import Table from '@ckeditor/ckeditor5-table/src/table';
import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ Table, TableToolbar, Bold, ... ],
        toolbar: [ 'insertTable', ... ],
        table: {
            defaultHeadings: { rows: 1, columns: 1 }
        }
    } )
    .then( ... )
    .catch( ... );

Check the table with default headers applied to both the first row and the first column in the demo below. Click on the table and use the column properties Table column or the row properties Table row UI button to toggle the respective headers.

Financial report

Main product line for Q4.

 

Sales

Income

Revenue

Walker

1050

$104.000

15%

Stroller

24

$12.000

10%

Walker 3

980

$97.000

15%

# Table and cell styling tools

To enable not only the basic table features but also the rich table and cell styling tools in your editor, install the @ckeditor/ckeditor5-table package:

npm install --save @ckeditor/ckeditor5-table

Then add the Table, TableToolbar, TableProperties, and TableCellProperties plugins to your plugin list and configure the table toolbar:

import Table from '@ckeditor/ckeditor5-table/src/table';
import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';
import TableProperties from '@ckeditor/ckeditor5-table/src/tableproperties';
import TableCellProperties from '@ckeditor/ckeditor5-table/src/tablecellproperties';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ Table, TableToolbar, TableProperties, TableCellProperties, Bold, ... ],
        toolbar: [ 'insertTable', ... ],
        table: {
            contentToolbar: [
                'tableColumn', 'tableRow', 'mergeTableCells',
                'tableProperties', 'tableCellProperties'
            ],

            // Configuration of the TableProperties plugin.
            tableProperties: {
                // ...
            },

            // Configuration of the TableCellProperties plugin.
            tableCellProperties: {
                // ...
            }
        }
    } )
    .then( ... )
    .catch( ... );

Learn more about configuring color palettes in the table and table cell property pop–ups.

Read more about installing plugins.

# Table caption

To enable the table caption feature in your editor, install the @ckeditor/ckeditor5-table package:

npm install --save @ckeditor/ckeditor5-table

Then add the Table, TableToolbar, and TableCaption plugins to your plugin list and configure the table toolbar:

import Table from '@ckeditor/ckeditor5-table/src/table';
import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';
import TableCaption from '@ckeditor/ckeditor5-table/src/tablecaption';

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ Table, TableToolbar, TableCaption, Bold, ... ],
        toolbar: [ 'insertTable', ... ],
        table: {
            contentToolbar: [
                'toggleTableCaption'
            ]
        }
    } )
    .then( ... )
    .catch( ... );

Read more about installing plugins.

# Configuring styling tools

By default, table styling tools are not included in ready–to–use editor builds and must be installed separately. See the installation section to learn how to enable them in your editor.

Among other formatting options, table and cell styling tools allow users to create tables with colorful backgrounds and borders. These colors can be easily picked using color palettes in the “Table properties” and “Cell properties” pop–ups. To help users choose the right colors for the content, the color palettes can be pre–configured, like in the editor below:

A beautiful color palette

Red Pink Purple Deep Purple
Indigo Blue Light Blue Cyan
Teal Green Light Green Lime
Yellow Amber Orange Deep Orange
Brown Grey Blue Grey White

With the selection inside any table cell, use the “Table properties” and “Cell properties” buttons in the toolbar to inspect available styling and color options.

# Customizing color palettes

You can use these specific configuration options to define customized color palettes for background and border colors to match your document:

The above configurations do not impact the data loaded into the editor, i.e. they do not limit or filter the colors in the data. They are used only in the user interface allowing users to pick colors in a more convenient way.

For instance, to define the same color palette for all border and background configurations, use the following code snippet:

const customColorPalette = [
    {
        color: 'hsl(4, 90%, 58%)',
        label: 'Red'
    },
    {
        color: 'hsl(340, 82%, 52%)',
        label: 'Pink'
    },
    {
        color: 'hsl(291, 64%, 42%)',
        label: 'Purple'
    },
    {
        color: 'hsl(262, 52%, 47%)',
        label: 'Deep Purple'
    },
    {
        color: 'hsl(231, 48%, 48%)',
        label: 'Indigo'
    },
    {
        color: 'hsl(207, 90%, 54%)',
        label: 'Blue'
    },

    // ...
];

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        plugins: [ Table, TableToolbar, TableProperties, TableCellProperties, Bold, ... ],
        toolbar: [ 'insertTable', ... ],
        table: {
            contentToolbar: [
                'tableColumn', 'tableRow', 'mergeTableCells',
                'tableProperties', 'tableCellProperties'
            ],

            // Set the palettes for tables.
            tableProperties: {
                borderColors: customColorPalette,
                backgroundColors: customColorPalette
            },

            // Set the palettes for table cells.
            tableCellProperties: {
                borderColors: customColorPalette,
                backgroundColors: customColorPalette
            }
        }
    } )
    .then( ... )
    .catch( ... );

# Default table and table cell styles

The table styles feature allows for configuring the default look of the tables in the editor. The configuration object should be synchronized with the editor content styles.

The “Table properties” and “Table cell properties” buttons in the toolbar will show the table and table cell properties applied to the table or table cells.

The stylesheet for the editor displayed below looks as follows:

.ck-content .table {
    float: left;
    width: 550px;
    height: 450px;
}

.ck-content .table table {
    border-style: dashed;
    border-color: 'hsl(90, 75%, 60%)';
    border-width: 3px;
}

.ck-content .table table td {
    text-align: center;
    vertical-align: bottom;
    padding: 10px
}

The same values must be passed to the editor configuration as:

const tableConfig = {
    table: {
        tableProperties: {
            // The default styles for tables in the editor.
            // They should be synchronized with the content styles.
            defaultProperties: {
                borderStyle: 'dashed',
                borderColor: 'hsl(90, 75%, 60%)',
                borderWidth: '3px',
                alignment: 'left',
                width: '550px',
                height: '450px'
            },
            // The default styles for table cells in the editor.
            // They should be synchronized with the content styles.
            tableCellProperties: {
                defaultProperties: {
                    horizontalAlignment: 'center',
                    verticalAlignment: 'bottom',
                    padding: '10px'
                }
            }
        }
    }
};

The table element should be aligned to the left side by default. Its size should be 550x450px. The border style should be dashed, 3px of its width, and the color specified as Light green.

The content should be away about 10px from the cell’s edges (padding), vertically aligned to bottom and horizontally to center.

The same will be applied for new tables and cells if they are inserted into the editor.

Before people could leave the cradle of humanity and enter the cosmic void, tests were required. A number of animals risked and sometimes lost their lives to open the gates for their owners to be able to reach the stars.

The animal spaceflights started in the late 1940s. German A4 rockets were used for the initial launches, later on each country developed their own carriers. Even though these simian, canine and rodent space farers were the most important test subjects during the first stage of the space race, before launching actual human astronauts, the animal spaceflight is very much a thing even today. In 2018 a rodent crew arrived at International Space Station!

Animal astronauts by country of origin

American: fruit flies, primates first flew in the 1940s.

The most memorable was Ham, a chimpanzee.

Soviet: mostly dogs, sent to space since the 1950s.

The most memorable was Laika who died during the first part of the journey.

French: rats and cats (1960s).

 Félicette was the most notable and the only French cat to survive the landing.

Chinese: mice, rats and dogs (1960s).

Read more about all supported properties for the table and table cell features in their API documentation.

The default table and table cell styles do impact the data loaded into the editor. Default properties will not be kept in the editor model.

# Block vs inline content in table cells

The table feature allows for creating block content (like paragraphs, lists, headings, etc.) inside table cells. However, if a table cell contains just one paragraph and this paragraph has no special attributes (like text alignment), the cell content is considered “inline” and the paragraph is not rendered.

This means that a table cell can have two states: with inline content or with block content. The reason for this differentiation is that most tables contain only inline content (e.g. in the demo above) and it is common for “data tables” to not contain any block content. In such a scenario, printing out <p> elements would be semantically incorrect and also unnecessary. There are, however, scenarios where the user wants to create, for example, a list inside a table cell and then the support for block content is necessary.

“Rendering” here refers to the view layer. In the model, a cell is always filled with at least a <paragraph>. This is because of consistency, as — since a cell always has some block content — the text is never directly inside the <tableCell>. This also allows features like Enter support to work out of the box (since a <paragraph> exists in the model, it can be split despite the fact that it is not present in the view).

# Inline content

The following is the model representation of table cells with inline content only (a single <paragraph> inside):

<table>
    <tableRow>
        <tableCell>
            <paragraph>Foo</paragraph>
        </tableCell>
        <tableCell>
            <paragraph>Bar</paragraph>
        </tableCell>
    </tableRow>
</table>

The above model structure will be rendered to the data as:

<figure class="table">
    <table>
        <tbody>
            <tr>
                <td>Foo</td>
                <td>Bar</td>
            </tr>
        </tbody>
    </table>
</figure>

In the editing view (the editable container in which the user edits the content), additional <span> elements are created to compensate for the hidden <paragraph> elements:

<figure class="table">
    <table>
        <tbody>
            <tr>
                <td><span>Foo</span></td>
                <td><span>Bar</span></td>
            </tr>
        </tbody>
    </table>
</figure>

# Block content

If a table cell contains any other block content than a single <paragraph> with no attributes, these block elements will be rendered.

The following is a sample table with some block content (model representation):

<table>
    <tableRow>
        <tableCell>
            <paragraph>Foo</paragraph>
            <paragraph>Bar</paragraph>
        </tableCell>
        <tableCell>
            <heading1>Some title</heading1>
        </tableCell>
        <tableCell>
            <paragraph textAlign="right">Baz</paragraph>
        </tableCell>
    </tableRow>
</table>

The above model structure will be rendered to the data and to the editing view as:

<figure class="table">
    <table>
        <tbody>
            <tr>
                <td>
                    <p>Foo</p>
                    <p>Bar</p>
                </td>
                <td>
                    <h2>Some title</h2>
                </td>
                <td>
                    <p style="text-align: right;">Baz</p>
                </td>
            </tr>
        </tbody>
    </table>
</figure>

At the moment, it is not possible to completely disallow block content in tables. See the discussion on GitHub about adding a configuration option that would enable that. Feel free to upvote 👍  if this feature is important to you.

# Disallow nesting tables

By default, the editor allows nesting a table inside another table’s cell.

In order to disallow nesting tables, you need to register an additional schema rule. It needs to be added before the data is loaded into the editor. Due to that, it is best to implement it as a plugin:

function DisallowNestingTables( editor ) {
    editor.model.schema.addChildCheck( ( context, childDefinition ) => {
        if ( childDefinition.name == 'table' && Array.from( context.getNames() ).includes( 'table' ) ) {
            return false;
        }
    } );
}

// Pass it via config.extraPlugins or config.plugins:

ClassicEditor
    .create( document.querySelector( '#editor' ), {
        extraPlugins: [ DisallowNestingTables ],

        // The rest of the configuration.
    } )
    .then( ... )
    .catch( ... );

Check the plugin development guide if you need more information about the technical side of this solution.

# Common API

# UI components

The table plugins register the following UI components:

Component name Registered by
The 'insertTable' dropdown Table
The 'tableColumn' dropdown
The 'tableRow' dropdown
The 'mergeTableCells' split button
The 'tableProperties' button TableProperties
The 'toggleTableCaption' button TableCaption
The 'tableCellProperties' button TableCellProperties

# Toolbars

The TableToolbar plugin introduces two balloon toolbars for tables.

  • The content toolbar shows up when a table cell is selected and it is anchored to the table. It is possible to configure its content. Normally, the toolbar contains the table-related tools such as 'tableColumn' and 'tableRow' dropdowns and 'mergeTableCells' split button.
  • The table toolbar shows up when the whole table is selected, for instance using the widget handler. It is possible to configure its content.

# Editor commands

Command name Command class Belongs to (top–level plugin)
'insertTable' InsertTableCommand Table
'insertTableColumnLeft' InsertColumnCommand
'insertTableColumnRight' InsertColumnCommand
'insertTableRowAbove' InsertRowCommand
'insertTableRowBelow' InsertRowCommand
'removeTableColumn' RemoveColumnCommand
'removeTableRow' RemoveRowCommand
'selectTableColumn' SelectColumnCommand
'selectTableRow' SelectRowCommand
'setTableColumnHeader' SetHeaderColumnCommand
'setTableRowHeader' SetHeaderRowCommand
'mergeTableCellRight' MergeCellCommand
'mergeTableCellLeft' MergeCellCommand
'mergeTableCellUp' MergeCellCommand
'mergeTableCellDown' MergeCellCommand
'splitTableCellVertically' SplitCellCommand
'splitTableCellHorizontally' SplitCellCommand
'toggleTableCaption' ToggleTableCaptionCommand TableCaption
'tableBorderColor' TableBorderColorCommand TableProperties
'tableBorderStyle' TableBorderStyleCommand
'tableBorderWidth' TableBorderWidthCommand
'tableAlignment' TableAlignmentCommand
'tableWidth' TableWidthCommand
'tableHeight' TableHeightCommand
'tableBackgroundColor' TableBackgroundColorCommand
'tableCellBorderStyle' TableCellBorderStyleCommand TableCellProperties
'tableCellBorderColor' TableCellBorderColorCommand
'tableCellBorderWidth' TableCellBorderWidthCommand
'tableCellHorizontalAlignment' TableCellHorizontalAlignmentCommand
'tableCellWidth' TableCellWidthCommand
'tableCellHeight' TableCellHeightCommand
'tableCellPadding' TableCellPaddingCommand
'tableCellBackgroundColor' TableCellBackgroundColorCommand
'tableCellVerticalAlignment' TableCellVerticalAlignmentCommand

We recommend using the official CKEditor 5 inspector 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.

# Known issues

While the table nesting functionality is fully functional, the Markdown code generated with the Markdown output feature will not properly render nested tables (#9475). Feel free to upvote 👍  this issue on GitHub if it is important for you.

# Contribute

The source code of the feature is available on GitHub in https://github.com/ckeditor/ckeditor5/tree/master/packages/ckeditor5-table.