
Creating a Custom PDF Invoice in Laravel with DomPDF, Images, and CSS Styling
Let’s be real, exporting invoices as PDF is still a must-have feature in many business apps. Whether you’re building an e-commerce backend, a freelance project tracker, or a custom CRM, chances are you’ll eventually need to let users download clean, branded invoices.
In this guide, I’ll walk you through how to generate beautiful PDF invoices in Laravel using DomPDF, complete with images (like logos) and custom CSS styles no mess, no guesswork.
Why DomPDF?
Laravel has a handful of PDF generation options from Snappy to TCPDF to mPDF but DomPDF remains one of the most popular thanks to:
- Simplicity easy to integrate and use
- Blade view compatibility render your PDFs using regular Laravel Blade templates
- CSS + inline image support essential for making it look great
- Free & open-source
If you’re after full control over layout and branding without having to learn a whole new templating language, DomPDF fits the bill perfectly.
Step 1: Install DomPDF via Composer
Let’s start by pulling in the package via the trusted Laravel wrapper:
composer require barryvdh/laravel-dompdf
After installation, Laravel will auto-discover the service provider. But if you’re on an older version, you can add this manually in config/app.php
:
'providers' => [
Barryvdh\DomPDF\ServiceProvider::class,
],
'aliases' => [
'PDF' => Barryvdh\DomPDF\Facade\Pdf::class,
],
✅ Pro tip: You don’t need to publish the config file unless you need advanced tweaks.
Step 2: Create a Blade Template for Your Invoice
Here’s where it gets fun. Create a dedicated Blade file, e.g., resources/views/invoice.blade.php
.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Invoice</title>
<style>
body { font-family: sans-serif; font-size: 14px; }
.header { text-align: center; margin-bottom: 30px; }
.logo { width: 120px; }
.table { width: 100%; border-collapse: collapse; }
.table th, .table td { border: 1px solid #999; padding: 8px; }
.footer { text-align: center; margin-top: 30px; font-size: 12px; color: #666; }
</style>
</head>
<body>
<div class="header">
<img src="{{ public_path('images/logo.png') }}" class="logo">
<h2>Invoice #{{ $invoice->id }}</h2>
</div>
<table class="table">
<thead>
<tr>
<th>Item</th><th>Qty</th><th>Price</th><th>Total</th>
</tr>
</thead>
<tbody>
@foreach($invoice->items as $item)
<tr>
<td>{{ $item->name }}</td>
<td>{{ $item->qty }}</td>
<td>${{ number_format($item->price, 2) }}</td>
<td>${{ number_format($item->qty * $item->price, 2) }}</td>
</tr>
@endforeach
</tbody>
</table>
<div class="footer">
Thank you for your business!
</div>
</body>
</html>
📎 Notes:
- Use
public_path()
for images so DomPDF can find them. - Stick with inline CSS for best compatibility.
Step 3: Build the Controller to Generate the PDF
Now create a controller method to load the view and convert it to a PDF:
use Barryvdh\DomPDF\Facade\Pdf;
use App\Models\Invoice;
public function download($id)
{
$invoice = Invoice::with('items')->findOrFail($id);
$pdf = Pdf::loadView('invoice', compact('invoice'));
return $pdf->download("invoice-{$invoice->id}.pdf");
}
Simple and clean. You can also use ->stream()
if you want it to open in the browser instead.
Step 4: Add the Route
In routes/web.php
, register the route like so:
Route::get('/invoice/{id}/download', [InvoiceController::class, 'download']);
Now when you visit /invoice/123/download
, it will generate and download the invoice PDF on the fly.
Step 5: Polish the Look with CSS and Branding
Here’s what takes your PDF from “meh” to “wow”:
- Add your company logo, brand color palette, and typography.
- Use media queries only if necessary (DomPDF doesn’t support all).
- Avoid complex layouts keep it table-based.
- Test your PDF layout in multiple browsers (some fonts may render differently).
Common Pitfalls (And How to Fix Them)
Problem | Fix |
---|---|
Image not showing | Use public_path() or base64-encoded images |
CSS doesn’t apply | Use inline CSS and avoid @import or external stylesheets |
Fonts look wrong | Stick to safe fonts (Arial, sans-serif, etc.) |
Margins cut off | Add @page rules in <style> or tweak margins manually |
Optional: Save PDF to Storage Instead of Download
If you want to store the generated PDF for later, use:
Storage::put("invoices/invoice-{$invoice->id}.pdf", $pdf->output());
Then serve it via URL or attach it to email.
Final Thoughts
DomPDF and Laravel are a perfect match for generating lightweight, styled PDF invoices.
You can build something beautiful without leaving your Laravel comfort zone. Whether you’re making a billing system, e-commerce backend, or admin dashboard, exporting invoices becomes a breeze with this setup.
Just keep your Blade view simple, CSS inline, and assets local and you’re good to go.
Pro Tip:
If you need pixel-perfect PDF rendering or advanced layout features, consider switching to Browsershot or Snappy, but for 80% of use cases, DomPDF is more than enough.