Billing and receivables / A4
EU VAT invoice HTML template
A cross-border invoice inside the EU, with both parties' VAT identification numbers, tax broken out per rate, and a reverse charge statement.
When this document is the right one
A business in one member state supplies a business in another. The VAT treatment changes, the invoice has to say so explicitly, and an invoice that does not carry the required particulars can be rejected as evidence for an input tax claim.
Why each part is there
The fields are visible in the markup. What is not visible is why they are present, which is the part that gets removed first when someone adapts a template for their own use.
- Both VAT identification numbers, prominently. Applying the reverse charge without the customer's number stated is the most common reason a cross-border invoice is challenged.
- A supply date separate from the invoice date, because the tax point is the supply and the two are frequently in different months.
- A VAT summary table showing taxable amount and tax per rate, which is a legal requirement and not a design flourish.
- The reverse charge wording as a sentence on the face of the invoice, naming the provision relied on.
- Sequential numbering with no gaps, which most member states require rather than merely prefer.
The template
A complete file. Doctype, stylesheet, body: paste it into a renderer unchanged and it produces a finished A4 page. Replace the sample data and the styling holds.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>VAT invoice 2026-0451</title>
<style>
@page { size: A4; margin: 16mm 15mm 22mm; }
* { box-sizing: border-box; }
body { margin: 0; font: 9.5pt/1.45 Arial, sans-serif; color: #111; }
.head-grid { display: grid; grid-template-columns: 1fr auto; gap: 8mm;
border-bottom: 3px double #111; padding-bottom: 7mm; }
h1 { margin: 0 0 2mm; font-size: 16pt; }
.legal-note { font-size: 8pt; color: #555; }
.ids { display: grid; grid-template-columns: auto auto; gap: 1mm 5mm; font-size: 9pt; }
.ids dt { color: #555; }
.ids dd { margin: 0; font-variant-numeric: tabular-nums; }
.parties { display: grid; grid-template-columns: 1fr 1fr; gap: 8mm; margin: 7mm 0; }
.party { border: 1px solid #ccc; padding: 4mm; }
.party h2 { margin: 0 0 2mm; font-size: 8pt; text-transform: uppercase; color: #555; }
.party .vatid { margin-top: 2mm; font-size: 8.5pt; }
address { font-style: normal; }
table.lines { width: 100%; border-collapse: collapse; }
thead { display: table-header-group; }
table.lines th { background: #f2f2f2; border: 1px solid #ccc; padding: 2mm;
font-size: 8pt; text-align: left; }
table.lines td { border: 1px solid #ccc; padding: 2mm; }
tr { break-inside: avoid; }
.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* A VAT invoice must show tax broken out per rate, not only as one figure.
This block is a legal requirement in most of the EU, not a nicety. */
.vat-summary { margin-top: 7mm; break-inside: avoid; }
.vat-summary h2 { font-size: 9pt; margin: 0 0 2mm; }
.vat-summary table { border-collapse: collapse; width: 110mm; }
.vat-summary th, .vat-summary td { border: 1px solid #ccc; padding: 1.5mm 2mm; font-size: 8.5pt; }
.totals { margin-top: 5mm; margin-left: auto; width: 80mm; break-inside: avoid; }
.totals div { display: flex; justify-content: space-between; padding: 1.2mm 0; }
.totals .grand { border-top: 2px solid #111; padding-top: 2mm; font-weight: 700; font-size: 11.5pt; }
.reverse-charge { margin-top: 8mm; border-left: 3px solid #111; padding: 3mm 4mm;
background: #f7f7f7; font-size: 8.5pt; break-inside: avoid; }
</style>
</head>
<body>
<div class="head-grid">
<div>
<h1>Meridiaan Techniek B.V.</h1>
<address>Hoofdweg 212, 1057 DR Amsterdam, Netherlands</address>
<p class="legal-note">KvK 68421177 · VAT NL857392044B01</p>
</div>
<dl class="ids">
<dt>Invoice number</dt><dd>2026-0451</dd>
<dt>Invoice date</dt><dd>2026-05-14</dd>
<dt>Supply date</dt><dd>2026-05-09</dd>
<dt>Due date</dt><dd>2026-06-13</dd>
</dl>
</div>
<section class="parties">
<div class="party">
<h2>Supplier</h2>
<address><strong>Meridiaan Techniek B.V.</strong><br>
Hoofdweg 212<br>1057 DR Amsterdam<br>Netherlands</address>
<div class="vatid">VAT: NL857392044B01</div>
</div>
<div class="party">
<h2>Customer</h2>
<address><strong>Werkhaus Systeme GmbH</strong><br>
Lindenstrasse 44<br>10969 Berlin<br>Germany</address>
<div class="vatid">VAT: DE289410577</div>
</div>
</section>
<table class="lines">
<thead>
<tr>
<th>Description</th>
<th class="num">Qty</th>
<th class="num">Net unit</th>
<th class="num">VAT rate</th>
<th class="num">Net amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>Controller module MT-40, calibrated</td>
<td class="num">12</td><td class="num">318.00</td>
<td class="num">0% RC</td><td class="num">3,816.00</td>
</tr>
<tr>
<td>On-site commissioning, 2 engineer days</td>
<td class="num">2</td><td class="num">940.00</td>
<td class="num">0% RC</td><td class="num">1,880.00</td>
</tr>
<tr>
<td>Documentation pack, printed</td>
<td class="num">1</td><td class="num">125.00</td>
<td class="num">21%</td><td class="num">125.00</td>
</tr>
</tbody>
</table>
<section class="vat-summary">
<h2>VAT summary by rate</h2>
<table>
<tr><th>Rate</th><th class="num">Taxable amount</th><th class="num">VAT</th></tr>
<tr><td>0% (reverse charge)</td><td class="num">5,696.00</td><td class="num">0.00</td></tr>
<tr><td>21% standard</td><td class="num">125.00</td><td class="num">26.25</td></tr>
</table>
</section>
<div class="totals">
<div><span>Total net</span><span>5,821.00</span></div>
<div><span>Total VAT</span><span>26.25</span></div>
<div class="grand"><span>Total payable</span><span>EUR 5,847.25</span></div>
</div>
<p class="reverse-charge">
VAT reverse charged. Article 196 of Council Directive 2006/112/EC applies to the
supplies shown at 0%: the recipient is liable to account for VAT in Germany.
Both parties' VAT identification numbers are stated above, which is a condition
of applying the reverse charge.
</p>
</body>
</html>The layout decision worth understanding
The VAT summary is a separate block from the line table rather than a footer row inside it. That is deliberate: a summary row inside the table would break across pages with the table, and this block is the one thing on the document a tax inspector reads first. It gets break-inside: avoid and it sits above the totals.
The mistake people make adapting it
Showing one combined VAT figure when more than one rate is present. It is arithmetically correct and legally insufficient, and it is only ever noticed when someone tries to reconcile the invoice against a return.
Rendering it
The page box is declared in the template's own CSS as A4, so the size travels with the markup rather than living in the code that calls the renderer. A4 is also one of the six named formats the API accepts, so it can be passed in the request options instead if that suits your setup better.
curl -X POST https://api.pdfpipe.xyz/v1/pdf \
-H "Authorization: Bearer $PDFPIPE_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<!doctype html>...",
"options": { "format": "A4" }
}' \
--output invoice-vat.pdfFrequently asked
Can I use this template commercially?
Yes. Copy it, change it, ship it. It is sample markup written to be taken, and the sample data in it is invented, so replace the names and the numbers before anyone sees it.
Why is the page size in the CSS rather than in the API call?
Because a eu vat invoice is a A4 document, and that is a property of the document rather than of the code that renders it. Declaring it in the page box means the size cannot be lost between the template and the call, which is the usual way a document ends up on the wrong paper.
Will it look the same in every renderer?
The layout will, because it uses ordinary CSS. The page break behaviour will not: break-inside and break-after are implemented differently by browser engines and by dedicated print engines, and some of the paged media specification is not implemented in browser renders at all. That difference is documented per property in the paged CSS reference.
Other templates
Documents from the same part of a business, and one from each of the other groups.
HTML invoice template with CSS
The standard commercial invoice: a demand for payment with line items, a tax figure, and terms that say when the money is due.
GST tax invoice HTML template for India
An Indian tax invoice with GSTIN for both parties, HSN codes per line, and tax split into CGST and SGST or charged as IGST depending on the place of supply.
Commercial invoice template for customs
The customs document that travels with an international shipment: what the goods are, what they are worth, where they were made, and under what terms they move.
Proforma invoice HTML template
A document shaped like an invoice that is deliberately not one: it commits nobody to pay and exists so the buyer can raise an order, open a credit, or clear an import.
Payment receipt HTML template
Proof that a payment was made: the amount, the payment reference, the method, and what it was for.
Quotation HTML template with CSS
A priced proposal with a validity date, a scope, optional items kept out of the headline total, and somewhere to sign.
Packing slip HTML template
The document that goes in the box: what was ordered, what was actually shipped, and no prices at all.
Every template
The full set, grouped by what part of a business produces the document.
A4 page size for PDF generation
A4 is the default page for business documents everywhere except North America, and the default this API uses when no format is given.
Paste the template into the playground and get the PDF back. No signup, no key.