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.
Architecture fit
The headline finding is a framework mismatch: this is a Symfony bundle, not a Laravel package. There is no ServiceProvider, no config publishing, no facade, and nothing autodiscovered by Laravel. The bundle's entire contribution is a Twig token parser plus a Twig extension that wraps tijsverkoyen/css-to-inline-styles and inlines <style> blocks inside a {% cssinline %}…{% endcssinline %} tag. On a Laravel/Blade stack that tag does not exist and cannot be registered, so the package as shipped is not directly consumable.
The real value is one layer down: CssToInlineStyles is a mature, actively maintained library, and laravel/framework already pulls it in transitively for Illuminate\Mail\Markdown. Verification of composer.lock should be step one — in many Laravel applications the capability we want is already present with zero new dependencies.
Integration feasibility
Two viable paths:
@cssinline … @endcssinline) or an inline_css() helper backed by CssToInlineStyles. This is roughly 1–2 engineering days including tests, and removes the Symfony/Twig dependency entirely.Effort to adopt the bundle as-is is high relative to value; effort to replicate its behavior is low.
Technical risk
^5.0; Symfony 4/5 support lines are past or nearing end of life. PHP 8.2/8.3 compatibility of the bundle layer is unverified.@media query support, no CSS custom properties, imperfect specificity handling, external stylesheets not fetched. These are properties of the engine, not the wrapper, and they will surface as email-client rendering bugs.Key questions
Stack fit
Laravel 9–11 with Blade and laravel/framework already present is a good fit for the underlying library and a poor fit for the bundle. The correct target architecture is a thin internal abstraction — an CssInliner contract with a CssToInlineStyles-backed implementation — consumed by the mail layer. That keeps the inlining engine swappable and prevents bundle-specific concepts from leaking into application code.
Migration path
tijsverkoyen/css-to-inline-styles in composer.lock; if present, no new dependency is required.inline_css() helper behind the abstraction, with golden-file tests on template fixtures.composer.json.Compatibility
Confirm PHP 8.1+ support on the exact css-to-inline-styles constraint resolved in the lockfile. If the transitive version is old, promote it to a direct dependency at a current minor to control upgrades. Do not introduce symfony/twig-bridge or twig/twig into a Blade codebase — that is the single largest avoidable compatibility burden here.
Sequencing
Low priority and independently shippable. Slot it inside existing email work rather than as a standalone initiative: one sprint, one engineer, gated on the fidelity spike. It should not block any roadmap item and should not be scheduled ahead of mail deliverability or template-system work.
Maintenance
Near-zero if we consume the library directly — upgrades track tijsverkoyen/css-to-inline-styles. Non-trivial if we adopt the bundle: we inherit an unmaintained wrapper, and the realistic outcome is a fork we own, which converts a 2-day integration into an open-ended maintenance line item. The abstraction layer is the mitigation; budget the interface, not just the call site.
Support
No upstream support expectation. No issue triage, no CVE response, no release cadence. Internal ownership of the ~50 lines of glue must be explicit and assigned, not assumed.
Scaling
Inlining is CPU-bound HTML/CSS parsing per render. Cost is milliseconds for small templates and tens of milliseconds for large ones, which is acceptable for transactional mail volumes but wasteful for batch campaigns. Cache the inlined output keyed by template version plus locale; the result is deterministic for a given input. This is a rendering-tier concern, not an infrastructure one — no new services required.
Failure modes
Mitigation: golden-file tests on representative templates, a rendering diff in CI, and a documented list of unsupported CSS features for template authors.
Ramp-up
The public surface is a single tag or directive; a developer is productive in under an hour. The documentation is one page and adequate for what it covers. The genuine ramp-up cost is institutional knowledge about email-client quirks, which this package neither supplies nor solves.
How can I help you explore Laravel packages today?