Skip to content

fix: PDF image spacing, page top margin, and soft line breaks#59

Merged
rogerdigital merged 1 commit into
mainfrom
fix/pdf-image-layout-margins
Jun 24, 2026
Merged

fix: PDF image spacing, page top margin, and soft line breaks#59
rogerdigital merged 1 commit into
mainfrom
fix/pdf-image-layout-margins

Conversation

@rogerdigital

Copy link
Copy Markdown
Owner

Problem

Exported PDFs had three layout defects, all stemming from how CSS interacts with Obsidian's rendered DOM:

  1. Images stuck to page top (no top margin) on continuation pages
  2. Excessive vertical spacing between consecutive images
  3. Soft line breaks collapsed — adjacent text lines (no blank line in source) merged into one line

Root Causes & Fixes

Page top margin

Own physical margins via CSS @page with preferCSSPageSize: true, and zero the printToPDF margins. When both @page margin and printToPDF margins are non-zero, Chromium uses the printToPDF margins for the page box — and those drop the top margin to 0 on continuation pages. Verified via CDP Page.printToPDF (same path as Electron) + PyMuPDF coordinate measurement: with printToPDF margins at 0 and @page margin: 52px 60px, continuation-page top margin is correctly ~39pt.

Image spacing

Obsidian merges consecutive image embeds (and adjacent text) into a single <p> separated by <br>. Broadened the media-paragraph spacing collapse from :has(> img:only-child) to descendant :has(img) so multi-media paragraphs tighten. Media gap is controlled by line-height: 1 (shrinks the <br> line-box) plus per-media margin.

Soft line breaks

A prior rule p:has(img) > br { display:none } — meant to tighten media spacing — collapsed all <br> in media paragraphs, silently merging legitimate soft line breaks when text and media shared one <p>. Removed the rule entirely. Added a regression test forbidding display:none on <br> anywhere in the PDF stylesheet.

Verification

  • 159 tests pass
  • PyMuPDF coordinate measurement confirms all soft-break paragraphs render on separate lines
  • Other formats audited: html-document, docx, markdown-bundle all handle soft breaks correctly (no change needed)

Three interrelated PDF layout fixes:

- Page top margin: own physical margins via CSS @page with
  preferCSSPageSize, and zero printToPDF margins. Non-zero printToPDF
  margins make Chromium use them for the page box, which drops the top
  margin to 0 on continuation pages (images stuck to page top).

- Image spacing: Obsidian merges consecutive image embeds (and adjacent
  text) into one <p> separated by <br>. Broaden the media-paragraph
  spacing collapse from :has(> img:only-child) to descendant :has(img)
  so multi-media paragraphs tighten. Control media gap via line-height:1
  plus per-media margin.

- Soft line breaks: do NOT hide <br> in media paragraphs. A prior rule
  (p:has(img) > br { display:none}) collapsed all <br>, which silently
  merged soft line breaks when text and media shared one <p>. Add a
  regression test forbidding display:none on <br> anywhere in the PDF
  stylesheet.
@rogerdigital rogerdigital merged commit 187ceef into main Jun 24, 2026
1 check passed
@rogerdigital rogerdigital deleted the fix/pdf-image-layout-margins branch June 24, 2026 14:02
@rogerdigital rogerdigital mentioned this pull request Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant