Laravel Spatie PDF Package: Generate Invoice with Images and CSS

Generating PDF files is a common task in Laravel projects. The most popular PHP package is dompdf/dompdf. We have a tutorial using the DomPDF package, but it has limitations. Spatie has a modern package spatie/laravel-pdf, for generating PDF files with some features just for that. This tutorial will show how to generate a PDF file using that package.

This is a simple invoice we will be aiming for:


Generate Invoice From Blade View

To use this package, we need to install it via composer.

composer require spatie/laravel-pdf

Under the hood this package uses Browsershot to generate PDFs. You'll need to install the required dependencies for Browsershot to work. You can find the instructions here.

We will generate the PDF from a Blade View file, using the pdf() helper function. In your Controller, the code would look similar to the below:

use function Spatie\LaravelPdf\Support\pdf;
 
public function download() {
return pdf()
->view('pdf')
->name('invoice.pdf');
}

This code assumes that the PDF design is in HTML format in the resources/views/pdf.blade.php file.

We can also pass some data array to PDF and generate it. In this case, it's hard-coded, but in real projects it would probably come from the database.

Controller:

use function Spatie\LaravelPdf\Support\pdf;
 
public function download() {
$data = [
[
'quantity' => 1,
'description' => '1 Year Subscription',
'price' => '129.00'
]
];
 
return pdf()
->view('pdf', compact('data'))
->name('invoice.pdf');
}

And the View file should be a typical HTML/Blade template.

resources/views/pdf.blade.php:

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>PDF</title>
@vite(['resources/css/app.css'])
</head>
<body class="p-4">
<div class="flex justify-between">
<img src="{{ asset('laraveldaily.png') }}" alt="laravel daily" class="w-52" />
<h2 class="text-2xl font-bold">Invoice ID: 834847473</h2>
</div>
 
<div class="grid grid-cols-2 my-4">
<div>
<div class="font-bold">To:</div>
<div>John Doe</div>
<div>123 Acme Str.</div>
</div>
<div class="text-left">
<div class="font-bold">From:</div>
<div>Laravel Daily</div>
<div>London</div>
</div>
</div>
 
<table class="w-full bg-indigo-500">
<tr>
<th class="text-white p-1">Qty</th>
<th class="text-white p-1">Description</th>
<th class="text-white p-1">Price</th>
</tr>
<tr class="bg-slate-100">
@foreach($data as $item)
<td class="p-2">
{{ $item['quantity'] }}
</td>
<td class="p-2">
{{ $item['description'] }}
</td>
<td class="p-2">
{{ $item['price'] }}
</td>
@endforeach
</tr>
</table>
 
<div class="mt-2 text-right">
Total: $129.00 USD
</div>
 
<footer class="mt-6 p-4 bg-slate-100">
<div>Thank you</div>
<div>&copy; Laravel Daily</div>
</footer>
</body>
</html>

Notice: The logo image is placed in the /public directory and loaded in the PDF using the asset() Laravel helper to get the full URL to the image.

As you can see, in the View file, we use Tailwind CSS to style the PDF and Vite to compile styles. This allows the use of modern CSS styles. Of course, after every change, styles must be recompiled:

npm run dev
// or
npm run build

After downloading the PDF, we should see it appropriately styled:


Other Package Features

The spatie/laravel-pdf package has some features specifically for adding to PDF documents.

Besides streaming to the browser, you can force the download.

use function Spatie\LaravelPdf\Support\pdf;
 
public function download() {
$data = [
[
'quantity' => 1,
'description' => '1 Year Subscription',
'price' => '129.00'
]
];
 
return pdf()
->view('pdf', compact('data'))
->name('invoice.pdf')
->download();
}

With this package, you can format the PDF document like this:

  • Adding page number to the footer
  • Changing page orientation
  • Changing paper format

Default options can also be set in the boot() method of the Service Provider:

app/Providers/AppServiceProvider.php:

use Spatie\LaravelPdf\Facades\Pdf;
use Spatie\LaravelPdf\Enums\Format;
use Illuminate\Support\ServiceProvider;
 
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
Pdf::default()
->format(Format::A3);
}
}

For more, check the package official documentation.

I also have a YouTube video where I review this package.

No comments or questions yet...

Like our articles?

Become a Premium Member for $129/year or $29/month
What else you will get:
  • 78 courses
  • 95 long-form tutorials
  • access to project repositories
  • access to private Discord

Recent New Courses