Selling and buying / A4
Purchase order HTML template
Issued by the buyer: an instruction to supply specific goods at specific prices, with separate delivery and invoicing addresses and the conditions of the order.
When this document is the right one
A buyer commits to a purchase. It is the document a goods-in team checks a delivery against and an accounts payable team matches an invoice to, so it is read by three different departments with three different interests.
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.
- Three addresses: supplier, deliver-to and invoice-to. Assuming any two of them are the same is how goods arrive at a finance office.
- A required-by date, because a purchase order with no date is a wish.
- Supplier part numbers alongside your own description, since the picker at the other end works from their catalogue rather than your wording.
- The order number, stated as required on the delivery note and the invoice, because three-way matching fails without it.
- Conditions of order, which is where the delivery window, the part-shipment rule and the price-firmness rule live.
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>Purchase order PO-88213</title>
<style>
@page { size: A4; margin: 15mm; }
* { box-sizing: border-box; }
body { margin: 0; font: 9.5pt/1.4 Arial, sans-serif; color: #111; }
header { display: flex; justify-content: space-between; align-items: flex-start;
border-bottom: 3px solid #111; padding-bottom: 6mm; }
h1 { margin: 0; font-size: 22pt; letter-spacing: 0.02em; }
.po-no { font-size: 14pt; font-weight: 700; font-variant-numeric: tabular-nums; }
.issued-by { text-align: right; font-size: 9pt; }
/* Ship-to and bill-to are different addresses often enough that assuming
they are the same is how goods arrive at a finance office. */
.addresses { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5mm;
margin: 7mm 0; }
.addresses > div { border: 1px solid #ccc; padding: 3.5mm; }
.addresses h2 { margin: 0 0 2mm; font-size: 7.5pt; text-transform: uppercase;
letter-spacing: 0.07em; color: #666; }
address { font-style: normal; }
.terms-strip { display: grid; grid-template-columns: repeat(4, 1fr);
border: 1px solid #111; margin-bottom: 6mm; }
.terms-strip > div { padding: 3mm; border-right: 1px solid #ccc; }
.terms-strip > div:last-child { border-right: 0; }
.terms-strip .k { font-size: 7.5pt; text-transform: uppercase; color: #666;
letter-spacing: 0.06em; }
.terms-strip .v { font-weight: 700; margin-top: 1mm; }
table { width: 100%; border-collapse: collapse; }
thead { display: table-header-group; }
th, td { border: 1px solid #ccc; padding: 2.2mm; }
th { background: #f1f1f1; text-align: left; font-size: 8pt;
text-transform: uppercase; letter-spacing: 0.05em; }
tr { break-inside: avoid; }
.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
tfoot td { font-weight: 700; }
.conditions { margin-top: 7mm; font-size: 8pt; color: #444; break-inside: avoid;
border-top: 1px solid #ccc; padding-top: 4mm; }
.conditions ol { margin: 2mm 0 0; padding-left: 5mm; }
.conditions li { margin-bottom: 1.2mm; }
.auth { margin-top: 8mm; display: grid; grid-template-columns: 1fr 1fr; gap: 10mm;
break-inside: avoid; }
.auth div { border-top: 1px solid #111; padding-top: 2mm; font-size: 8.5pt;
margin-top: 14mm; }
</style>
</head>
<body>
<header>
<div>
<h1>Purchase order</h1>
<div class="po-no">PO-88213</div>
</div>
<div class="issued-by">
<strong>Calder Interiors Ltd</strong><br>
7 Meridian Court, Leeds LS11 5AL<br>
procurement@calderinteriors.example<br>
Raised 06 May 2026 by D. Okafor
</div>
</header>
<section class="addresses">
<div>
<h2>Supplier</h2>
<address><strong>Northgate Supply Co.</strong><br>
18 Wharf Road<br>Bristol BS1 4RN<br>Account NG-4471</address>
</div>
<div>
<h2>Deliver to</h2>
<address><strong>Calder Interiors, Workshop</strong><br>
Unit 6, Kirkstall Trade Park<br>Leeds LS4 2AZ<br>Goods in: 07:00 to 15:00</address>
</div>
<div>
<h2>Invoice to</h2>
<address><strong>Calder Interiors Ltd</strong><br>
Accounts Payable<br>7 Meridian Court<br>Leeds LS11 5AL<br>
ap@calderinteriors.example</address>
</div>
</section>
<div class="terms-strip">
<div><div class="k">Required by</div><div class="v">12 May 2026</div></div>
<div><div class="k">Payment terms</div><div class="v">Net 30</div></div>
<div><div class="k">Delivery terms</div><div class="v">DAP Leeds</div></div>
<div><div class="k">Currency</div><div class="v">GBP</div></div>
</div>
<table>
<thead>
<tr>
<th>Line</th><th>Supplier part</th><th>Description</th>
<th class="num">Qty</th><th>UoM</th>
<th class="num">Unit price</th><th class="num">Line total</th>
</tr>
</thead>
<tbody>
<tr><td>1</td><td>NG-OAK-2412</td><td>Oak veneer panel, 2400 x 1200, A grade</td>
<td class="num">24</td><td>ea</td><td class="num">86.00</td><td class="num">2,064.00</td></tr>
<tr><td>2</td><td>NG-EB-22</td><td>Edge banding, 22mm, 50m roll</td>
<td class="num">6</td><td>roll</td><td class="num">41.50</td><td class="num">249.00</td></tr>
<tr><td>3</td><td>NG-DEL-PAL</td><td>Palletised delivery, two-day</td>
<td class="num">1</td><td>ea</td><td class="num">115.00</td><td class="num">115.00</td></tr>
</tbody>
<tfoot>
<tr><td colspan="6" class="num">Order total, excluding VAT</td>
<td class="num">2,428.00</td></tr>
</tfoot>
</table>
<section class="conditions">
<strong>Conditions of order</strong>
<ol>
<li>The purchase order number must appear on the delivery note and on the invoice. An invoice without it will be returned unpaid.</li>
<li>Deliveries outside the goods-in window will be refused at the gate.</li>
<li>Part deliveries are accepted only where agreed in writing in advance; the balance is not automatically back-ordered.</li>
<li>Prices are firm. Any variation must be agreed before despatch, not raised on the invoice.</li>
<li>Title passes on delivery. Risk passes on acceptance at goods in.</li>
</ol>
</section>
<div class="auth">
<div>Authorised by, for Calder Interiors Ltd</div>
<div>Date</div>
</div>
</body>
</html>The layout decision worth understanding
The layout is a grid of bordered cells rather than a flowing document. Purchase orders are read fast by people looking for one field, and a rigid grid means the delivery address is always in the same place on every order the supplier receives.
The mistake people make adapting it
Leaving the delivery window off. Every warehouse has one, deliveries outside it are refused at the gate, and the driver then costs everyone a second delivery charge for a fact that would have fitted in eight words.
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 purchase-order.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 purchase order 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.
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.
Trade price list PDF template
A dated catalogue of prices by item code, usually with a second column for volume, issued to trade accounts.
Order confirmation HTML template
Sent to the buyer after an order is placed: what was ordered, what it cost, and above all when it will arrive.
Product datasheet PDF template
A two-column technical specification sheet with a revision number, grouped tables, a dimensions figure and an ordering code.
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.
Payment receipt HTML template
Proof that a payment was made: the amount, the payment reference, the method, and what it was for.
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.