Open demo

CSS code

HTML
<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 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Product and project invoice with a print button</span>
<article class="ci" aria-labelledby="ci1-title">
  <div class="d-flex justify-content-end mb-3 d-print-none"><button class="btn btn-primary ci-print" 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 d-flex flex-wrap justify-content-between align-items-start gap-4 pb-4 border-bottom">
      <div class="d-flex align-items-start gap-3">
        <svg class="flex-shrink-0" style="color:var(--ci-accent)" 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="fw-bold fs-6 lh-sm mb-1">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="text-sm-end"><h2 class="ci-title" id="ci1-title">Invoice</h2><p class="mt-2 text-body-secondary">No. <b class="text-body">HP-2026-0142</b></p></div>
    </header>
    <div class="ci-meta row g-4 py-4">
      <div class="col-sm-6"><h3 class="ci-k">Billed to</h3>
        <address class="ci-addr"><strong class="d-block fs-6 text-body">Brightwater Coffee Co.</strong>Attn: Maya Okafor<br>77 Harbor Road<br>Astoria, OR 97103</address></div>
      <div class="col-sm-6"><h3 class="ci-k">Details</h3>
        <dl class="ci-dl">
          <dt>Issue date</dt><dd class="text-end fw-semibold">12 Oct 2026</dd>
          <dt>Due date</dt><dd class="text-end fw-semibold">11 Nov 2026</dd>
          <dt>Terms</dt><dd class="text-end fw-semibold">Net 30</dd>
          <dt>PO number</dt><dd class="text-end fw-semibold">BW-4471</dd>
        </dl>
        <dl class="ci-due d-flex justify-content-between align-items-baseline gap-3 mt-3 px-3 py-2"><dt class="fw-normal">Balance due</dt><dd class="fs-5 fw-bolder" style="color:var(--ci-accent)">$8,997.21</dd></dl></div>
    </div>
    <table class="table caption-top">
      <caption>Line items</caption>
      <thead><tr><th scope="col">Description</th><th scope="col" class="text-end">Qty</th><th scope="col" class="text-end">Unit price</th><th scope="col" class="text-end">Amount</th></tr></thead>
      <tbody>
        <tr><th scope="row"><strong class="d-block fw-semibold">Brand identity refresh</strong><span class="small text-body-secondary">Logo, colour palette and type system</span></th><td class="text-end text-nowrap">1</td><td class="text-end text-nowrap">$4,800.00</td><td class="text-end text-nowrap">$4,800.00</td></tr>
        <tr><th scope="row"><strong class="d-block fw-semibold">Packaging design</strong><span class="small text-body-secondary">Retail bags in 250 g, 500 g and 1 kg</span></th><td class="text-end text-nowrap">3</td><td class="text-end text-nowrap">$950.00</td><td class="text-end text-nowrap">$2,850.00</td></tr>
        <tr><th scope="row"><strong class="d-block fw-semibold">Print-ready label artwork</strong><span class="small text-body-secondary">Revisions, billed hourly</span></th><td class="text-end text-nowrap">6 h</td><td class="text-end text-nowrap">$85.00</td><td class="text-end text-nowrap">$510.00</td></tr>
        <tr><th scope="row"><strong class="d-block fw-semibold">Photography art direction</strong><span class="small text-body-secondary">Half-day shoot at the roastery</span></th><td class="text-end text-nowrap">1</td><td class="text-end text-nowrap">$650.00</td><td class="text-end text-nowrap">$650.00</td></tr>
      </tbody>
      <tfoot>
        <tr><th scope="row" colspan="3" class="text-end">Subtotal</th><td class="text-end text-nowrap">$8,810.00</td></tr>
        <tr><th scope="row" colspan="3" class="text-end">Returning client discount (5%)</th><td class="text-end text-nowrap">−$440.50</td></tr>
        <tr><th scope="row" colspan="3" class="text-end">Sales tax (7.5%)</th><td class="text-end text-nowrap">$627.71</td></tr>
        <tr class="ci-grand"><th scope="row" colspan="3" class="text-end">Total due (USD)</th><td class="text-end text-nowrap">$8,997.21</td></tr>
      </tfoot>
    </table>
    <footer class="ci-foot row g-4 mt-4 pt-4 border-top small">
      <div class="col-sm-6"><h3 class="ci-k">Payment details</h3>
        <dl class="ci-dl"><dt>Bank transfer</dt><dd class="fw-medium">Cascade Mutual Bank</dd><dt>Account name</dt><dd class="fw-medium">Halden & Pike Studio LLC</dd><dt>Account</dt><dd class="fw-medium">•••• 4821</dd><dt>Reference</dt><dd class="fw-medium">HP-2026-0142</dd></dl></div>
      <div class="col-sm-6"><h3 class="ci-k">Notes</h3>
        <p class="text-body-secondary">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 text-center mt-4">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="d-flex justify-content-end mb-3 d-print-none"><button class="btn btn-primary ci-print" 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 d-flex flex-wrap justify-content-between align-items-start gap-4 pb-4 border-bottom">
      <div class="d-flex align-items-start gap-3">
        <svg class="flex-shrink-0" style="color:var(--ci-accent)" 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="fw-bold fs-6 lh-sm mb-1">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="text-sm-end"><h2 class="ci-title" id="ci2-title">Invoice</h2><p class="mt-2 text-body-secondary">No. <b class="text-body">IV-0087</b></p></div>
    </header>
    <div class="ci-meta row g-4 py-4">
      <div class="col-sm-6"><h3 class="ci-k">Billed to</h3>
        <address class="ci-addr"><strong class="d-block fs-6 text-body">Fernway Outdoor Supply</strong>Accounts payable<br>1180 Ridgeline Avenue<br>Bend, OR 97701</address></div>
      <div class="col-sm-6"><h3 class="ci-k">Details</h3>
        <dl class="ci-dl">
          <dt>Period</dt><dd class="text-end fw-semibold">1–14 Oct 2026</dd>
          <dt>Issue date</dt><dd class="text-end fw-semibold">15 Oct 2026</dd>
          <dt>Due date</dt><dd class="text-end fw-semibold">29 Oct 2026</dd>
        </dl>
        <dl class="ci-due d-flex justify-content-between align-items-baseline gap-3 mt-3 px-3 py-2"><dt class="fw-normal">Balance due</dt><dd class="fs-5 fw-bolder" style="color:var(--ci-accent)">$2,070.00</dd></dl></div>
    </div>
    <table class="table caption-top">
      <caption>Hours worked</caption>
      <thead><tr><th scope="col">Date and task</th><th scope="col" class="text-end">Hours</th><th scope="col" class="text-end">Rate</th><th scope="col" class="text-end">Amount</th></tr></thead>
      <tbody>
        <tr><th scope="row"><strong class="d-block fw-semibold">Checkout performance audit</strong><span class="small text-body-secondary">1 Oct 2026</span></th><td class="text-end">3.50</td><td class="text-end">$120.00</td><td class="text-end">$420.00</td></tr>
        <tr><th scope="row"><strong class="d-block fw-semibold">Product filter refactor</strong><span class="small text-body-secondary">3 Oct 2026</span></th><td class="text-end">6.00</td><td class="text-end">$120.00</td><td class="text-end">$720.00</td></tr>
        <tr><th scope="row"><strong class="d-block fw-semibold">Cart drawer accessibility fixes</strong><span class="small text-body-secondary">7 Oct 2026</span></th><td class="text-end">4.25</td><td class="text-end">$120.00</td><td class="text-end">$510.00</td></tr>
        <tr><th scope="row"><strong class="d-block fw-semibold">Deploy and uptime monitoring</strong><span class="small text-body-secondary">9 Oct 2026</span></th><td class="text-end">2.00</td><td class="text-end">$120.00</td><td class="text-end">$240.00</td></tr>
        <tr><th scope="row"><strong class="d-block fw-semibold">Code review and handover call</strong><span class="small text-body-secondary">14 Oct 2026</span></th><td class="text-end">1.50</td><td class="text-end">$120.00</td><td class="text-end">$180.00</td></tr>
      </tbody>
      <tfoot>
        <tr><th scope="row" colspan="3" class="text-end">Total hours</th><td class="text-end">17.25</td></tr>
        <tr class="ci-grand"><th scope="row" colspan="3" class="text-end">Total due (USD)</th><td class="text-end text-nowrap">$2,070.00</td></tr>
      </tfoot>
    </table>
    <footer class="ci-foot row g-4 mt-4 pt-4 border-top small">
      <div class="col-sm-6"><h3 class="ci-k">Payment details</h3>
        <dl class="ci-dl"><dt>Bank transfer</dt><dd class="fw-medium">Snake River Credit Union</dd><dt>Account</dt><dd class="fw-medium">•••• 3307</dd><dt>Reference</dt><dd class="fw-medium">IV-0087</dd></dl></div>
      <div class="col-sm-6"><h3 class="ci-k">Notes</h3><p class="text-body-secondary">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
