How to Resolve Styling Conflicts in html-to-pdfmake
You resolve styling conflicts in html-to-pdfmake by leveraging its last-wins merging hierarchy—where default tag styles apply first, inline CSS overrides them, and constructor options like ignoreStyles, removeTagClasses, and defaultStyles take final precedence.
Converting HTML to PDFMake definitions often produces unexpected visual results when multiple style sources collide. The html-to-pdfmake library merges built-in defaults, inline CSS, and user-provided options in a specific order defined in index.js. Understanding this resolution pipeline allows you to suppress unwanted properties and ensure your PDF output matches your design specifications exactly.
Understanding the Style Merging Hierarchy
The library processes three distinct style sources during conversion, as implemented in the constructor and parsing logic of index.js:
- Built-in default styles – Defined in lines 58-78, these map HTML tags to PDFMake properties (e.g.,
<b>maps to{bold: true}). - Inline CSS attributes – Parsed by the
parseStylefunction around line 768, converting attributes likestyle="margin:10px"into PDFMake-compatible keys. - User-provided override options – Constructor parameters including
defaultStyles,ignoreStyles, andremoveTagClasses(stored in lines 49-51).
When the same property exists in multiple sources, html-to-pdfmake follows a last-wins rule. The default style applies first, inline CSS overrides it, and option overrides take final precedence. The ignoreStyles array removes properties entirely before merging, preventing them from appearing regardless of their source.
Configuration Options for Conflict Resolution
Several constructor options control how styles merge:
ignoreStyles– An array of CSS properties to exclude from parsing (e.g.,['margin', 'padding']).removeTagClasses– Boolean flag (line 49) that disables automatichtml-TAGclass generation on every node.defaultStyles– Object that replaces or extends the built-in mappings for specific tags.tableAutoSize– Boolean (line 45) that prioritizes explicit width/height values on table cells over calculated defaults.showHidden– Boolean (line 48) that includes elements withdisplay:nonein the output.removeExtraBlanks– Boolean (line 48) that aggressively trims whitespace whenwhite-space:preconflicts with PDFMake defaults.
Common Styling Conflicts and Solutions
Inline Margins vs. Default Tag Margins
Paragraphs and headers carry default margins in defaultStyles, but inline style="margin:20px" declarations may produce unexpected spacing. Since the default applies first and inline styles override selectively, you might inherit unwanted margin components.
Resolution: Use ignoreStyles: ['margin'] to strip all CSS margin declarations, forcing reliance on defaultStyles definitions. Alternatively, override the baseline entirely by providing defaultStyles.p.margin in your options.
Table Border Duplication
Table headers (<th>) receive default borders via defaultStyles.th, while inline style="border:1px solid red" attempts to modify them. Without intervention, these properties may compound rather than replace.
Resolution: Supply an empty string or null for the specific property in defaultStyles.th.border to remove the baseline before the inline style applies.
Text Decoration Collisions
Both default conversion (e.g., <u> → decoration: 'underline') and inline text-decoration properties populate the decoration array. Duplicate values create unwanted visual artifacts.
Resolution: The applyStyle function (lines 84-92 in index.js) automatically deduplicates decorations. Ensure you do not manually inject duplicate values through custom styles.
Unwanted html-TAG Classes
By default, every element receives a class like html-p or html-div, which can conflict with downstream CSS processing of the generated JSON.
Resolution: Set removeTagClasses: true in the constructor options to suppress automatic class generation (as stored in line 49).
Table Cell Dimension Conflicts
Explicit widths set via style="width:250px" may be ignored if defaultStyles.th or defaultStyles.td specify different dimensions.
Resolution: Enable tableAutoSize: true to prioritize explicit CSS dimensions over internal calculations.
Whitespace Handling Conflicts
Inline white-space:pre preserves spacing that PDFMake's default parser may trim, resulting in layout shifts.
Resolution: Activate removeExtraBlanks: true to force aggressive whitespace normalization, though this incurs a performance cost.
The Style Resolution Algorithm
The core merging logic resides in the applyStyle function around line 655 of index.js. The algorithm executes these steps in sequence:
- Collect CSS classes – Gathers classes from the element, including the auto-generated
html-TAGclass unlessremoveTagClassesis enabled. - Apply default styles – Retrieves tag-specific defaults from the internal mapping.
- Parse inline CSS – Processes the
styleattribute viaparseStyle, converting CSS to PDFMake properties. - Filter ignored properties – Skips any keys listed in the
ignoreStylesarray. - Deduplicate decorations – Merges underline and line-through values into a unique array.
- Normalize margins – Converts CSS margin shorthand into PDFMake's left-top-right-bottom object format.
- Return merged object – Produces the final
retobject containing resolved styles for the PDFMake document definition.
Practical Code Examples
The following examples demonstrate resolving specific conflicts using the options discussed.
Suppressing Default Margins and Tag Classes
const opts = {
window, // Required in Node.js environments
removeTagClasses: true, // Disable html-p, html-div classes
ignoreStyles: ['margin'] // Ignore CSS margins, use defaults only
};
const html = '<p style="margin:20px; color:red">Hello</p>';
const pdfDef = htmlToPdfmake(html, opts);
// Result: The node contains only color:'#ff0000'; margin comes from defaultStyles.p
Overriding Default Table Header Styles
const opts = {
window,
defaultStyles: {
th: {
fillColor: '' // Remove default gray background
}
}
};
const pdfDef = htmlToPdfmake('<table><tr><th>Header</th></tr></table>', opts);
// Result: Header cell appears without the default fillColor:'#EEEEEE'
Preserving Hidden Elements and Explicit Widths
const opts = {
window,
showHidden: true, // Include display:none elements
tableAutoSize: true // Respect explicit width/height values
};
const html = `
<div style="display:none">Secret Content</div>
<table style="width:100%">
<tr>
<td style="width:250px">Fixed Width</td>
<td>Auto Width</td>
</tr>
</table>
`;
const pdfDef = htmlToPdfmake(html, opts);
// Result: Secret Content appears in PDF; first cell respects 250px width
Summary
- html-to-pdfmake resolves styling conflicts using a last-wins hierarchy: default styles apply first, inline CSS overrides them, and constructor options take final precedence.
- Use
ignoreStylesto prevent specific CSS properties from being parsed, andremoveTagClassesto eliminate automatichtml-TAGclasses. - Override built-in defaults by providing custom objects to the
defaultStylesoption. - Enable
tableAutoSizeto ensure explicit table dimensions override internal calculations, andshowHiddento retain elements withdisplay:none. - The merging logic is centralized in the
applyStylefunction (around line 655) ofindex.js, with default style definitions located in lines 58-78.
Frequently Asked Questions
Why does my inline style get ignored when converting HTML to PDFMake?
Your inline style likely conflicts with a hardcoded default in defaultStyles or is being filtered by the ignoreStyles array. According to the source code in index.js (lines 58-78), tags like <p> and <th> carry predefined margins and borders that override or merge with your CSS. Check that you have not included the property in ignoreStyles, and verify that tableAutoSize is enabled if working with table dimensions.
How do I remove the default gray background from table headers?
The library assigns fillColor:'#EEEEEE' to <th> elements by default. To remove this, pass a defaultStyles object in your constructor options that sets th.fillColor to an empty string or null. This empty value clears the default before inline styles are processed, allowing complete control over the header appearance.
Can I prevent html-to-pdfmake from adding html-p classes to every element?
Yes. Set removeTagClasses: true in your options object. By default, the constructor (line 49 of index.js) generates classes like html-p and html-div for every node to aid styling, but this flag disables that behavior entirely, preventing conflicts with your own class-based logic.
What is the performance impact of using removeExtraBlanks to fix whitespace issues?
The removeExtraBlanks option (line 48) forces aggressive whitespace cleanup across the entire document, which requires additional string processing and node traversal. While effective for resolving conflicts between white-space:pre and PDFMake's default trimming, you should only enable it when necessary for layout accuracy, as it increases conversion time for large documents.
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 →