eschmar/css-inliner-bundle
A Symfony Twig extension that inlines CSS into HTML emails using CssToInlineStyles. Wrap content in the cssinline tag and it converts style blocks into inline styles, then strips the originals—ideal for email templates.
This is a Symfony bundle, not a Laravel package. It ships a Twig tag ({% cssinline %}) that wraps tijsverkoyen/css-to-inline-styles. Laravel uses Blade, not Twig, and has no service provider auto-discovery for Symfony bundles. Day-to-day leverage in a Laravel app is therefore not direct — the bundle itself is essentially unusable without pulling in Twig and Symfony’s kernel.
Minimal steps for a Laravel developer:
eschmar/css-inliner-bundle. Install the underlying library instead:composer require tijsverkoyen/css-to-inline-styles<style> blocks, inline those rules into matching elements, strip the <style> tags.CssToInlineStyles before sending.If you insist on inspecting the bundle, look at its Twig extension class — it is a thin wrapper around CssToInlineStyles::convert($html). That one method call is the entire value proposition.
Because the bundle is Symfony-only, these patterns use the underlying CssToInlineStyles library directly inside Laravel.
Pattern 1 — Service wrapper (recommended)
Create a small service and bind it as a singleton:
namespace App\Services;
use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;
class CssInliner
{
public function inline(string $html): string
{
$inliner = new CssToInlineStyles();
$inliner->setCleanup(true);
$inliner->setStripOriginalStyleTags(true);
return $inliner->convert($html);
}
}
Pattern 2 — Mailable integration
Override build() and render manually before inlining:
public function build()
{
$html = view('emails.welcome', $this->data)->render();
$inlined = app(CssInliner::class)->inline($html);
return $this->html($inlined)->subject('Welcome');
}
Alternatively, listen to the MessageSending event and rewrite the body, but manual rendering is clearer.
Pattern 3 — Blade component
Mimic the Twig tag with a class component:
namespace App\View\Components;
use App\Services\CssInliner;
use Illuminate\View\Component;
class CssInline extends Component
{
public function render()
{
return function (array $data) {
return app(CssInliner::class)->inline($data['slot']);
};
}
}
Usage: <x-css-inline><style>...</style><p>...</p></x-css-inline>.
Pattern 4 — Blade directive (hacky)
Output buffering can work but is fragile with nested directives:
Blade::directive('cssinline', fn () => '<?php ob_start(); ?>');
Blade::directive('endcssinline', fn () => '<?php echo app(\App\Services\CssInliner::class)->inline(ob_get_clean()); ?>');
Prefer the component or service approach.
Integration tips
Cache::remember).CssToInlineStyles options in your own service.CssToInlineStyles handles simple selectors well but does not support media queries, pseudo-classes, or complex combinators. It may strip <style> tags entirely, losing responsive email styles. Test with real email clients (Gmail, Outlook).setCleanup(false) and inspect the before/after HTML. Log both versions during development.fedeisas/laravel-mail-css-inliner or spatie/laravel-mail-css-inliner (check maintenance status). They integrate with Laravel’s mailer and Blade directly, which is a far better day-to-day fit than a Symfony bundle.How can I help you explore Laravel packages today?