# A free HTML invoice template (HTML + CSS) that prints to a one-page PDF

> A copy-paste HTML and CSS invoice template for A4, rendered to a one-page PDF and a PNG: the fields, how to fill it from code, and when you need more.

Published 2026-11-08 · https://shareglint.com/en/guides/html-invoice-template

Below is a complete invoice template in plain HTML and CSS: a header with your details and the invoice number, a bill-to block, eight line items, totals, and payment details at the bottom of an A4 page. Copy it, change the colours and labels, and print it from any browser or HTML-to-PDF tool. We rendered it on 2026-11-08 through Shareglint — to a **one-page A4 PDF** with real, selectable text, and to a PNG — and saved it as a template through our API to make sure it passes our template rules as written.

The fields are `{{ field }}` placeholders, the syntax our templates use; in your own code, replace them with your template engine's syntax (Jinja, Blade, Handlebars) or with plain string replacement.

## The HTML

```html
<div class="invoice">
  <header class="top">
    <div class="brand">
      <img class="logo" src="{{ logo }}" alt="">
      <p class="seller">{{ seller_name }}<br>{{ seller_address }}<br>{{ seller_tax_id }}</p>
    </div>
    <div class="meta">
      <h1>Invoice</h1>
      <div class="pair"><span>Number</span><strong>{{ number }}</strong></div>
      <div class="pair"><span>Date</span><strong>{{ date }}</strong></div>
      <div class="pair"><span>Due</span><strong>{{ due }}</strong></div>
    </div>
  </header>
  <section class="bill-to">
    <h2>Bill to</h2>
    <p>{{ buyer_name }}<br>{{ buyer_address }}<br>{{ buyer_tax_id }}</p>
  </section>
  <section class="lines">
    <div class="row head"><span>Description</span><span class="num">Qty</span><span class="num">Unit price</span><span class="num">Amount</span></div>
    <div class="row"><span>{{ item_1 }}</span><span class="num">{{ qty_1 }}</span><span class="num">{{ price_1 }}</span><span class="num">{{ amount_1 }}</span></div>
    <div class="row"><span>{{ item_2 }}</span><span class="num">{{ qty_2 }}</span><span class="num">{{ price_2 }}</span><span class="num">{{ amount_2 }}</span></div>
    <div class="row"><span>{{ item_3 }}</span><span class="num">{{ qty_3 }}</span><span class="num">{{ price_3 }}</span><span class="num">{{ amount_3 }}</span></div>
    <div class="row"><span>{{ item_4 }}</span><span class="num">{{ qty_4 }}</span><span class="num">{{ price_4 }}</span><span class="num">{{ amount_4 }}</span></div>
    <div class="row"><span>{{ item_5 }}</span><span class="num">{{ qty_5 }}</span><span class="num">{{ price_5 }}</span><span class="num">{{ amount_5 }}</span></div>
    <div class="row"><span>{{ item_6 }}</span><span class="num">{{ qty_6 }}</span><span class="num">{{ price_6 }}</span><span class="num">{{ amount_6 }}</span></div>
    <div class="row"><span>{{ item_7 }}</span><span class="num">{{ qty_7 }}</span><span class="num">{{ price_7 }}</span><span class="num">{{ amount_7 }}</span></div>
    <div class="row"><span>{{ item_8 }}</span><span class="num">{{ qty_8 }}</span><span class="num">{{ price_8 }}</span><span class="num">{{ amount_8 }}</span></div>
  </section>
  <section class="totals">
    <div class="pair"><span>Subtotal</span><span>{{ subtotal }}</span></div>
    <div class="pair"><span>{{ tax_label }}</span><span>{{ tax }}</span></div>
    <div class="pair grand"><span>Total</span><span>{{ total }}</span></div>
  </section>
  <footer class="pay">
    <h2>Payment</h2>
    <p>{{ payment }}</p>
    <p class="note">{{ note }}</p>
  </footer>
</div>
```

## The CSS

```css
.invoice { box-sizing: border-box; width: 794px; height: 1123px; padding: 56px 60px; display: flex; flex-direction: column; font: 13px/1.5 'Roboto', sans-serif; color: #1f2937; background: #fff; }
p { margin: 0; }
.top { display: flex; justify-content: space-between; align-items: flex-start; gap: 32px; padding-bottom: 28px; border-bottom: 2px solid #1d4ed8; }
.brand { display: flex; flex-direction: column; gap: 12px; }
.logo { max-width: 160px; max-height: 56px; object-fit: contain; }
.seller { color: #4b5563; }
.meta { min-width: 220px; }
h1 { margin: 0 0 8px; text-align: right; font-size: 32px; font-weight: 700; letter-spacing: .02em; color: #1d4ed8; text-transform: uppercase; }
.pair { display: flex; justify-content: space-between; gap: 16px; }
.meta .pair span { color: #6b7280; }
h2 { margin: 0 0 6px; font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: #6b7280; }
.bill-to { margin: 28px 0 24px; }
.row { display: grid; grid-template-columns: 1fr 60px 120px 120px; gap: 12px; padding: 9px 8px; min-height: 22px; border-bottom: 1px solid #e5e7eb; }
.row.head { background: #eff6ff; color: #1e3a8a; font-weight: 600; border-bottom: 0; }
.num { text-align: right; white-space: nowrap; }
.totals { margin: 20px 0 0 auto; width: 300px; }
.totals .pair { padding: 5px 0; color: #4b5563; }
.totals .grand { margin-top: 6px; padding-top: 10px; border-top: 2px solid #1f2937; font-size: 16px; font-weight: 700; color: #111827; }
.pay { margin-top: auto; padding-top: 20px; border-top: 1px solid #e5e7eb; }
.note { margin-top: 4px; color: #6b7280; font-size: 12px; }
```

