How to Use Columns in PDFMake with html-to-pdfmake
Use the data-pdfmake-type="columns" attribute on a <div> element to convert its children into a PDFMake columns array, with optional width control via data-pdfmake attributes or inline styles.
The aymkdn/html-to-pdfmake library transforms standard HTML into PDFMake document definitions. When you need side-by-side layouts in your generated PDFs, the library provides a declarative way to use columns in PDFMake with html-to-pdfmake through data attributes rather than writing complex JavaScript object structures.
Understanding the Columns Feature
PDFMake supports a columns layout that places elements horizontally next to each other. In html-to-pdfmake, you trigger this behavior by adding a specific data attribute to a container div. When the parser encounters a <div> with data-pdfmake-type="columns", it treats each direct child element as a separate column in the resulting PDF.
According to the source code in index.js, the parser checks for this attribute inside the default branch of the switch(nodeName) block during the recursive DOM traversal performed by parseElement.
Implementing Columns with data-pdfmake-type
Basic Syntax
Wrap your column content in a parent div with the columns attribute:
<div data-pdfmake-type="columns">
<div>First column content</div>
<div>Second column content</div>
</div>
The library converts this into a PDFMake structure where each child becomes an entry in the columns array. During parsing, the library builds a temporary stack containing the processed children, then moves this stack to ret.columns and deletes the temporary stack property.
Controlling Column Widths
You can declare column widths using three methods:
data-pdfmake='{"width":"*"}'– Explicitly sets width to star (remaining space), auto, or a fixed unitstyle="width:auto"– Extracts the style value and normalizes it into the width property- No declaration – Inherits default PDFMake auto-sizing behavior
The parser extracts these values during the conversion process and applies them to the resulting column definitions.
Code Examples
Two Equal-Width Columns
Create a balanced two-column layout using star widths:
<div data-pdfmake-type="columns">
<div data-pdfmake='{"width":"*"}'>
<p>Left column content with flexible width</p>
</div>
<div data-pdfmake='{"width":"*"}'>
<p>Right column content with flexible width</p>
</div>
</div>
Resulting PDFMake definition:
{
"columns": [
{ "width": "*", "stack": [{ "text": "Left column content with flexible width" }] },
{ "width": "*", "stack": [{ "text": "Right column content with flexible width" }] }
]
}
Mixed Width Configurations
Combine fixed, auto, and default sizing in a single row:
<div data-pdfmake-type="columns">
<div data-pdfmake='{"width":"150"}'>Fixed 150 points</div>
<div style="width:auto">Auto-sized based on content</div>
<div>Default auto behavior</div>
</div>
This generates columns with specific measurements while letting PDFMake handle the remaining space automatically.
Nesting Columns Inside Tables
Columns work within any PDFMake container, including table cells:
<table>
<tr>
<td>
<div data-pdfmake-type="columns">
<div data-pdfmake='{"width":"*"}'>Column A</div>
<div data-pdfmake='{"width":"*"}'>Column B</div>
</div>
</td>
</tr>
</table>
The resulting structure places a columns array inside the table body definition, allowing complex grid layouts within tabular data.
Node.js and Browser Implementation
Node.js with jsdom:
const htmlToPdfMake = require('html-to-pdfmake');
const { JSDOM } = require('jsdom');
const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>');
const html = `
<div data-pdfmake-type="columns">
<div data-pdfmake='{"width":"*"}'>Server-side column 1</div>
<div data-pdfmake='{"width":"*"}'>Server-side column 2</div>
</div>
`;
const docDefinition = htmlToPdfMake(html, { window: dom.window });
console.log(JSON.stringify(docDefinition, null, 2));
Browser environment:
const docDefinition = htmlToPdfMake(
document.getElementById('source').innerHTML,
{ window: window }
);
pdfMake.createPdf(docDefinition).open();
The window option supplies the DOM environment required for parsing. In Node.js, libraries like jsdom provide this interface.
Technical Implementation Details
The column conversion logic resides in index.js within the parseElement function. Specifically, in the default case of the node name switch block (lines 581-588), the code checks element.dataset.pdfmakeType === "columns".
When this condition matches:
- The parser processes all child nodes into a temporary
stackarray - It assigns this stack to
ret.columns - It removes the temporary
stackproperty from the return object - Each child's width configuration is extracted from
data-pdfmakeattributes or inline styles
This approach allows the library to support complex nested structures where columns contain tables, images, or additional nested columns.
Validation and Testing
The unit test suite in test/unit.js (lines 16-31) validates the column functionality. The test verifies that HTML containing the columns attribute generates a proper columns array with three items and correctly parses various width specifications, including JSON in data attributes and CSS-style width declarations.
The test confirms that width values are properly extracted whether specified via data-pdfmake='{"width":"*"}' or style="width:auto", ensuring consistent behavior across different markup styles.
Summary
- Add
data-pdfmake-type="columns"to a<div>to enable PDFMake column layouts - Each direct child becomes a separate column in the generated PDF
- Control widths using
data-pdfmakeattributes (e.g.,{"width":"*"}), inline styles (e.g.,width:auto), or leave unspecified for default sizing - The conversion happens in
index.jsduring theparseElementrecursive traversal - Columns function correctly when nested inside tables, stacks, or other containers
- Supply a
windowobject when running in Node.js environments
Frequently Asked Questions
What is the exact HTML attribute needed to create columns?
Add data-pdfmake-type="columns" to a parent <div> element. When the parser processes this div in index.js, it recognizes the special type and converts the element's children into a PDFMake columns array instead of a vertical stack.
How do I set column widths using html-to-pdfmake?
Use one of three methods: apply data-pdfmake='{"width":"*"}' for star sizing, data-pdfmake='{"width":"auto"}' for automatic sizing, or style="width:150" for fixed units. The parser extracts these values during the conversion process defined in the default branch of the element handler.
Can columns be nested inside tables or other elements?
Yes, columns work within any valid PDFMake container. You can place a data-pdfmake-type="columns" div inside table cells (<td>), list items, or other structural elements. The library recursively processes the DOM tree, so nested columns generate properly structured PDFMake definitions at any depth.
Does this work in Node.js environments?
Yes, but you must provide a DOM environment since the library uses DOMParser internally. Pass a window object from jsdom or similar libraries in the options parameter: htmlToPdfMake(html, { window: dom.window }). Without this, the parser cannot parse the HTML string into a traversable DOM tree.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →