<div><span class="lbl">Product and project invoice with a print button</span>
<article class="ci" aria-labelledby="ci1-title">
<div class="ci-toolbar"><button class="ci-btn" type="button" data-print hidden><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9V3h12v6M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><path d="M6 14h12v7H6z"/></svg>Print or save as PDF</button></div>
<div class="ci-sheet">
<header class="ci-top">
<div class="ci-brand">
<svg class="ci-mark" width="44" height="44" viewBox="0 0 44 44" aria-hidden="true"><rect x="1" y="1" width="42" height="42" rx="6" fill="none" stroke="currentColor" stroke-width="2"/><path d="M12 32V12M12 22h11M23 12v20M28 32V12h4a5 5 0 0 1 0 10h-4" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
<div><p class="ci-co">Halden & Pike Studio</p>
<address class="ci-addr">214 Mercer Street, Suite 5<br>Portland, OR 97209<br>[email protected] · (503) 555-0142</address></div>
</div>
<div class="ci-head"><h2 class="ci-title" id="ci1-title">Invoice</h2><p class="ci-no">No. <b>HP-2026-0142</b></p></div>
</header>
<div class="ci-meta">
<div class="ci-to"><h3 class="ci-k">Billed to</h3>
<address class="ci-addr"><strong>Brightwater Coffee Co.</strong>Attn: Maya Okafor<br>77 Harbor Road<br>Astoria, OR 97103</address></div>
<div><h3 class="ci-k">Details</h3>
<dl class="ci-dl">
<dt>Issue date</dt><dd>12 Oct 2026</dd>
<dt>Due date</dt><dd>11 Nov 2026</dd>
<dt>Terms</dt><dd>Net 30</dd>
<dt>PO number</dt><dd>BW-4471</dd>
</dl>
<dl class="ci-due"><dt>Balance due</dt><dd>$8,997.21</dd></dl></div>
</div>
<table class="ci-table">
<caption>Line items</caption>
<thead><tr><th scope="col">Description</th><th scope="col" class="num">Qty</th><th scope="col" class="num">Unit price</th><th scope="col" class="num">Amount</th></tr></thead>
<tbody>
<tr><th scope="row"><strong>Brand identity refresh</strong><span>Logo, colour palette and type system</span></th><td class="num">1</td><td class="num">$4,800.00</td><td class="num">$4,800.00</td></tr>
<tr><th scope="row"><strong>Packaging design</strong><span>Retail bags in 250 g, 500 g and 1 kg</span></th><td class="num">3</td><td class="num">$950.00</td><td class="num">$2,850.00</td></tr>
<tr><th scope="row"><strong>Print-ready label artwork</strong><span>Revisions, billed hourly</span></th><td class="num">6 h</td><td class="num">$85.00</td><td class="num">$510.00</td></tr>
<tr><th scope="row"><strong>Photography art direction</strong><span>Half-day shoot at the roastery</span></th><td class="num">1</td><td class="num">$650.00</td><td class="num">$650.00</td></tr>
</tbody>
<tfoot>
<tr><th scope="row" colspan="3">Subtotal</th><td class="num">$8,810.00</td></tr>
<tr><th scope="row" colspan="3">Returning client discount (5%)</th><td class="num">−$440.50</td></tr>
<tr><th scope="row" colspan="3">Sales tax (7.5%)</th><td class="num">$627.71</td></tr>
<tr class="ci-grand"><th scope="row" colspan="3">Total due (USD)</th><td class="num">$8,997.21</td></tr>
</tfoot>
</table>
<footer class="ci-foot">
<div><h3 class="ci-k">Payment details</h3>
<dl class="ci-dl">
<dt>Bank transfer</dt><dd>Cascade Mutual Bank</dd>
<dt>Account name</dt><dd>Halden & Pike Studio LLC</dd>
<dt>Account</dt><dd>•••• 4821</dd>
<dt>Reference</dt><dd>HP-2026-0142</dd>
</dl></div>
<div><h3 class="ci-k">Notes</h3>
<p>Please quote the invoice number with your payment. Balances unpaid after the due date accrue 1.5% per month. Questions: <a href="mailto:[email protected]">[email protected]</a></p></div>
</footer>
<p class="ci-thanks">Thank you for your business.</p>
</div>
</article>
</div>
<div><span class="lbl">Hourly timesheet invoice (prints on its own page)</span>
<article class="ci ci-break" aria-labelledby="ci2-title">
<div class="ci-toolbar"><button class="ci-btn" type="button" data-print hidden><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 9V3h12v6M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><path d="M6 14h12v7H6z"/></svg>Print or save as PDF</button></div>
<div class="ci-sheet">
<header class="ci-top">
<div class="ci-brand">
<svg class="ci-mark" width="44" height="44" viewBox="0 0 44 44" aria-hidden="true"><circle cx="22" cy="22" r="21" fill="none" stroke="currentColor" stroke-width="2"/><path d="M15 13l7 18 7-18" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
<div><p class="ci-co">Ines Varga</p>
<address class="ci-addr">Freelance web development<br>9 Linden Court, Boise, ID 83702<br>[email protected]</address></div>
</div>
<div class="ci-head"><h2 class="ci-title" id="ci2-title">Invoice</h2><p class="ci-no">No. <b>IV-0087</b></p></div>
</header>
<div class="ci-meta">
<div class="ci-to"><h3 class="ci-k">Billed to</h3>
<address class="ci-addr"><strong>Fernway Outdoor Supply</strong>Accounts payable<br>1180 Ridgeline Avenue<br>Bend, OR 97701</address></div>
<div><h3 class="ci-k">Details</h3>
<dl class="ci-dl">
<dt>Period</dt><dd>1–14 Oct 2026</dd>
<dt>Issue date</dt><dd>15 Oct 2026</dd>
<dt>Due date</dt><dd>29 Oct 2026</dd>
</dl>
<dl class="ci-due"><dt>Balance due</dt><dd>$2,070.00</dd></dl></div>
</div>
<table class="ci-table">
<caption>Hours worked</caption>
<thead><tr><th scope="col">Date and task</th><th scope="col" class="num">Hours</th><th scope="col" class="num">Rate</th><th scope="col" class="num">Amount</th></tr></thead>
<tbody>
<tr><th scope="row"><strong>Checkout performance audit</strong><span>1 Oct 2026</span></th><td class="num">3.50</td><td class="num">$120.00</td><td class="num">$420.00</td></tr>
<tr><th scope="row"><strong>Product filter refactor</strong><span>3 Oct 2026</span></th><td class="num">6.00</td><td class="num">$120.00</td><td class="num">$720.00</td></tr>
<tr><th scope="row"><strong>Cart drawer accessibility fixes</strong><span>7 Oct 2026</span></th><td class="num">4.25</td><td class="num">$120.00</td><td class="num">$510.00</td></tr>
<tr><th scope="row"><strong>Deploy and uptime monitoring</strong><span>9 Oct 2026</span></th><td class="num">2.00</td><td class="num">$120.00</td><td class="num">$240.00</td></tr>
<tr><th scope="row"><strong>Code review and handover call</strong><span>14 Oct 2026</span></th><td class="num">1.50</td><td class="num">$120.00</td><td class="num">$180.00</td></tr>
</tbody>
<tfoot>
<tr><th scope="row" colspan="3">Total hours</th><td class="num">17.25</td></tr>
<tr class="ci-grand"><th scope="row" colspan="3">Total due (USD)</th><td class="num">$2,070.00</td></tr>
</tfoot>
</table>
<footer class="ci-foot">
<div><h3 class="ci-k">Payment details</h3>
<dl class="ci-dl"><dt>Bank transfer</dt><dd>Snake River Credit Union</dd><dt>Account</dt><dd>•••• 3307</dd><dt>Reference</dt><dd>IV-0087</dd></dl></div>
<div><h3 class="ci-k">Notes</h3><p>Payment due within 14 days. Hours are logged in 15-minute increments; the detailed log is attached to the email.</p></div>
</footer>
</div>
</article>
</div>
CSS
/* Classic printable invoice. On screen it is a sheet of paper; in print the @page rule sets the margins, the
sheet loses its shadow, the toolbar is hidden, the table header repeats on every page and rows never split.
size:auto follows the paper chosen in the print dialog (A4 or US Letter). Force one with size:A4 or size:letter. */
.ci{--ci-ink:#1c2533;--ci-muted:#56606e;--ci-line:#d5dae1;--ci-soft:#f3f5f8;--ci-accent:#1f4e79;--ci-paper:#fff;
box-sizing:border-box;max-width:210mm;margin:0 auto;color:var(--ci-ink);font-size:14px;line-height:1.5}
.ci *,.ci *::before,.ci *::after{box-sizing:border-box}
:where(.ci) :is(h2,h3,p,dl,dd,table,address){margin:0}
.ci .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.ci-toolbar{display:flex;justify-content:flex-end;gap:10px;margin-bottom:14px}
.ci-btn{display:inline-flex;align-items:center;gap:8px;padding:10px 18px;border:1px solid var(--ci-accent);border-radius:8px;background:var(--ci-accent);color:#fff;
font:600 .9rem/1 inherit;font-family:inherit;cursor:pointer;transition:background-color .15s}
.ci-btn[hidden]{display:none}
.ci-btn:hover{background:#173b5c}
.ci-btn:focus-visible,.ci a:focus-visible{outline:2px solid var(--ci-accent);outline-offset:3px}
.ci-sheet{background:var(--ci-paper);padding:56px 60px 48px;border-top:6px solid var(--ci-accent);box-shadow:0 1px 3px rgba(28,37,51,.08),0 24px 48px -28px rgba(28,37,51,.4)}
.ci-top{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:flex-start;gap:24px;padding-bottom:28px;border-bottom:1px solid var(--ci-line)}
.ci-brand{display:flex;gap:14px;align-items:flex-start}
.ci-mark{flex:none;color:var(--ci-accent)}
.ci-co{font-weight:700;font-size:1.05rem;line-height:1.3}
.ci-addr{font-style:normal;color:var(--ci-muted);font-size:.86rem;line-height:1.55}
.ci-head{text-align:right}
.ci-title{font-family:Georgia,"Times New Roman",serif;font-weight:400;font-size:2.5rem;line-height:1;letter-spacing:.02em;color:var(--ci-accent)}
.ci-no{margin-top:8px;color:var(--ci-muted);font-variant-numeric:tabular-nums}
.ci-no b{color:var(--ci-ink)}
.ci-meta{display:grid;grid-template-columns:1fr 1fr;gap:24px 40px;padding:28px 0}
.ci-k{font-size:.72rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ci-muted);margin-bottom:6px}
.ci-to strong{display:block;font-size:1rem}
.ci-dl{display:grid;grid-template-columns:auto 1fr;gap:4px 18px;font-variant-numeric:tabular-nums}
.ci-dl dt{color:var(--ci-muted)}
.ci-dl dd{text-align:right;font-weight:600}
.ci-due{display:flex;justify-content:space-between;align-items:baseline;gap:12px;margin-top:12px!important;padding:12px 14px;border-radius:6px;background:var(--ci-soft)}
.ci-due dd{font-size:1.2rem;font-weight:800;color:var(--ci-accent)}
.ci-table{width:100%;border-collapse:collapse;font-variant-numeric:tabular-nums}
.ci-table caption{text-align:left;font-size:.72rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ci-muted);padding-bottom:8px}
.ci-table thead th{padding:10px 8px;border-bottom:2px solid var(--ci-ink);font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ci-muted);text-align:left;font-weight:700}
.ci-table tbody :is(th,td){padding:14px 8px;border-bottom:1px solid var(--ci-line);vertical-align:top;text-align:left;font-weight:400}
.ci-table tbody th strong{display:block;font-weight:600}
.ci-table tbody th span{display:block;color:var(--ci-muted);font-size:.84rem}
.ci-table .num{text-align:right;white-space:nowrap}
.ci-table :is(th,td):first-child{padding-left:0}
.ci-table :is(th,td):last-child{padding-right:0}
.ci-table tfoot :is(th,td){padding:6px 8px;text-align:right;font-weight:400}
.ci-table tfoot th{color:var(--ci-muted)}
.ci-table tfoot tr:first-child :is(th,td){padding-top:16px}
.ci-table .ci-grand :is(th,td){padding-top:12px;border-top:2px solid var(--ci-ink);font-size:1.1rem;font-weight:800;color:var(--ci-ink)}
.ci-foot{display:grid;grid-template-columns:1.1fr 1fr;gap:24px 40px;margin-top:36px;padding-top:24px;border-top:1px solid var(--ci-line);font-size:.86rem}
.ci-foot .ci-dl dd{text-align:left;font-weight:500}
.ci-foot p{color:var(--ci-muted)}
.ci-thanks{margin-top:32px;text-align:center;font-family:Georgia,"Times New Roman",serif;font-style:italic;color:var(--ci-accent)}
.ci-sheet a{color:var(--ci-accent)}
@media (max-width:640px){
.ci{font-size:13px}
.ci-sheet{padding:28px 18px 26px}
.ci-head{text-align:left}
.ci-title{font-size:2rem}
.ci-meta,.ci-foot{grid-template-columns:1fr}
.ci-table thead th{font-size:.66rem;letter-spacing:.04em;padding:8px 4px}
.ci-table tbody :is(th,td),.ci-table tfoot :is(th,td){padding-left:4px;padding-right:4px}
}
@page{size:auto;margin:12mm}
@media print{
.ci{max-width:none;font-size:10pt;-webkit-print-color-adjust:exact;print-color-adjust:exact}
.ci-toolbar{display:none!important}
.ci-sheet{padding:6mm 0 0;box-shadow:none;border-top-width:4px}
.ci-top{padding-bottom:16px}
.ci-title{font-size:28pt}
.ci-meta{padding:14px 0}
.ci-table tbody :is(th,td){padding-top:7px;padding-bottom:7px}
.ci-table tfoot :is(th,td){padding-top:3px;padding-bottom:3px}
.ci-foot{margin-top:16px;padding-top:14px}
.ci-thanks{margin-top:12px}
.ci-break{break-before:page}
.ci-table thead{display:table-header-group}
.ci-table tr,.ci-foot,.ci-meta{break-inside:avoid}
.ci-sheet a{color:inherit;text-decoration:none}
}
@media (prefers-reduced-motion:reduce){.ci-btn{transition:none}}
JavaScript
// Print buttons are hidden until JavaScript can run them; the browser's own Print menu works either way.
document.querySelectorAll('[data-print]').forEach(function (btn) {
btn.hidden = false;
btn.addEventListener('click', function () { window.print(); });
});
/* Bootstrap .row/.col, .table, .btn and .d-print-none, retuned through Bootstrap's CSS variables. The @page rule and the
print block remove the shadow, repeat the table header on each page and keep rows whole. size:auto follows
the paper chosen in the print dialog (A4 or US Letter); force one with size:A4 or size:letter. */
.ci{--ci-ink:#1c2533;--ci-muted:#56606e;--ci-line:#d5dae1;--ci-soft:#f3f5f8;--ci-accent:#1f4e79;
--bs-body-color:var(--ci-ink);--bs-secondary-color:var(--ci-muted);--bs-border-color:var(--ci-line);
max-width:210mm;margin:0 auto;color:var(--ci-ink);font-size:14px;line-height:1.5}
.ci :is(h2,h3,p,dl,dd,address){margin:0}
.ci .btn-primary{--bs-btn-bg:var(--ci-accent);--bs-btn-border-color:var(--ci-accent);--bs-btn-hover-bg:#173b5c;--bs-btn-hover-border-color:#173b5c;--bs-btn-active-bg:#173b5c;
--bs-btn-font-weight:600;--bs-btn-font-size:.9rem;--bs-btn-padding-x:18px;--bs-btn-padding-y:10px;--bs-btn-border-radius:8px}
.ci-print{display:inline-flex;align-items:center;gap:8px}
.ci .btn:focus-visible,.ci a:focus-visible{outline:2px solid var(--ci-accent);outline-offset:3px;box-shadow:none}
.ci-sheet{background:#fff;padding:56px 60px 48px;border-top:6px solid var(--ci-accent);box-shadow:0 1px 3px rgba(28,37,51,.08),0 24px 48px -28px rgba(28,37,51,.4)}
.ci-title{font-family:Georgia,"Times New Roman",serif;font-weight:400;font-size:2.5rem;line-height:1;letter-spacing:.02em;color:var(--ci-accent)}
.ci-k{font-size:.72rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ci-muted);margin-bottom:6px!important}
.ci-addr{font-style:normal;color:var(--ci-muted);font-size:.86rem;line-height:1.55}
.ci-dl{display:grid;grid-template-columns:auto 1fr;gap:4px 18px;font-variant-numeric:tabular-nums}
.ci-dl dt{font-weight:400;color:var(--ci-muted)}
.ci-due{background:var(--ci-soft);border-radius:6px}
.ci .table{--bs-table-color:var(--ci-ink);--bs-table-bg:transparent;--bs-table-border-color:var(--ci-line);--bs-border-width:1px;font-variant-numeric:tabular-nums;margin:0}
.ci .table caption{color:var(--ci-muted);font-size:.72rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;padding:0 0 8px}
.ci .table thead th{padding:10px 8px;border-bottom:2px solid var(--ci-ink);font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ci-muted)}
.ci .table tbody>tr>*{padding:14px 8px;font-weight:400}
.ci .table>:not(caption)>*>*:first-child{padding-left:0}
.ci .table>:not(caption)>*>*:last-child{padding-right:0}
.ci .table tfoot>tr>*{padding:6px 8px;border:0;font-weight:400}
.ci .table tfoot th{color:var(--ci-muted)}
.ci .table tfoot tr:first-child>*{padding-top:16px}
.ci .table .ci-grand>*{padding-top:12px;border-top:2px solid var(--ci-ink);font-size:1.1rem;font-weight:800;color:var(--ci-ink)}
.ci-thanks{font-family:Georgia,"Times New Roman",serif;font-style:italic;color:var(--ci-accent)}
.ci-sheet a{color:var(--ci-accent)}
@media (max-width:640px){
.ci{font-size:13px}
.ci-sheet{padding:28px 18px 26px}
.ci-title{font-size:2rem}
.ci .table thead th{font-size:.66rem;letter-spacing:.04em;padding:8px 4px}
.ci .table tbody>tr>*,.ci .table tfoot>tr>*{padding-left:4px;padding-right:4px}
}
@page{size:auto;margin:12mm}
@media print{
.ci{max-width:none;font-size:10pt;-webkit-print-color-adjust:exact;print-color-adjust:exact}
.ci-sheet{padding:6mm 0 0;box-shadow:none;border-top-width:4px}
.ci-title{font-size:28pt}
.ci-top{padding-bottom:16px!important}
.ci-meta{padding:14px 0!important}
.ci .table tbody>tr>*{padding-top:7px;padding-bottom:7px}
.ci .table tfoot>tr>*{padding-top:3px;padding-bottom:3px}
.ci-foot{margin-top:16px!important;padding-top:14px!important}
.ci-thanks{margin-top:12px!important}
.ci-break{break-before:page}
.ci .table thead{display:table-header-group}
.ci .table tr,.ci-foot,.ci-meta{break-inside:avoid}
.ci-sheet a{color:inherit;text-decoration:none}
}
JavaScript
// Print buttons are hidden until JavaScript can run them; the browser's own Print menu works either way.
document.querySelectorAll('[data-print]').forEach(function (btn) {
btn.hidden = false;
btn.addEventListener('click', function () { window.print(); });
});
@theme {
--color-ci-ink: #1c2533;
--color-ci-muted: #56606e;
--color-ci-line: #d5dae1;
--color-ci-soft: #f3f5f8;
--color-ci-accent: #1f4e79;
--color-ci-accent-dark: #173b5c;
}
/* size:auto follows the paper chosen in the print dialog (A4 or US Letter); force one with size:A4 or size:letter.
print: utilities in the markup hide the button, drop the shadow and tighten spacing; thead repeats on each page. */
@page { size: auto; margin: 12mm; }
@media print {
thead { display: table-header-group; }
tr { break-inside: avoid; }
}
JavaScript
// Print buttons are hidden until JavaScript can run them; the browser's own Print menu works either way.
document.querySelectorAll('[data-print]').forEach(function (btn) {
btn.hidden = false;
btn.addEventListener('click', function () { window.print(); });
});
About this set
Two invoices laid out like a sheet of A4 or US Letter paper, built to come out of the browser’s Print dialog or Save as PDF as a clean page. Product and project invoice is for a design studio: a monogram and address block, a Billed to block, a details list with issue date, due date, terms and PO number, a highlighted balance due, a line items table with descriptions, quantity, unit price and amount, a discount, sales tax and total in the table footer, then payment details and notes. Hourly timesheet invoice is for a freelancer: each row is a dated task with hours and rate, and the footer adds up the hours and the total. On screen each invoice is a white sheet with a navy rule and a shadow. In print an @page rule sets 12 mm margins, size:auto follows the paper chosen in the dialog, the shadow and the Print button disappear, the table header repeats on every page, rows never split across pages, and the second invoice starts on a new page. The Print button is a few lines of JavaScript that call window.print() and stays hidden until the script runs. Below 640 pixels the blocks stack and the table tightens so it fits a phone.
What’s included
A4 or US Letter output from the browser print dialog, one invoice per page
@page margins, repeating table header and rows that never split across pages
Totals in a tfoot with th scope="row" labels, line items as th scope="row"
Print button hidden in print and until JavaScript runs
Product invoice and hourly timesheet invoice
Accessibility
Each invoice is an article named by its Invoice heading, the line items are a real table with a caption, column headers with scope="col" and row headers with scope="row", and the totals are labelled rows in the table footer. The Print button has a visible text label and a focus outline, and its colour transition is switched off under prefers-reduced-motion.
Customise it
Change --ci-accent, --ci-ink, --ci-muted and --ci-line on .ci for colour, and the @page rule for paper size and margins (size:A4 or size:letter to force one). Bootstrap uses the same variables on .ci beside the --bs-btn and --bs-table overrides; in Tailwind edit the ci-* colours in @theme.