Table Rows

Basic row structure

There are multiple ways to group cells into a row. The cells in a row can be placed on:

Cells on the same line
|===

|Cell in column 1, row 1 |Cell in column 2, row 1 |Cell in column 3, row 1

|Cell in column 1, row 2 |Cell in column 2, row 2 |Cell in column 3, row 2

|===
Result: Rendered table when multiple cells where entered on the same line

Cell in column 1, row 1

Cell in column 2, row 1

Cell in column 3, row 1

Cell in column 1, row 2

Cell in column 2, row 2

Cell in column 3, row 2

When the cells of a row are individually entered on consecutive lines, the cols attribute is needed to specify the number of columns in the table. If the cols attribute is not set, the first non-blank line inside the block delimiter (|===) determines the number of columns.

Cells on consecutive, individual lines
[cols="3*"] (1)
|===
|Cell in column 1, row 1
|Cell in column 2, row 1
|Cell in column 3, row 1

|Cell in column 1, row 2
|Cell in column 2, row 2
|Cell in column 3, row 2
|===
1 The cols attribute states that this table has three columns. The * is a repeat operator which is explained in column specifiers.
Result: Rendered table when cells where listed on consecutive, individual lines

Cell in column 1, row 1

Cell in column 2, row 1

Cell in column 3, row 1

Cell in column 1, row 2

Cell in column 2, row 2

Cell in column 3, row 2

Rows can be formed from adjacent lines of individual cells and cells listed on the same line.

Cells on the same line and individual lines
[cols="3*"]
|===
|Cell in column 1, row 1 |Cell in column 2, row 1
|Cell in column 3, row 1

|Cell in column 1, row 2
|Cell in column 2, row 2 |Cell in column 3, row 2
|===
Result: Cells on the same line and individual lines

Cell in column 1, row 1

Cell in column 2, row 1

Cell in column 3, row 1

Cell in column 1, row 2

Cell in column 2, row 2

Cell in column 3, row 2

The next sections describe and demonstrate the variety of ways you can customize table cells, rows and columns.

Header row

The first row of a table is promoted to a header row if the header option is set (either explicitly or implicitly).

You can enable the header option by adding the header keyword to the comma-separated list of values in the options attribute on the table. You can also enable the header option by adding the %header directive to the table style (the first positional attribute).

In the example below, the table has an attribute list containing an options attribute that includes the header option.

Table with the header value assigned to the options attribute
[cols=2*,options="header"]
|===
|Name of Column 1
|Name of Column 2

|Cell in column 1, row 1
|Cell in column 2, row 1

|Cell in column 1, row 2
|Cell in column 2, row 2
|===
Result: Rendered table when the header value is assigned to the options attribute
Name of Column 1 Name of Column 2

Cell in column 1, row 1

Cell in column 2, row 1

Cell in column 1, row 2

Cell in column 2, row 2

Alternately, you can define the header row based on how you layout the table. Asciidoctor use the following conventions to determine when the first row should become the header row:

  1. The first line of content inside the table block delimiters is not empty.

  2. The second line of content inside the table block delimiters is empty.

  3. The options attribute has not been specified in the block attributes (prior to 1.5.5).

As seen in the result of the example below, if all of these rules hold, then the first row of the table is treated as a header.

Table that has an implicit header row
|===
|Name of Column 1 |Name of Column 2

|Cell in column 1, row 1
|Cell in column 2, row 1

|Cell in column 1, row 2
|Cell in column 2, row 2
|===
Result: Rendered table when the header row was assigned implicitly
Name of Column 1 Name of Column 2

Cell in column 1, row 1

Cell in column 2, row 1

Cell in column 1, row 2

Cell in column 2, row 2

If you want to suppress this implicit behavior of promoting the first row to a header row, set the option value noheader (or add the %noheader directive to the table style).

Notice that when the implicit method of assigning the header row is used, it’s not necessary to set the cols attribute. That’s because the number of columns are determined by the number of cells in the first line if the cols attribute is absent.

We’re considering using a similar convention for enabling the footer in the future. Thus, if you rely on this convention to enable the header row, it’s advised that you not put all the cells in the last row on the same line unless you intend on making it the footer row.

The last row of a table can be styled as a footer by adding the footer keyword to the options attribute.

[options="footer"]
|===
|Name of Column 1 |Name of Column 2

|Cell in column 1, row 1
|Cell in column 2, row 1

|Cell in column 1, row 2
|Cell in column 2, row 2

|Footer in column 1, row 3
|Footer in column 2, row 3
|===
Result: Table rendered with a footer
Name of Column 1 Name of Column 2

Cell in column 1, row 1

Cell in column 2, row 1

Cell in column 1, row 2

Cell in column 2, row 2

Footer in column 1, row 3

Footer in column 2, row 3