twig/html-extra
Twig extension adding data_uri, html_classes, and html_cva filters/functions for generating RFC 2397 data URLs, conditionally joining class names, and managing class variants with Cva objects.
data_uri (RFC 2397 inline assets), html_classes (conditional class joining), html_cva (class-variant objects for component styling), and html_attr (ergonomic HTML attribute output). v3.29.0 adds a fifth, lower-level primitive: htmlAttrValue() (see below), which nudges this from "four conveniences" toward "a thin, composable attribute layer."twig/laravel). In a Blade-first Laravel app, the same outcomes are largely covered by Blade's @class, @style, and component attributes — so this is a "do not adopt" signal, not a feature gap.html_cva gives you a typed, template-side variant API (size, intent, state) instead of scattered ternaries. That is a real lever for design-system consistency and for onboarding designers into templates. New in v3.29.0: htmlAttrValue() exposes attribute value rendering separately from full tag output, which lets component partials assemble attribute fragments (a style string here, a class string there) and hand them to a parent tag — a small but real enabler for layered component composition rather than monolithic attribute blobs.data_uri is the strongest standalone use case — email clients strip external assets, so inline base64 icons/logos materially improve email rendering fidelity without a build-step dependency.html_classes supports conditional UI states (dark mode, A/B cohorts, entitlement-driven styling) at the template layer rather than in PHP/JS, which shortens the loop between flag definition and visible UI change.html_attr silently dropped style declarations whose value is 0 (e.g. margin: 0, border-radius: 0, opacity: 0). This is the kind of defect that produces "why does this card have unexpected spacing in Twig but not in the styleguide?" tickets. It is now fixed, but it sets a floor: if you adopt html_attr, pin to >= 3.29.0 and treat pre-3.29 output as untrustworthy for zero-valued styles.Adopt if:
twig/laravel, Symfony, or standalone Twig 3.x).html_cva) and conditional classes (html_classes) recur across dozens of templates.data_uri) for email templates or small icon sets where an extra HTTP request is undesirable.htmlAttrValue() you can produce attribute values in one partial and render them in another, instead of duplicating string-concatenation logic across components.Look elsewhere if:
@class/@style directives and anonymous components cover the majority of the value; adopting Twig purely to get these helpers is a net negative in migration cost, hiring, and tooling.html_cva is string assembly, not a styling engine.htmlAttrValue() does not change that.Validation caveats a PM should weigh:
twigphp package with a real, ongoing release cadence (v3.24.0 → v3.28.0 → v3.29.0), so abandonment risk is lower than the raw numbers suggest — but it is not zero, and it is not a "safe default" you can assume review boards will wave through. The v3.29.0 bug fix supports the stewardship argument: a non-maintained package would not have caught a zero-value style edge case.html_attr can silently drop 0-valued style declarations. Any spike or benchmark run on an older version should be discarded and re-baselined on 3.29.0, or you will under- or mis-read the helper's fitness for style-heavy components.htmlAttrValue() is a public API surface with one release behind it; assume minor churn and avoid spreading it across every component in the first pass.For executives (30 seconds):
"This is a small, free, officially maintained add-on for Twig, the templating engine. It gives our frontend team ready-made helpers for repetitive HTML chores — merging CSS classes conditionally, generating style variants for buttons and cards, embedding small images directly in the page or in emails, and now assembling HTML attribute fragments for reusable components. The value is speed and consistency in our component library, not new capability. The newest release also fixed a subtle bug where certain style values (things like margin: 0) were being silently dropped — a good sign that the project is actively maintained, but also a reason to pin a minimum version. The catch remains: it only pays off if we're already using Twig. If we stay on Blade, we should skip it and use Blade's built-in equivalents. My recommendation is unchanged: a one-sprint spike on a single component before any broader commitment."
For engineering:
"It's still a small, MIT, no-Laravel-coupling Twig extension registered in config/twig.php. Core API unchanged: data_uri (RFC 2397 inline assets — the real win for email), html_classes (safe conditional class joining), html_cva (immutable variant objects), html_attr (attribute output). v3.29.0 brings two things that matter to us: (1) a fix for html_attr dropping style declarations with a 0 value — so pin >= 3.29.0, and re-run any earlier spike results, because that bug would have made html_attr look worse or better than it is depending on the component; (2) htmlAttrValue() extracted from html_attr, letting us render attribute values standalone and compose attribute fragments across partials instead of concatenating strings by hand. It's a nice-to-have, not a reason to adopt — one release of API history, so keep usage narrow initially. No service-container pollution, no runtime I/O, renders at normal view speed. Asks before commit: (1) confirm the twig/laravel bridge is healthy on our Laravel version, (2) lint templates in CI — a Twig syntax error is a 500 in prod, (3) add a regression fixture asserting style="margin: 0" survives rendering, so we don't re-introduce that class of bug through our own wrapping. html_cva still overlaps with Tailwind/PostCSS; I want to prove it removes code rather than adding a second styling idiom."
Ask / decision requested: unchanged — a timeboxed spike on one variant-heavy component, with an explicit exit criterion: reduce that component's template complexity without introducing a parallel styling convention. Add one condition: run the spike on v3.29.0+ and include a zero-value-style regression case. If Twig isn't already in the stack, the answer is still no, and the money is better spent on Blade component hygiene.
How can I help you explore Laravel packages today?