Alternative to SelectPdf for Print

For my project I was looking for a simple way to print quotes. At first I tried different PDF plugins, but in the end I went with another approach: I generated an HTML/Tailwind template (with the help of ChatGPT), placed it on a separate page, and passed in the data type with all the information I needed.

In the workflow, I just open that page in a new window, and it gives me the result — no plugin required. The real challenge is getting the HTML template right, but once that’s done, it works well.

It’s a pretty basic solution, but it solved my problem and might help others who are trying to avoid plugins for this use case.

1 Like

Awesome! What’s the process you used? Do you have sample of the code you got from ChatGPT?

Sure, this was the original output.

paste it here - HTML Online Editor (Compiler, Interpreter & Runner)

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Invoice — Demo</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <style>
    /* Optional: keep nice print margins */
    @page { size: auto; margin: 18mm; }
  </style>
</head>
<body class="bg-gray-100 text-gray-900 antialiased">
  <main class="mx-auto my-8 max-w-3xl bg-white shadow-sm ring-1 ring-gray-200 print:shadow-none print:ring-0">
    <!-- Actions (hidden on print) -->
    <div class="flex items-center justify-end gap-2 px-6 py-3 border-b border-gray-200 print:hidden">
      <button onclick="window.print()" class="px-3 py-2 text-sm rounded-lg ring-1 ring-gray-300 hover:bg-gray-50">Print</button>
      <button id="downloadBtn" class="px-3 py-2 text-sm rounded-lg ring-1 ring-gray-300 hover:bg-gray-50">Download HTML</button>
    </div>

    <!-- Header -->
    <header class="px-6 py-6 border-b border-gray-200">
      <div class="flex items-start justify-between gap-6">
        <!-- Logo placeholder -->
        <div class="h-14 w-40 rounded-xl bg-gray-100 flex items-center justify-center text-xs uppercase tracking-widest text-gray-500">Logo</div>

        <div class="text-right">
          <h1 class="text-2xl font-semibold tracking-tight">INVOICE</h1>
          <p class="mt-1 text-sm text-gray-500"># INV-002718</p>
        </div>
      </div>

      <div class="mt-6 grid grid-cols-1 sm:grid-cols-3 gap-6 text-sm">
        <div>
          <p class="uppercase tracking-wider text-gray-500">From</p>
          <p class="mt-1 font-medium">Demo Company LLC</p>
          <p>123 Market Street</p>
          <p>Austin, TX 78701</p>
          <p>support@democo.test</p>
          <p>+1 (512) 555-0199</p>
        </div>
        <div>
          <p class="uppercase tracking-wider text-gray-500">Bill To</p>
          <p class="mt-1 font-medium">Acme Industries</p>
          <p>Attn: Jane Doe</p>
          <p>88 Industrial Way</p>
          <p>San Francisco, CA 94105</p>
          <p>billing@acme.test</p>
        </div>
        <div>
          <dl class="grid grid-cols-2 gap-x-3 gap-y-2">
            <dt class="text-gray-500">Invoice Date</dt>
            <dd class="text-right">Sep 13, 2025</dd>
            <dt class="text-gray-500">Due Date</dt>
            <dd class="text-right">Sep 27, 2025</dd>
            <dt class="text-gray-500">Terms</dt>
            <dd class="text-right">Net 14</dd>
            <dt class="text-gray-500">PO #</dt>
            <dd class="text-right">PO-8941</dd>
          </dl>
        </div>
      </div>
    </header>

    <!-- Line Items -->
    <section class="px-6 py-6">
      <div class="overflow-hidden rounded-lg ring-1 ring-gray-200">
        <table class="min-w-full divide-y divide-gray-200 text-sm">
          <thead class="bg-gray-50">
            <tr>
              <th scope="col" class="px-4 py-3 text-left font-medium text-gray-600">Item</th>
              <th scope="col" class="px-4 py-3 text-right font-medium text-gray-600">Qty</th>
              <th scope="col" class="px-4 py-3 text-right font-medium text-gray-600">Rate</th>
              <th scope="col" class="px-4 py-3 text-right font-medium text-gray-600">Tax</th>
              <th scope="col" class="px-4 py-3 text-right font-medium text-gray-600">Line Total</th>
            </tr>
          </thead>
          <tbody class="divide-y divide-gray-100">
            <tr>
              <td class="px-4 py-3 align-top">
                <p class="font-medium">Discovery & Planning</p>
                <p class="text-gray-500">Initial workshops, requirements, and timeline definition.</p>
              </td>
              <td class="px-4 py-3 text-right align-top">1</td>
              <td class="px-4 py-3 text-right align-top">$1,500.00</td>
              <td class="px-4 py-3 text-right align-top">$0.00</td>
              <td class="px-4 py-3 text-right align-top">$1,500.00</td>
            </tr>
            <tr>
              <td class="px-4 py-3 align-top">
                <p class="font-medium">Design & Prototyping</p>
                <p class="text-gray-500">UI kit, wireframes, and interactive prototype.</p>
              </td>
              <td class="px-4 py-3 text-right align-top">12</td>
              <td class="px-4 py-3 text-right align-top">$85.00</td>
              <td class="px-4 py-3 text-right align-top">$97.20</td>
              <td class="px-4 py-3 text-right align-top">$1,117.20</td>
            </tr>
            <tr>
              <td class="px-4 py-3 align-top">
                <p class="font-medium">Development Sprint</p>
                <p class="text-gray-500">Backend integrations and core features.</p>
              </td>
              <td class="px-4 py-3 text-right align-top">40</td>
              <td class="px-4 py-3 text-right align-top">$95.00</td>
              <td class="px-4 py-3 text-right align-top">$456.00</td>
              <td class="px-4 py-3 text-right align-top">$4,256.00</td>
            </tr>
            <tr>
              <td class="px-4 py-3 align-top">
                <p class="font-medium">Quality Assurance</p>
                <p class="text-gray-500">Test plan, regression, and UAT support.</p>
              </td>
              <td class="px-4 py-3 text-right align-top">10</td>
              <td class="px-4 py-3 text-right align-top">$70.00</td>
              <td class="px-4 py-3 text-right align-top">$56.00</td>
              <td class="px-4 py-3 text-right align-top">$756.00</td>
            </tr>
          </tbody>
        </table>
      </div>

      <!-- Totals -->
      <div class="mt-6 grid grid-cols-1 sm:grid-cols-2 gap-6">
        <div>
          <div class="grid grid-cols-[auto,1fr] gap-x-3 gap-y-2 text-sm">
            <span class="text-gray-500">Payment Method</span>
            <span>Bank Transfer (ACH)</span>
            <span class="text-gray-500">Account</span>
            <span>Demo Bank • **** 4321</span>
            <span class="text-gray-500">Reference</span>
            <span>INV-002718</span>
          </div>
          <div class="mt-4">
            <p class="uppercase tracking-wider text-gray-500 text-xs">Notes</p>
            <p class="text-sm">Thank you for your business. Please include the invoice number with your payment.</p>
          </div>
          <div class="mt-3">
            <p class="uppercase tracking-wider text-gray-500 text-xs">Terms</p>
            <p class="text-sm">Payment due within 14 days. Late payments may incur a 1.5% monthly fee.</p>
          </div>
        </div>
        <div class="sm:justify-self-end w-full sm:w-80">
          <div class="rounded-lg ring-1 ring-gray-200 overflow-hidden">
            <dl class="divide-y divide-gray-200 text-sm">
              <div class="flex items-center justify-between px-4 py-3">
                <dt class="text-gray-600">Subtotal</dt>
                <dd class="font-medium">$7,629.20</dd>
              </div>
              <div class="flex items-center justify-between px-4 py-3">
                <dt class="text-gray-600">Discount</dt>
                <dd class="font-medium">-$250.00</dd>
              </div>
              <div class="flex items-center justify-between px-4 py-3">
                <dt class="text-gray-600">Tax</dt>
                <dd class="font-medium">$609.20</dd>
              </div>
              <div class="flex items-center justify-between px-4 py-3">
                <dt class="text-gray-900">Total</dt>
                <dd class="text-lg font-semibold">$7,988.40</dd>
              </div>
              <div class="flex items-center justify-between px-4 py-3 bg-gray-50">
                <dt class="text-gray-600">Amount Paid</dt>
                <dd class="font-medium">$0.00</dd>
              </div>
              <div class="flex items-center justify-between px-4 py-3 bg-gray-50">
                <dt class="text-gray-900">Balance Due</dt>
                <dd class="text-lg font-semibold">$7,988.40</dd>
              </div>
            </dl>
          </div>
          <div class="mt-4 flex items-center gap-3 text-xs text-gray-500">
            <div class="h-14 w-14 rounded bg-gray-100 flex items-center justify-center">QR</div>
            <p>Scan to view invoice online.</p>
          </div>
        </div>
      </div>
    </section>

    <!-- Acceptance (optional) -->
    <section class="px-6 pb-6">
      <div class="mt-4 rounded-lg ring-1 ring-gray-200 p-4 text-sm">
        <p class="mb-3 text-gray-700">Acceptance</p>
        <div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
          <div>
            <label class="block text-gray-500 text-xs">Authorized Name</label>
            <div class="mt-1 h-9 rounded-md ring-1 ring-gray-200"></div>
          </div>
          <div>
            <label class="block text-gray-500 text-xs">Signature</label>
            <div class="mt-1 h-9 rounded-md ring-1 ring-gray-200"></div>
          </div>
        </div>
        <div class="mt-3 grid grid-cols-1 sm:grid-cols-3 gap-4">
          <div>
            <label class="block text-gray-500 text-xs">Title</label>
            <div class="mt-1 h-9 rounded-md ring-1 ring-gray-200"></div>
          </div>
          <div>
            <label class="block text-gray-500 text-xs">Date</label>
            <div class="mt-1 h-9 rounded-md ring-1 ring-gray-200"></div>
          </div>
          <div>
            <label class="block text-gray-500 text-xs">Email</label>
            <div class="mt-1 h-9 rounded-md ring-1 ring-gray-200"></div>
          </div>
        </div>
      </div>
    </section>

    <!-- Footer -->
    <footer class="px-6 py-6 border-t border-gray-200 text-center text-sm text-gray-500">
      <p>www.example-website.test</p>
    </footer>
  </main>

  <script>
    // Simple HTML download (current document) for convenience
    document.getElementById('downloadBtn')?.addEventListener('click', () => {
      const blob = new Blob([document.documentElement.outerHTML], { type: 'text/html' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'invoice-demo.html';
      a.click();
      URL.revokeObjectURL(url);
    });
  </script>
</body>
</html>

Thank you. I put it into an HTML element on the page and it looks great!

Cool. Kind of like a movie set.