Documentation Index Fetch the complete documentation index at: https://mintlify.com/bpampuch/pdfmake/llms.txt
Use this file to discover all available pages before exploring further.
Tables are one of the most powerful layout tools in pdfmake. A table node wraps a table object that contains at minimum a body array — a two-dimensional array where each inner array is a row, and each element within that row is a cell. Cells can contain any content node pdfmake supports, including nested tables.
Basic table structure
const docDefinition = {
content: [
{
table: {
body: [
[ 'Column 1' , 'Column 2' , 'Column 3' ],
[ 'One value goes here' , 'Another one here' , 'OK?' ]
]
}
}
]
};
Cells can hold rich content — stacks, lists, nested tables, or inline styled text:
{
table : {
body : [
[ 'Column 1' , 'Column 2' , 'Column 3' ],
[
{
stack: [
"Let's try an unordered list" ,
{ ul: [ 'item 1' , 'item 2' ] }
]
},
[
'or a nested table' ,
{
table: {
body: [
[ 'Col1' , 'Col2' , 'Col3' ],
[ '1' , '2' , '3' ],
[ '1' , '2' , '3' ]
]
}
}
],
{
text: [
'Inlines can be ' ,
{ text: 'styled \n ' , italics: true },
{ text: 'easily as everywhere else' , fontSize: 10 }
]
}
]
]
}
}
Column widths
The widths property accepts an array with one entry per column. Omitting widths distributes space evenly.
fixed-and-star
auto-and-star
no-wrap-auto
{
table : {
widths : [ 100 , '*' , 200 , '*' ],
body : [
[ 'width=100' , 'star-sized' , 'width=200' , 'star-sized' ],
[ 'fixed-width cells have exactly the specified width' ,
{ text: 'nothing interesting here' , italics: true , color: 'gray' },
{ text: 'nothing interesting here' , italics: true , color: 'gray' },
{ text: 'nothing interesting here' , italics: true , color: 'gray' }]
]
}
}
Width value Behaviour 100 (number)Fixed width in points '*'Star-sized — shares remaining space equally with other stars 'auto'Shrinks to fit content '50%'Percentage of the available width
Row heights
heights controls the minimum height of each row. It accepts a number, an array, or a function:
{
table : {
heights : [ 20 , 50 , 70 ],
body : [
[ 'row 1 with height 20' , 'column B' ],
[ 'row 2 with height 50' , 'column B' ],
[ 'row 3 with height 70' , 'column B' ]
]
}
}
Use a function for dynamic heights:
{
table : {
heights : function ( row ) {
return ( row + 1 ) * 25 ;
},
body : [
[ 'row 1' , 'column B' ],
[ 'row 2' , 'column B' ],
[ 'row 3' , 'column B' ]
]
}
}
Column and row spans
Set colSpan and rowSpan on a cell object. Placeholder empty strings '' must fill the skipped slots so every row has the correct number of cells.
{
table : {
widths : [ 200 , 'auto' , 'auto' ],
headerRows : 2 ,
body : [
[
{ text: 'Header with Colspan = 2' , style: 'tableHeader' , colSpan: 2 , alignment: 'center' },
{},
{ text: 'Header 3' , style: 'tableHeader' , alignment: 'center' }
],
[
{ text: 'Header 1' , style: 'tableHeader' , alignment: 'center' },
{ text: 'Header 2' , style: 'tableHeader' , alignment: 'center' },
{ text: 'Header 3' , style: 'tableHeader' , alignment: 'center' }
],
[ 'Sample value 1' , 'Sample value 2' , 'Sample value 3' ],
[
{ rowSpan: 3 , text: 'rowSpan set to 3 \n Lorem ipsum ...' },
'Sample value 2' , 'Sample value 3'
],
[ '' , 'Sample value 2' , 'Sample value 3' ],
[ 'Sample value 1' , 'Sample value 2' , 'Sample value 3' ],
[
'Sample value 1' ,
{ colSpan: 2 , rowSpan: 2 , text: 'Both rowSpan and colSpan \n can be defined at the same time' },
''
],
[ 'Sample value 1' , '' , '' ]
]
}
}
When using colSpan, pad the skipped cells with empty objects {} rather than empty strings if the skipped cells need a specific border or fill color.
headerRows marks the first N rows as headers. pdfmake automatically repeats them at the top of each new page when the table spans multiple pages.
{
table : {
headerRows : 1 ,
body : [
[
{ text: 'Header 1' , style: 'tableHeader' },
{ text: 'Header 2' , style: 'tableHeader' },
{ text: 'Header 3' , style: 'tableHeader' }
],
[ 'Sample value 1' , 'Sample value 2' , 'Sample value 3' ],
// ... more rows
]
}
}
Use keepWithHeaderRows to prevent a page break between the header and the first N data rows:
{
table : {
headerRows : 1 ,
keepWithHeaderRows : 1 , // keep at least one data row with the header
body : [ /* ... */ ]
}
}
Use dontBreakRows: true to prevent any row from being split across pages:
{
table : {
dontBreakRows : true ,
body : [ /* ... */ ]
}
}
Built-in table layouts
pdfmake ships with three predefined layouts you can reference by name using the layout property on the wrapper node (not inside table):
noBorders
headerLineOnly
lightHorizontalLines
{
table : { headerRows : 1 , body : [ /* ... */ ] },
layout : 'noBorders'
}
Custom table layouts
Pass a layout object directly to override every visual attribute. All functions receive the row index and the table node:
{
table : {
headerRows : 1 ,
body : [ /* ... */ ]
},
layout : {
hLineWidth : function ( i , node ) {
return ( i === 0 || i === node . table . body . length ) ? 2 : 1 ;
},
vLineWidth : function ( i , node ) {
return ( i === 0 || i === node . table . widths . length ) ? 2 : 1 ;
},
hLineColor : function ( i , node ) {
return ( i === 0 || i === node . table . body . length ) ? 'black' : 'gray' ;
},
vLineColor : function ( i , node ) {
return ( i === 0 || i === node . table . widths . length ) ? 'black' : 'gray' ;
}
// paddingLeft: function(i, node) { return 4; },
// paddingRight: function(i, node) { return 4; },
// paddingTop: function(i, node) { return 2; },
// paddingBottom: function(i, node) { return 2; },
// fillColor: function (rowIndex, node, columnIndex) { return null; }
}
}
Dashed borders
hLineStyle and vLineStyle return a dash descriptor:
layout : {
hLineStyle : function ( i , node ) {
if ( i === 0 || i === node . table . body . length ) { return null ; }
return { dash: { length: 10 , space: 4 } };
},
vLineStyle : function ( i , node ) {
if ( i === 0 || i === node . table . widths . length ) { return null ; }
return { dash: { length: 4 } };
}
}
Zebra stripes
{
table : { body : [ /* ... */ ] },
layout : {
fillColor : function ( rowIndex , node , columnIndex ) {
return ( rowIndex % 2 === 0 ) ? '#CCCCCC' : null ;
}
}
}
Fill color with opacity gradient
{
table : { body : [ /* 8 rows */ ] },
layout : {
fillColor : 'blue' ,
fillOpacity : function ( rowIndex , node , columnIndex ) {
return ( rowIndex / 8 + columnIndex / 3 );
}
}
}
Cell-level properties
Individual cells accept style properties in addition to layout-controlled ones:
[
{ text: 'Sample value 1' , fillColor: 'blue' , fillOpacity: 0.15 },
{ text: 'Sample value 2' , fillColor: 'blue' , fillOpacity: 0.60 },
{ text: 'Sample value 3' , fillColor: 'blue' , fillOpacity: 0.85 }
]
Per-cell borders
border accepts a four-element boolean array — [left, top, right, bottom]:
{
table : {
body : [
[
{ border: [ false , true , false , false ], fillColor: '#eeeeee' , text: 'top border only' },
{ border: [ false , false , false , false ], fillColor: '#dddddd' , text: 'no borders' },
{ border: [ true , true , true , true ], fillColor: '#eeeeee' , text: 'all borders' }
]
]
},
layout : { defaultBorder : false }
}
layout.defaultBorder controls whether cells without an explicit border property show borders (true by default). Setting it to false lets you opt-in per cell.
Per-cell border colors
borderColor accepts a four-element color array — [left, top, right, bottom]:
{
text : 'Header with Colspan = 3' ,
colSpan : 3 ,
borderColor : [ '#ff00ff' , '#00ffff' , '#ff00ff' , '#00ffff' ],
alignment : 'center'
}
Overlay patterns on cells
Cells support an additional overlayPattern and overlayOpacity to composite a pattern on top of a solid fill:
{
text : 'Sample value 1' ,
fillColor : 'blue' ,
fillOpacity : 0.15 ,
overlayPattern : [ 'stripe45d' , 'gray' ],
overlayOpacity : 0.15
}
Named table layouts
Register layouts by name using pdfmake.addTableLayouts() before calling createPdf(). Once registered, any table in any document can reference them by name using the layout property:
const docDefinition = { /* ... */ };
pdfmake . addTableLayouts ({
exampleLayout: {
hLineWidth : function ( i , node ) { return 1 ; },
vLineWidth : function ( i , node ) { return 0 ; },
hLineColor : function ( i , node ) { return '#aaa' ; },
paddingLeft : function ( i , node ) { return 8 ; },
paddingRight : function ( i , node ) { return 8 ; }
}
});
pdfmake . createPdf ( docDefinition );
Then reference the layout by name in any table wrapper node:
{
table : { body : [ /* ... */ ] },
layout : 'exampleLayout'
}