emiliolodigiani / laravel-images
Responsive image resizing with srcset generation for Laravel
Requires
- php: ^8.3
- illuminate/support: ^11.0|^12.0|^13.0
- intervention/image: ^3.0
Requires (Dev)
- orchestra/testbench: ^9.0|^10.0|^11.0
- pestphp/pest: ^3.0|^4.0
README
Responsive image resizing with srcset generation for Laravel.
Automatically resizes images to multiple WebP variants and generates <img> tags with srcset for optimal loading. Configurable image sources allow each project to define its own directories and URL structure.
Installation
composer require emiliolodigiani/laravel-images
Publish the config file:
php artisan vendor:publish --tag=images-config
Configuration
Define your image sources in config/images.php:
return [ 'quality' => 80, 'widths' => [400, 800, 1200, 1920, 2500], 'sources' => [ 'default' => [ 'originals' => public_path('images'), 'originals_url' => '/images', 'sizes' => public_path('images/sizes'), 'url' => '/images/sizes/{width}', ], // Add more sources as needed: 'blog' => [ 'originals' => storage_path('app/public/blog'), 'originals_url' => '/storage/blog', 'sizes' => storage_path('app/public/blog-sizes'), 'url' => '/storage/blog-sizes/{width}', ], ], ];
Each source defines:
- originals — absolute path to the directory with original images
- originals_url — public URL prefix for originals (used as fallback when no resized versions exist)
- sizes — absolute path where resized versions are stored (subdirectories per width)
- url — public URL pattern for srcset (
{width}is replaced with the actual value)
Usage
Blade component
<x-img src="photo.webp" alt="A photo" /> <x-img src="photo.webp" alt="A photo" sizes="(min-width: 768px) 50vw, 100vw" /> <x-img src="photo.webp" alt="A photo" source="guides" />
The component outputs an <img> tag with srcset and sizes attributes. If no resized versions exist, it falls back to the original.
HTML body helper
For rich text content with embedded <img> tags:
{!! responsive_images($model->body) !!}
This transforms all <img> tags in the HTML to responsive versions with srcset, sizes, and loading="lazy".
Resize after upload
The package does not handle file storage — your app saves files using Laravel's filesystem (Storage, Livewire storeAs(), controller store(), etc.). After saving, call ImageResizer::resize() with the absolute path to generate all resized versions.
The resize() method automatically detects which configured source the file belongs to based on its path.
use EmilioLodigiani\LaravelImages\ImageResizer; // Livewire component $this->photo->storeAs('', $filename, 'my-disk'); ImageResizer::resize(storage_path('app/public/photos/' . $filename)); // Controller $request->file('image')->store('photos', 'public'); ImageResizer::resize(storage_path('app/public/photos/' . $filename)); // Downloaded from URL (e.g. MCP tool) file_put_contents($path, Http::get($url)->body()); ImageResizer::resize($path);
Deleting images
Use ImageResizer::delete() to remove an image and all its resized versions:
ImageResizer::delete('photo.jpg', 'default');
Batch resize
Generate missing resized versions for all configured sources:
php artisan images:resize
Programmatic access
use EmilioLodigiani\LaravelImages\ImageResizer; // Get available widths for an image $widths = ImageResizer::availableWidths('photo', 'default'); // [400, 800, 1200, 1920] // Get the public URL for a specific size $url = ImageResizer::url('photo', 800, 'default'); // /images/sizes/800/photo.webp
How it works
- When an image is resized, WebP versions are generated for each configured width that is smaller than the original
- Images are scaled by their longer side (portrait images scale by height, not width)
- A PHP manifest file at
storage/framework/image-sizes.phptracks which sizes exist for fast lookup (no database queries) - The manifest is automatically updated after each resize operation and OPcache-invalidated for zero-downtime deploys
Customizing the view
Publish the Blade view to customize the <img> output:
php artisan vendor:publish --tag=images-views
The view will be at resources/views/vendor/laravel-images/components/img.blade.php.
Requirements
- PHP 8.2+
- Laravel 11 or 12
- Intervention Image 3 (GD driver)
License
MIT