/* 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(); });
});

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#56606e] uppercase print:hidden">Product and project invoice with a print button</span>
<article class="mx-auto max-w-[210mm] text-[14px] leading-normal text-ci-ink max-sm:text-[13px] print:max-w-none print:text-[10pt] print:[print-color-adjust:exact]" aria-labelledby="ci1-title">
  <div class="mb-3.5 flex justify-end print:hidden"><button class="inline-flex cursor-pointer items-center gap-2 rounded-lg border border-ci-accent bg-ci-accent px-[18px] py-2.5 text-[.9rem] leading-none font-semibold text-white transition-colors duration-150 hover:bg-ci-accent-dark focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-ci-accent motion-reduce:transition-none" 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="border-t-[6px] border-ci-accent bg-white px-[60px] pt-14 pb-12 shadow-[0_1px_3px_rgba(28,37,51,.08),0_24px_48px_-28px_rgba(28,37,51,.4)] max-sm:px-[18px] max-sm:pt-7 max-sm:pb-[26px] print:border-t-4 print:px-0 print:pt-[6mm] print:pb-0 print:shadow-none">
    <header class="flex flex-wrap items-start justify-between gap-6 border-b border-ci-line pb-7 print:pb-4">
      <div class="flex items-start gap-3.5">
        <svg class="flex-none text-ci-accent" 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="text-[1.05rem] leading-[1.3] font-bold">Halden & Pike Studio</p>
          <address class="text-[.86rem] leading-[1.55] text-ci-muted not-italic">214 Mercer Street, Suite 5<br>Portland, OR 97209<br>[email protected] · (503) 555-0142</address></div>
      </div>
      <div class="text-right max-sm:text-left"><h2 class="font-[Georgia,'Times_New_Roman',serif] text-[2.5rem] leading-none font-normal tracking-[.02em] text-ci-accent max-sm:text-[2rem] print:text-[28pt]" id="ci1-title">Invoice</h2><p class="mt-2 text-ci-muted tabular-nums">No. <b class="text-ci-ink">HP-2026-0142</b></p></div>
    </header>
    <div class="grid grid-cols-2 gap-x-10 gap-y-6 py-7 max-sm:grid-cols-1 print:break-inside-avoid print:py-3.5">
      <div><h3 class="mb-1.5 text-[.72rem] font-bold tracking-[.12em] text-ci-muted uppercase">Billed to</h3>
        <address class="text-[.86rem] leading-[1.55] text-ci-muted not-italic"><strong class="block text-base text-ci-ink">Brightwater Coffee Co.</strong>Attn: Maya Okafor<br>77 Harbor Road<br>Astoria, OR 97103</address></div>
      <div><h3 class="mb-1.5 text-[.72rem] font-bold tracking-[.12em] text-ci-muted uppercase">Details</h3>
        <dl class="grid grid-cols-[auto_1fr] gap-x-[18px] gap-y-1 tabular-nums [&>dd]:text-right [&>dd]:font-semibold [&>dt]:text-ci-muted">
          <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="mt-3 flex items-baseline justify-between gap-3 rounded-md bg-ci-soft px-3.5 py-3 tabular-nums"><dt>Balance due</dt><dd class="text-[1.2rem] font-extrabold text-ci-accent">$8,997.21</dd></dl></div>
    </div>
    <table class="w-full border-collapse tabular-nums [&_tbody_:is(th,td)]:border-b [&_tbody_:is(th,td)]:border-ci-line [&_tbody_:is(th,td)]:px-2 [&_tbody_:is(th,td)]:py-3.5 [&_tbody_:is(th,td)]:text-left [&_tbody_:is(th,td)]:align-top [&_tbody_:is(th,td)]:font-normal max-sm:[&_tbody_:is(th,td)]:px-1 print:[&_tbody_:is(th,td)]:py-[7px] [&_:is(th,td):first-child]:pl-0 [&_:is(th,td):last-child]:pr-0 [&_tbody_td]:text-right! [&_tbody_td]:whitespace-nowrap">
      <caption class="pb-2 text-left text-[.72rem] font-bold tracking-[.12em] text-ci-muted uppercase">Line items</caption>
      <thead class="[&_th]:border-b-2 [&_th]:border-ci-ink [&_th]:px-2 [&_th]:py-2.5 [&_th]:text-[.72rem] [&_th]:font-bold [&_th]:tracking-[.08em] [&_th]:text-ci-muted [&_th]:uppercase max-sm:[&_th]:px-1 max-sm:[&_th]:py-2 max-sm:[&_th]:text-[.66rem] max-sm:[&_th]:tracking-[.04em]"><tr><th scope="col" class="text-left">Description</th><th scope="col" class="text-right">Qty</th><th scope="col" class="text-right">Unit price</th><th scope="col" class="text-right">Amount</th></tr></thead>
      <tbody>
        <tr><th scope="row"><strong class="block font-semibold">Brand identity refresh</strong><span class="block text-[.84rem] text-ci-muted">Logo, colour palette and type system</span></th><td>1</td><td>$4,800.00</td><td>$4,800.00</td></tr>
        <tr><th scope="row"><strong class="block font-semibold">Packaging design</strong><span class="block text-[.84rem] text-ci-muted">Retail bags in 250 g, 500 g and 1 kg</span></th><td>3</td><td>$950.00</td><td>$2,850.00</td></tr>
        <tr><th scope="row"><strong class="block font-semibold">Print-ready label artwork</strong><span class="block text-[.84rem] text-ci-muted">Revisions, billed hourly</span></th><td>6 h</td><td>$85.00</td><td>$510.00</td></tr>
        <tr><th scope="row"><strong class="block font-semibold">Photography art direction</strong><span class="block text-[.84rem] text-ci-muted">Half-day shoot at the roastery</span></th><td>1</td><td>$650.00</td><td>$650.00</td></tr>
      </tbody>
      <tfoot class="[&_:is(th,td)]:px-2 [&_:is(th,td)]:py-1.5 [&_:is(th,td)]:text-right [&_:is(th,td)]:font-normal [&_th]:text-ci-muted max-sm:[&_:is(th,td)]:px-1 print:[&_:is(th,td)]:py-[3px] [&>tr:first-child>*]:pt-4">
        <tr><th scope="row" colspan="3">Subtotal</th><td>$8,810.00</td></tr>
        <tr><th scope="row" colspan="3">Returning client discount (5%)</th><td>−$440.50</td></tr>
        <tr><th scope="row" colspan="3">Sales tax (7.5%)</th><td>$627.71</td></tr>
        <tr class="[&>*]:border-t-2 [&>*]:border-ci-ink [&>*]:pt-3! [&>*]:text-[1.1rem] [&>*]:font-extrabold! [&>*]:text-ci-ink!"><th scope="row" colspan="3">Total due (USD)</th><td>$8,997.21</td></tr>
      </tfoot>
    </table>
    <footer class="mt-9 grid grid-cols-[1.1fr_1fr] gap-x-10 gap-y-6 border-t border-ci-line pt-6 text-[.86rem] max-sm:grid-cols-1 print:mt-4 print:break-inside-avoid print:pt-3.5">
      <div><h3 class="mb-1.5 text-[.72rem] font-bold tracking-[.12em] text-ci-muted uppercase">Payment details</h3>
        <dl class="grid grid-cols-[auto_1fr] gap-x-[18px] gap-y-1 tabular-nums [&>dd]:font-medium [&>dt]:text-ci-muted"><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="mb-1.5 text-[.72rem] font-bold tracking-[.12em] text-ci-muted uppercase">Notes</h3>
        <p class="text-ci-muted">Please quote the invoice number with your payment. Balances unpaid after the due date accrue 1.5% per month. Questions: <a class="text-ci-accent underline focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-ci-accent print:text-inherit print:no-underline" href="mailto:[email protected]">[email protected]</a></p></div>
    </footer>
    <p class="mt-8 text-center font-[Georgia,'Times_New_Roman',serif] text-ci-accent italic print:mt-3">Thank you for your business.</p>
  </div>
</article>
</div>
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#56606e] uppercase print:hidden">Hourly timesheet invoice (prints on its own page)</span>
<article class="mx-auto max-w-[210mm] text-[14px] leading-normal text-ci-ink max-sm:text-[13px] print:max-w-none print:break-before-page print:text-[10pt] print:[print-color-adjust:exact]" aria-labelledby="ci2-title">
  <div class="mb-3.5 flex justify-end print:hidden"><button class="inline-flex cursor-pointer items-center gap-2 rounded-lg border border-ci-accent bg-ci-accent px-[18px] py-2.5 text-[.9rem] leading-none font-semibold text-white transition-colors duration-150 hover:bg-ci-accent-dark focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-ci-accent motion-reduce:transition-none" 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="border-t-[6px] border-ci-accent bg-white px-[60px] pt-14 pb-12 shadow-[0_1px_3px_rgba(28,37,51,.08),0_24px_48px_-28px_rgba(28,37,51,.4)] max-sm:px-[18px] max-sm:pt-7 max-sm:pb-[26px] print:border-t-4 print:px-0 print:pt-[6mm] print:pb-0 print:shadow-none">
    <header class="flex flex-wrap items-start justify-between gap-6 border-b border-ci-line pb-7 print:pb-4">
      <div class="flex items-start gap-3.5">
        <svg class="flex-none text-ci-accent" 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="text-[1.05rem] leading-[1.3] font-bold">Ines Varga</p>
          <address class="text-[.86rem] leading-[1.55] text-ci-muted not-italic">Freelance web development<br>9 Linden Court, Boise, ID 83702<br>[email protected]</address></div>
      </div>
      <div class="text-right max-sm:text-left"><h2 class="font-[Georgia,'Times_New_Roman',serif] text-[2.5rem] leading-none font-normal tracking-[.02em] text-ci-accent max-sm:text-[2rem] print:text-[28pt]" id="ci2-title">Invoice</h2><p class="mt-2 text-ci-muted tabular-nums">No. <b class="text-ci-ink">IV-0087</b></p></div>
    </header>
    <div class="grid grid-cols-2 gap-x-10 gap-y-6 py-7 max-sm:grid-cols-1 print:break-inside-avoid print:py-3.5">
      <div><h3 class="mb-1.5 text-[.72rem] font-bold tracking-[.12em] text-ci-muted uppercase">Billed to</h3>
        <address class="text-[.86rem] leading-[1.55] text-ci-muted not-italic"><strong class="block text-base text-ci-ink">Fernway Outdoor Supply</strong>Accounts payable<br>1180 Ridgeline Avenue<br>Bend, OR 97701</address></div>
      <div><h3 class="mb-1.5 text-[.72rem] font-bold tracking-[.12em] text-ci-muted uppercase">Details</h3>
        <dl class="grid grid-cols-[auto_1fr] gap-x-[18px] gap-y-1 tabular-nums [&>dd]:text-right [&>dd]:font-semibold [&>dt]:text-ci-muted">
          <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="mt-3 flex items-baseline justify-between gap-3 rounded-md bg-ci-soft px-3.5 py-3 tabular-nums"><dt>Balance due</dt><dd class="text-[1.2rem] font-extrabold text-ci-accent">$2,070.00</dd></dl></div>
    </div>
    <table class="w-full border-collapse tabular-nums [&_tbody_:is(th,td)]:border-b [&_tbody_:is(th,td)]:border-ci-line [&_tbody_:is(th,td)]:px-2 [&_tbody_:is(th,td)]:py-3.5 [&_tbody_:is(th,td)]:text-left [&_tbody_:is(th,td)]:align-top [&_tbody_:is(th,td)]:font-normal max-sm:[&_tbody_:is(th,td)]:px-1 print:[&_tbody_:is(th,td)]:py-[7px] [&_:is(th,td):first-child]:pl-0 [&_:is(th,td):last-child]:pr-0 [&_tbody_td]:text-right! [&_tbody_td]:whitespace-nowrap">
      <caption class="pb-2 text-left text-[.72rem] font-bold tracking-[.12em] text-ci-muted uppercase">Hours worked</caption>
      <thead class="[&_th]:border-b-2 [&_th]:border-ci-ink [&_th]:px-2 [&_th]:py-2.5 [&_th]:text-[.72rem] [&_th]:font-bold [&_th]:tracking-[.08em] [&_th]:text-ci-muted [&_th]:uppercase max-sm:[&_th]:px-1 max-sm:[&_th]:py-2 max-sm:[&_th]:text-[.66rem] max-sm:[&_th]:tracking-[.04em]"><tr><th scope="col" class="text-left">Date and task</th><th scope="col" class="text-right">Hours</th><th scope="col" class="text-right">Rate</th><th scope="col" class="text-right">Amount</th></tr></thead>
      <tbody>
        <tr><th scope="row"><strong class="block font-semibold">Checkout performance audit</strong><span class="block text-[.84rem] text-ci-muted">1 Oct 2026</span></th><td>3.50</td><td>$120.00</td><td>$420.00</td></tr>
        <tr><th scope="row"><strong class="block font-semibold">Product filter refactor</strong><span class="block text-[.84rem] text-ci-muted">3 Oct 2026</span></th><td>6.00</td><td>$120.00</td><td>$720.00</td></tr>
        <tr><th scope="row"><strong class="block font-semibold">Cart drawer accessibility fixes</strong><span class="block text-[.84rem] text-ci-muted">7 Oct 2026</span></th><td>4.25</td><td>$120.00</td><td>$510.00</td></tr>
        <tr><th scope="row"><strong class="block font-semibold">Deploy and uptime monitoring</strong><span class="block text-[.84rem] text-ci-muted">9 Oct 2026</span></th><td>2.00</td><td>$120.00</td><td>$240.00</td></tr>
        <tr><th scope="row"><strong class="block font-semibold">Code review and handover call</strong><span class="block text-[.84rem] text-ci-muted">14 Oct 2026</span></th><td>1.50</td><td>$120.00</td><td>$180.00</td></tr>
      </tbody>
      <tfoot class="[&_:is(th,td)]:px-2 [&_:is(th,td)]:py-1.5 [&_:is(th,td)]:text-right [&_:is(th,td)]:font-normal [&_th]:text-ci-muted max-sm:[&_:is(th,td)]:px-1 print:[&_:is(th,td)]:py-[3px] [&>tr:first-child>*]:pt-4">
        <tr><th scope="row" colspan="3">Total hours</th><td>17.25</td></tr>
        <tr class="[&>*]:border-t-2 [&>*]:border-ci-ink [&>*]:pt-3! [&>*]:text-[1.1rem] [&>*]:font-extrabold! [&>*]:text-ci-ink!"><th scope="row" colspan="3">Total due (USD)</th><td>$2,070.00</td></tr>
      </tfoot>
    </table>
    <footer class="mt-9 grid grid-cols-[1.1fr_1fr] gap-x-10 gap-y-6 border-t border-ci-line pt-6 text-[.86rem] max-sm:grid-cols-1 print:mt-4 print:break-inside-avoid print:pt-3.5">
      <div><h3 class="mb-1.5 text-[.72rem] font-bold tracking-[.12em] text-ci-muted uppercase">Payment details</h3>
        <dl class="grid grid-cols-[auto_1fr] gap-x-[18px] gap-y-1 tabular-nums [&>dd]:font-medium [&>dt]:text-ci-muted"><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="mb-1.5 text-[.72rem] font-bold tracking-[.12em] text-ci-muted uppercase">Notes</h3><p class="text-ci-muted">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
@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.