DOMParser.stuffStyleIntoHead: when doc.body.innerHTML silently drops your CSS
TLDR
Parsing HTML strings usingDOMParser.parseFromString() automatically relocates <style> tags into the generated document's <head> element per the HTML parsing specification. Serializing output by reading doc.body.innerHTML silently discards all prepended <style> blocks, stripping extracted font rules. To preserve styles, query doc.head.querySelectorAll('style') and concatenate the outer HTML of all style tags into your final document wrapper.
| Serialization Target | Contains Body Content | Contains <style> Blocks | Extracted Font Fidelity |
|---|---|---|---|
doc.body.innerHTML Only | Yes | No (Relocated to <head>) | Fails (Styles stripped completely) |
doc.head Styles + doc.body | Yes | Yes (Re-assembled explicitly) | 100% (Full font styling preserved) |
Technical defect analysis
Our PDF export pipeline generates dynamic CSS classes (.f0, .f1) and prepends a <style> block to extracted HTML fragments:
<!-- INPUT HTML STRING -->
<style>
.pdf-doc .f0 { font-size: 12pt; font-family: "Times New Roman", serif; }
.pdf-doc .f1 { font-size: 10pt; font-family: "Arial", sans-serif; }
</style>
<article class="pdf-doc">
<p class="f0">Extracted PDF Text Content</p>
</article>
When processing images or DOM mutations using DOMParser:
// DEFECTIVE IMPLEMENTATION: Reading body.innerHTML drops head styles!
const parser = new DOMParser();
const doc = parser.parseFromString(rawHtmlString, 'text/html');
// ... perform DOM mutations on doc ...
const exportedHtml = doc.body.innerHTML; // SILENT LOSS: <style> tags were moved to doc.head!
Because DOMParser moves <style> tags into doc.head, doc.body.innerHTML returns only the <article> element, stripping all CSS font declarations from exported documents.
Remediation: head style extraction & re-assembly
Extract all <style> elements from doc.head before serializing doc.body.innerHTML:
export function serializeParsedDocument(doc, documentTitle = 'Extracted Document') {
// 1. Extract all style tags relocated to <head> by DOMParser
const styleElements = doc.head ? Array.from(doc.head.querySelectorAll('style')) : [];
const extractedCss = styleElements.map(style => style.outerHTML).join('\n');
// 2. Extract body HTML const bodyHtml = doc.body ? doc.body.innerHTML : '';
// 3. Assemble complete HTML5 document structure return <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"/> <title>${escapeHtml(documentTitle)}</title> ${extractedCss} </head> <body> ${bodyHtml} </body> </html>; }
Rule of thumb: Extract<style>tags fromdoc.headwhenever serializing HTML strings parsed byDOMParser.