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 unit
  • style="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:

  1. The parser processes all child nodes into a temporary stack array
  2. It assigns this stack to ret.columns
  3. It removes the temporary stack property from the return object
  4. Each child's width configuration is extracted from data-pdfmake attributes 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-pdfmake attributes (e.g., {"width":"*"}), inline styles (e.g., width:auto), or leave unspecified for default sizing
  • The conversion happens in index.js during the parseElement recursive traversal
  • Columns function correctly when nested inside tables, stacks, or other containers
  • Supply a window object 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →