Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cssinliner Extra Laravel Package

twig/cssinliner-extra

Twig extension adding the inline_css filter to inline CSS styles into HTML documents. Useful for rendering emails and templates with CSS applied directly to elements, improving compatibility with clients that strip or ignore external styles.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package

    composer require twig/cssinliner-extra
    

    For Laravel with TwigBridge:

    composer require twig/laravel
    
  2. Register the Extension In config/view.php (Laravel) or your Twig environment setup:

    Twig\Extension\CssInlinerExtraExtension::class,
    
  3. First Use Case Inline CSS for a static HTML template (e.g., resources/views/email/welcome.twig):

    {{ content|inline_css }}
    

    Or for a Blade template (via custom directive or Twig bridge):

    @twig({{ $html }}, inline_css)
    
  4. Verify Output Check the rendered HTML for inlined styles (no external <link> or <style> tags).


Implementation Patterns

Usage Patterns

  1. Static HTML Optimization Inline CSS for emails, marketing pages, or static site exports:

    {# resources/views/email/newsletter.twig #}
    {{ email_content|inline_css }}
    
  2. Dynamic Content with Caution Use for user-generated HTML (e.g., CMS content) but sanitize input first:

    {{ cms_content|inline_css(exclude=['.dynamic-class']) }}
    
  3. Conditional Inlining Skip inlining for non-critical pages (e.g., admin dashboards):

    {% if app.environment == 'production' %}
        {{ page_html|inline_css }}
    {% else %}
        {{ page_html }}
    {% endif %}
    
  4. Integration with Asset Pipelines Combine with Laravel Mix/Vite for hybrid workflows:

    // mix.js
    mix.postProcess('public/css', (cssFiles) => {
        return Promise.all(cssFiles.map(file => {
            return inlineCss(file.content); // Custom wrapper for twig/cssinliner-extra
        }));
    });
    

Workflows

  1. Email Optimization Workflow

    • Use Twig for email templates (e.g., resources/views/emails/welcome.twig).
    • Inline CSS during template rendering:
      {{ email_body|inline_css }}
      
    • Test with Email on Acid or Litmus.
  2. Marketing Page Optimization

    • Render Twig templates with inlined CSS:
      // routes/web.php
      Route::get('/marketing', function () {
          return view('marketing.landing', [
              'content' => file_get_contents('marketing-content.html'),
          ]);
      });
      
    • Template:
      {{ content|inline_css }}
      
  3. Headless CMS Export

    • Pre-process Twig templates during build:
      // console/commands/BuildStaticSite.php
      public function handle() {
          $html = $this->twig->render('templates/page.twig');
          $inlined = $this->twig->getFilter('inline_css')->filter($html);
          file_put_contents('dist/page.html', $inlined);
      }
      

Integration Tips

  1. Laravel Blade Compatibility Create a custom Blade directive for inline_css:

    // app/Providers/BladeServiceProvider.php
    Blade::directive('inlineCss', function ($expression) {
        return "<?php echo (new \\Twig\\Extension\\CssInlinerExtraExtension())->getInlineCssFilter()->filter($expression); ?>";
    });
    

    Usage:

    @inlineCss($html)
    
  2. Caching Inlined Output Cache results for static content (e.g., emails):

    // app/Services/EmailRenderer.php
    public function render($template, $data) {
        $cacheKey = md5($template . serialize($data));
        return Cache::remember($cacheKey, now()->addHours(1), function () use ($template, $data) {
            return $this->twig->render($template, $data);
        })->pipe(function ($html) {
            return $this->twig->getFilter('inline_css')->filter($html);
        });
    }
    
  3. Excluding Specific Elements Skip inlining for dynamic or third-party content:

    {{ content|inline_css(exclude=['.ad-banner', 'iframe']) }}
    
  4. Testing Inlined CSS Use PHPUnit to assert inlined styles:

    public function testCssInlining() {
        $html = '<div style="color:red">Hello</div>';
        $inlined = $this->twig->getFilter('inline_css')->filter($html);
        $this->assertStringNotContainsString('<style', $inlined);
        $this->assertStringContainsString('color:red', $inlined);
    }
    

Gotchas and Tips

Pitfalls

  1. DOM Extension Requirement

    • Error: FatalErrorException: Class 'DOMDocument' not found.
    • Fix: Enable the dom extension in php.ini:
      extension=dom
      
  2. Malformed HTML

    • Error: Twig\Error\RuntimeError: Failed to parse HTML.
    • Fix: Sanitize input with league/html-to-markup or DOMDocument::loadHTML():
      $dom = new DOMDocument();
      @$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
      $html = $dom->saveHTML();
      
  3. CSS Parsing Limits

    • Error: Allowed memory exhausted for large CSS files (>100KB).
    • Fix:
      • Pre-process CSS with PurgeCSS to reduce size.
      • Split inlining across multiple templates or use a queue system.
  4. Blade-Twig Interop Issues

    • Error: Twig\Error\SyntaxError when using in Blade.
    • Fix: Use a custom Blade directive (as shown above) or switch to Twig for critical templates.
  5. Dynamic Class Names

    • Issue: Inlined CSS may break if classes are dynamically generated (e.g., Tailwind).
    • Fix: Exclude dynamic selectors:
      {{ content|inline_css(exclude=['.[^a-z-]']) }}
      
  6. Media Query Inlining

    • Issue: Media queries (@media) are not inlined by default.
    • Workaround: Use a dedicated tool like grunt-css-inliner for advanced cases.
  7. Email Client Quirks

    • Issue: Some email clients (e.g., Gmail) strip or modify inlined CSS.
    • Fix: Test with Email on Acid and use MJML for complex emails.

Debugging

  1. Inspect Inlined Output Use Twig’s debug mode to see raw inlined HTML:

    {% set debugHtml = content|inline_css %}
    {{ dump(debugHtml) }}
    
  2. Log Parsing Errors Catch exceptions and log them:

    try {
        $inlined = $this->twig->getFilter('inline_css')->filter($html);
    } catch (\Exception $e) {
        \Log::error('CSS Inlining Failed: ' . $e->getMessage());
        $inlined = $html; // Fallback
    }
    
  3. Validate HTML Structure Use tidy to check HTML validity:

    tidy -e input.html
    

Configuration Quirks

  1. Twig Environment Setup Ensure the extension is registered after the Twig environment is built:

    $twig = new \Twig\Environment($loader);
    $twig->addExtension(new \Twig\Extension\CssInlinerExtraExtension());
    
  2. Laravel Caching Clear Twig cache after installing the package:

    php artisan view:clear
    
  3. Custom Filter Options Extend the filter for additional options (e.g., preserveMediaQueries):

    // app/Extensions/CustomCssInlinerExtension.php
    class CustomCssInlinerExtension extends \Twig\Extension\AbstractExtension {
        public function getFilters() {
            return [
                new \Twig\TwigFilter('custom_inline_css', [$this, 'inlineCss']),
            ];
        }
    
        public function inlineCss($html, array $options = []) {
            $inliner = new \Symfony\Component\CssInliner\CssInliner();
            return $inliner->inline($html, $options);
        }
    }
    

Extension Points

  1. Pre-Process CSS Hook into the inlining process to modify CSS before inlining:
    $css = $this->extractCss($html);
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky