May 24, 2026 · Developer Guide

Styling PDFs with Markdown: Layouts and CSS for E-Signatures (2026)

How to use markdown and custom CSS classes to generate beautiful, professional PDFs via API. Managing page breaks, margins, and headers.

Michael Beckett
Michael Beckett

Founder, Signbee

TL;DR

Generating professional PDFs from Markdown requires a mix of markup structure, custom CSS, and API options. By injecting custom CSS into the Signbee /v1/generate API, you can control document styling, handle page-break rules (like page-break-inside: avoid), and configure margins, headers, and footers. Read on to see payload examples, print-specific CSS patterns, and a full integration script.

Why Markdown alone isn't enough for PDFs

Markdown is the perfect format for writing digital agreements, NDAs, and proposals. It is human-readable, version-control friendly, and lightweight. However, markdown was built for the continuous scroll of web browsers. It has no concept of page dimensions, margin limits, headers, footers, or page-break boundaries.

When you convert raw markdown to a PDF using a typical API, you often end up with awkward results: headings stranded at the bottom of a page, text overlapping with headers, or a signature block split across a page crease. To turn markdown into a client-ready contract, you need to combine the simplicity of markdown with custom CSS layout rules and precise API controls.

The Signbee generate API payload

The Signbee /v1/generate endpoint allows you to send markdown, inject custom CSS, and set page layout options in a single API call. This separation of concerns lets your application logic focus on generating content while keeping style and document rules clean.

Here is what a typical payload looks like when configuring page sizes, custom margins, and headers/footers with dynamic page numbering:

Signbee /v1/generate API Request Payload
{
  "markdown": "# Service Agreement\n\nThis agreement is made between...",
  "css": "body { font-family: 'Helvetica', sans-serif; color: #111; }\nh1 { font-size: 24pt; }\n.signature-block { page-break-inside: avoid; }",
  "options": {
    "format": "Letter",
    "margin": {
      "top": "20mm",
      "bottom": "20mm",
      "left": "15mm",
      "right": "15mm"
    },
    "displayHeaderFooter": true,
    "headerTemplate": "<div style='font-size: 8px; color: #888; width: 100%; text-align: right; padding-right: 15mm;'>CONFIDENTIAL</div>",
    "footerTemplate": "<div style='font-size: 8px; color: #888; width: 100%; text-align: center;'>Page <span class='pageNumber'></span> of <span class='totalPages'></span></div>"
  }
}

Mastering CSS page breaks in PDFs

Controlling how elements split across pages is critical for legal agreements. You don't want your sign-off details floating alone on page five, nor do you want a table row cut in half. The PDF generation engine supports standard CSS paged media rules:

1. Forced Page Breaks (page-break-before: always / break-before: page): Use this to begin a new major section on a clean page. You can insert an HTML element directly into your markdown to trigger this:

Markdown snippet for forcing a page break
<div class="page-break"></div>

2. Avoiding Inside Breaks (page-break-inside: avoid / break-inside: avoid): Apply this to groups of elements that must stay together, such as signature fields, callout boxes, or small tables.

3. Preventing Headings Orphans (page-break-after: avoid / break-after: avoid): Prevent headings from sitting alone at the bottom of a page by ensuring they always stay attached to the paragraph that follows.

Styling tables, lists, and images

Because markdown compiles into standard HTML tags, you can target them directly using your custom CSS block. Use this table as a reference for print-specific rules:

ElementCSS PropertyRecommended Value
Table Rows (tr)page-break-insideavoid
Table Header (thead)displaytable-header-group
Tables (table)border-collapsecollapse
Signature Box (.sig)page-break-insideavoid
Images (img)max-width, height100%, auto

A complete generation example (Node.js)

Here is a complete integration script. It defines a document with a forced page break using an inline HTML spacer, customizes CSS fonts and margins, makes a POST request to Signbee, and saves the generated PDF buffer directly to the local filesystem.

Node.js — Generate styled PDF via Signbee API
import fs from 'fs/promises';