## What is in it

- **A4 at 96 px per inch.** The page is 794×1123 CSS pixels, which our renderer prints as a 595.92 × 842.88 pt PDF — A4. For US Letter, change the size to 816×1056.
- **Flexbox for the header, CSS grid for the lines.** Each line is a four-column grid row: description, quantity, unit price, amount. Numbers are right-aligned and never wrap.
- **Footer pinned to the bottom.** The invoice is a flex column and the payment block has `margin-top: auto`, so it sits at the foot of the page however many lines are filled.
- **Roboto**, one of the fonts installed on our renderer ([fonts and emoji](https://shareglint.com/en/guides/fonts-and-emoji-in-generated-images)); in your own setup, any installed or web font works.
- **48 fields**: seller, buyer, number and dates, eight lines of four fields, totals, tax label, payment text, a note and a logo image.

Why rows of `div`s and not a `<table>`: either works. Saved templates pass through an HTML sanitiser that keeps tables (`<table>` with its sections, `colspan` and `rowspan`); grid rows are used here because every line item is one fixed row with its own fields. Use a table if you prefer.

## Filling it

Compute every number in your billing code and send the results as formatted text — the template does no arithmetic, and money should never be calculated in a layout. Empty line slots render as empty rows, which keeps the layout identical for one line or eight.

With Shareglint, save it once (`POST /v1/templates` with the HTML, the CSS, `width` 794, `height` 1123, the field list and `"images": ["logo"]`), then each invoice is one request:

```bash
curl -X POST "https://shareglint.com/v1/images?wait=true" \
  -H "Authorization: Bearer sk_live_..." -H "Content-Type: application/json" \
  -d '{ "template": "invoice-a4", "format": "pdf",
        "modifications": { "number": "2026-0412", "date": "8 November 2026", "due": "22 November 2026",
          "seller_name": "Northwind Ltd", "buyer_name": "Acme GmbH",
          "item_1": "Annual subscription, Pro plan", "qty_1": "1", "price_1": "€1,200.00", "amount_1": "€1,200.00",
          "subtotal": "€1,200.00", "tax_label": "VAT 0% (reverse charge)", "tax": "€0.00", "total": "€1,200.00",
          "payment": "IBAN GB00 NWBK 0000 0000 0000 00 · Ref 2026-0412" } }'
```

The response's `url` is the PDF; `"format": "png"` gives an image for an email or a preview instead. For a month's invoices, a batch takes one row per invoice and returns every PDF and a ZIP (rows per batch by plan: Free 50, Starter 500, Pro 1,000, Scale 2,000, Business 5,000). Store each PDF in your own system: invoices usually have to be kept for years, and our copies are kept for 365 days on paid plans.

## When this template is not enough

Be clear about the limits before you build on it:

- **One page only.** Our PDFs are always exactly one page, the template's size — no page breaks, no header repeated on page two, no page numbers. Eight lines fit comfortably; an invoice with forty lines needs a multi-page tool such as Playwright, Puppeteer or WeasyPrint ([HTML to PDF in Python](https://shareglint.com/en/guides/html-to-pdf-python) compares them on a 45-line invoice).
- **Not an e-invoice.** In the EU, an electronic invoice is structured data under the standard EN 16931; a PDF is a human-readable copy ([European Commission, eInvoicing](https://ec.europa.eu/digital-building-blocks/sites/display/DIGITAL/eInvoicing)).
- **No legal check.** What an invoice must show depends on your country and your customer's — numbering, tax numbers, tax per rate, payment terms. The template shows what you send.

More on where one-page PDFs fit, and where they do not, is in [PDF invoices](https://shareglint.com/en/use-cases/pdf-invoices). The CSS units and print sizes follow [CSS Values and Units](https://www.w3.org/TR/css-values-4/#absolute-lengths): 1 in = 96 px.

## FAQ

### Is this HTML invoice template free to use?

Yes. Copy the HTML and CSS into your own project, change the colours and wording, and use it however you like. It is plain HTML and CSS with no framework, so any HTML-to-PDF tool or browser can print it.

### Why does the template use div rows instead of a table?

Either works: saved templates keep table elements (table, thead, tbody, tr, th, td, colspan, rowspan). Grid rows are used here because each line item is one fixed row with its own fields, and the same markup reads well in any HTML-to-PDF tool.

### How many invoice lines fit?

The template has eight fixed line slots and fits on one A4 page; empty slots stay as blank lines. For more lines, add slots (up to the 50-field limit of a saved template) and check the longest invoice still fits, or use a multi-page PDF tool.

### Can I turn the template into a multi-page invoice?

Not with our API: our PDFs are always one page, the template's size. Long invoices need page breaks, repeated headers and page numbers — use Playwright, Puppeteer or WeasyPrint with the same HTML, adding a table with a repeated header.