async function generateStyledPdf() {
  const payload = {
    markdown: `# Master Services Agreement
    
This Agreement is entered into as of May 24, 2026.

## 1. Services and Deliverables
The Consultant will provide styling engine services as detailed in Exhibit A.

<div class="page-break"></div>

## 2. Payment Terms
Invoices are payable within 30 days of receipt.

<div class="signature-block">
  <h3>Signatures</h3>
  <table style="width: 100%; border: none;">
    <tr>
      <td style="width: 50%; border: none; padding: 20px 0;">
        ___________________________<br/>
        <strong>Client Signature</strong>
      </td>
      <td style="width: 50%; border: none; padding: 20px 0;">
        ___________________________<br/>
        <strong>Consultant Signature</strong>
      </td>
    </tr>
  </table>
</div>`,
    css: `
      body {
        font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
        color: #333;
        font-size: 11pt;
        line-height: 1.6;
      }
      h1 { font-size: 22pt; margin-bottom: 20px; color: #111; }
      h2 { font-size: 16pt; margin-top: 30px; color: #222; }
      h3 { font-size: 13pt; margin-top: 20px; color: #333; }
      .page-break { page-break-before: always; }
      .signature-block { page-break-inside: avoid; margin-top: 50px; }
    `,
    options: {
      format: "A4",
      margin: {
        top: "25mm",
        bottom: "25mm",
        left: "20mm",
        right: "20mm"
      },
      displayHeaderFooter: true,
      headerTemplate: `<div style="font-size: 9px; color: #888; width: 100%; text-align: right; padding-right: 20mm; font-family: sans-serif;">Confidential - MSA</div>`,
      footerTemplate: `<div style="font-size: 9px; color: #888; width: 100%; text-align: center; font-family: sans-serif;">Page <span class="pageNumber"></span> of <span class="totalPages"></span></div>`
    }
  };

  const response = await fetch("https://signb.ee/api/v1/generate", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": "Bearer YOUR_API_KEY"
    },
    body: JSON.stringify(payload)
  });

  if (!response.ok) {
    const errorText = await response.text();
    throw new Error(`Failed to generate PDF: ${response.status} ${errorText}`);
  }

  // API returns the raw PDF stream
  const arrayBuffer = await response.arrayBuffer();
  await fs.writeFile("agreement.pdf", Buffer.from(arrayBuffer));
  console.log("agreement.pdf generated successfully!");
}

generateStyledPdf().catch(console.error);

Advanced Typography: Custom Web Fonts & Base64 Embedding

One of the most frequent styling hurdles developers face is loading custom brand typography (such as Inter, Roboto, or bespoke corporate typefaces) in generated PDFs. In headless browser rendering environments, loading external web fonts via standard @import url(...) or <link rel="stylesheet"> tags introduces network latency and intermittent render timeouts—often leading to Flash of Unstyled Text (FOUT) or blank glyphs.

The recommended pattern for bulletproof PDF typography is inlining base64-encoded WOFF2 or TTF font files directly into your custom CSS string:

Embedding base64 font in custom CSS payload
@font-face {
  font-family: 'Inter';
  src: url('data:font/woff2;base64,d09GMgABAAAAAA...') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: block;
}

body {
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 10.5pt;
  line-height: 1.55;
  color: #1a1a1a;
}

Cover Page Styling & Dynamic Watermarks

When generating formal enterprise proposals or multi-page Master Service Agreements, you often want a prominent cover page that omits the running header and footer, followed by subsequent pages that display confidentiality notices and running page counters.

You can achieve this layout cleanly using CSS paged media rules and the @page:first pseudo-class selector:

Cover Page & Watermark Patterns:

  • Suppress Header/Footer on Cover: While the global header template applies to all pages, you can set the cover page container to full viewport height (min-height: 100vh) and style subsequent content blocks with page-break-before: always.
  • Diagonal "DRAFT" Watermark: Apply a fixed-position background watermark using CSS: .watermark { position: fixed; top: 40%; left: 15%; transform: rotate(-45deg); font-size: 72pt; color: rgba(200, 200, 200, 0.15); pointer-events: none; z-index: -1; }. Because it is positioned fixed within paged media, it stamps across every page automatically.
  • Bleed & Crop Marks: When printing physical booklets, define @page { size: A4; marks: crop cross; bleed: 3mm; } to guide commercial print finishing.
MistakeConsequence
Using Flexbox / Grid wrappingColumns clip or break poorly across pages
Relative font sizes (rem / em)Font scaling depends on viewport size, leading to unpredictable sizing
Ignoring background color rulesTable headers or callouts have missing background fills in PDF
Orphaned HeadingsH2/H3 titles show at bottom of page; text starts on next page
No margin space in footer/headerHeaders/footers overlap document text

Frequently Asked Questions

Can I use standard CSS rules like page-break-before in markdown to PDF conversion?

Yes. When converting markdown to PDF using Signbee's API, you can embed standard CSS style tags or inline styles. To force a page break, use rules like page-break-before: always or break-before: page inside HTML tags embedded in your markdown, such as <div class="page-break"></div> or via custom CSS class definitions.

How do I manage margins, headers, and footers when generating PDFs?

Margins, headers, and footers are controlled via the Signbee /v1/generate API payload options. You can specify top, bottom, left, and right margins in inches, millimeters, or pixels. Custom headers and footers can contain HTML with special classes like date, title, url, pageNumber, and totalPages to dynamically print page info.

How do I style markdown tables and lists for PDF outputs?

Since markdown tables and lists compile to standard HTML tags (<table>, <ul>, <ol>), you can style them by passing a custom CSS stylesheet in the API payload. You should set border-collapse: collapse and define borders, padding, and alternating row backgrounds for tables to ensure they render beautifully and remain readable on a printed page.

Create beautifully styled agreements instantly — 5 free docs/month, 100 req/min.

Last updated: May 29, 2026 · Michael Beckett is the founder of Signbee and B2bee Ltd.

Related resources