Weave 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

Php Autoprefixer Laravel Package

padaliyajay/php-autoprefixer

A PHP port of Autoprefixer that adds vendor prefixes to your CSS without Node.js or PostCSS. Write modern properties and let it handle browser compatibility, with support for custom browser lists and working from CSS files or strings.

Deep Wiki
Context7

Getting Started

Install it like any other Composer dependency — there is no Node toolchain, no PostCSS config, and no binary to compile:

composer require padaliyajay/php-autoprefixer

Where to look first

  1. vendor/padaliyajay/php-autoprefixer/README.md — the canonical usage example and the browser-targeting options for your pinned version.
  2. vendor/padaliyajay/php-autoprefixer/src/ — the Autoprefixer entry class plus the Compiler, Browser, Vendor, and Element\* handler classes. Read these before you assume a property is supported.
  3. The bundled browser/caniuse data file under src/ — this is what determines which prefixes get emitted. If a prefix is missing, check this data before you blame your CSS.

The minimal call

use Padaliyajay\PHPAutoprefixer\Autoprefixer;

$css = '.card { display: flex; user-select: none; }';

$autoprefixer = new Autoprefixer($css);
$autoprefixer->compile();

echo (string) $autoprefixer; // .card{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;...}

Your first real use case in Laravel

The natural entry point is not a per-request middleware — it's a build/deploy step. Create a one-off check in tinker or a throwaway route to confirm the output for your actual stylesheet:

Route::get('/_prefix-check', function () {
    return response(
        (string) (new \Padaliyajay\PHPAutoprefixer\Autoprefixer(
            file_get_contents(public_path('css/app.css'))
        ))->compile()
    )->header('Content-Type', 'text/css');
});

If that emits -webkit- / -ms- variants for your flexbox and user-select rules, you're ready to wire it into an Artisan command (below). Remove the route immediately afterward.

Implementation Patterns

1. Service container binding

Wrap the library so the rest of the app never touches it directly. This gives you one place to swap in PostCSS later and one place to control browser targets:

// app/Support/CssAutoprefixer.php
namespace App\Support;

use Padaliyajay\PHPAutoprefixer\Autoprefixer;

class CssAutoprefixer
{
    public function __construct(private array $browsers = []) {}

    public function prefix(string $css): string
    {
        $processor = new Autoprefixer($css);

        // Apply targets before compiling — see the README for the exact
        // setter name in your pinned version (set_browsers / setBrowsers).
        if ($this->browsers) {
            foreach ($this->browsers as $target) {
                // e.g. 'chrome 50', 'ie 11', 'safari 9'
                $processor->set_browser($target);
            }
        }

        $processor->compile();

        return (string) $processor;
    }
}
// app/Providers/AppServiceProvider.php
$this->app->singleton(\App\Support\CssAutoprefixer::class, fn () => new \App\Support\CssAutoprefixer(
    config('autoprefixer.browsers', [])
));

2. Artisan build command (the recommended default)

Treat autoprefixing as a deploy-time transformation of already-compiled CSS. Order matters: Sass/Less/Tailwind compile → autoprefix → minify → write to public/.

class PrefixCss extends Command
{
    protected $signature = 'css:prefix {--in=public/css/app.css} {--out=public/css/app.prefixed.css}';

    public function handle(CssAutoprefixer $prefixer)
    {
        $in  = base_path($this->option('in'));
        $out = base_path($this->option('out'));

        $prefixed = $prefixer->prefix(file_get_contents($in));

        file_put_contents($out, $prefixed);
        $this->info("Wrote {$out}");
    }
}

Then in your deploy script: php artisan css:prefix && php artisan css:minify. Do not chain this into composer install scripts unless you're comfortable with deploy-time filesystem writes.

3. Blade directive for inline/critical CSS

For above-the-fold CSS inlined into the layout, a directive keeps views tidy:

// AppServiceProvider::boot()
Blade::directive('autoprefix', function ($expression) {
    return "<?php echo app(\App\Support\CssAutoprefixer::class)->prefix($expression); ?>";
});
<style>@autoprefix($criticalCss)</style>

Because this runs at render time, pair it with a cache (next pattern) or restrict it to small, static critical-CSS strings.

4. Mail templates

Emails are the strongest argument for a PHP autoprefixer: mail clients are notoriously inconsistent and your CSS is often generated or inlined by PHP, outside any Vite pipeline. A view composer on your mail layouts is a clean hook:

View::composer('emails.*', function ($view) {
    $view->with('emailCss', app(CssAutoprefixer::class)->prefix(
        file_get_contents(resource_path('css/email.css'))
    ));
});

5. Cache the compiled result

Never prefix the same stylesheet twice per request. Key on file mtime plus the browser config hash, and store in storage/framework/cache:

$key = 'css.prefixed.' . md5_file($path) . '.' . md5(json_encode(config('autoprefixer.browsers')));

$css = Cache::rememberForever($key, fn () => $prefixer->prefix(file_get_contents($path)));

6. Configuration file

// config/autoprefixer.php
return [
    'browsers' => ['chrome 50', 'ie 11', 'safari 9', 'firefox 45'],
];

Keep this in version control so a CI run and a production deploy produce byte-identical CSS.

7. Testing

Golden-file tests are the only reliable way to catch regressions when you bump the package or the bundled browser data:

public function test_flexbox_gets_prefixed(): void
{
    $out = app(CssAutoprefixer::class)->prefix('.a { display: flex; }');

    $this->assertStringContainsString('-webkit-flex', $out);
    $this->assertStringContainsString('display: flex', $out);
}

Gotchas and Tips

  • It is not PostCSS Autoprefixer. The autoprefixer npm package parses CSS with PostCSS's full AST and has years of edge-case handling. This library is a pure-PHP approximation. Modern syntax — nesting, @layer, @container, complex :is()/:has() selectors, custom properties in shorthand positions — may be passed through unchanged, reordered, or (worst case) mangled. Run your entire stylesheet through it and diff before adopting.
  • Browser data is static. Targets come from a bundled caniuse snapshot, not browserslist in package.json. Your .browserslistrc, tailwind.config.js targets, and Vite's defaults are ignored. If you need a prefix the data doesn't know about, you must update the package or contribute the data.
  • Pick one pipeline. If you already run Vite/PostCSS, this package is redundant and will produce subtly different output depending on which step ran last. Use it only when there is genuinely no Node step: shared hosting, legacy PHP-only apps, PHP-generated CSS, or email templates.
  • Order of operations. Autoprefix after Sass/Less/Tailwind compilation, and before minification. Prefixing minified CSS is slower and harder to debug; minifying before prefixing can produce invalid output around at-rule handling.
  • compile() mutates; cast to string. compile() returns the object (or nothing) depending on version — always render via (string) $autoprefixer. Do not assume the constructor is enough.
  • Performance. It's a PHP parser walking every rule and declaration. On a 200 KB stylesheet it is noticeably slower than native tooling, and it allocates a lot of objects. Never call it inside a hot controller path or per-request middleware; always cache or precompile. Guard any endpoint that prefixes user-supplied CSS with a size limit.
  • No source maps. Prefixed output is a separate artifact with no mapping back to your sources. Generate it as a distinct *.prefixed.css file so browser DevTools line numbers still correspond to something.
  • Idempotency is not guaranteed. Running the output through the prefixer a second time can duplicate or reorder declarations, depending on the property. Make the build step run exactly once and assert on the artifact, not on re-processing.
  • It does not minify. Pair with matthiasmullie/minify or similar; the two compose cleanly since both are pure PHP.
  • Debugging a missing prefix. Drop down a level: inspect the Element\Declaration handler for that property, then check the browser data entry. More often than not the property simply has no handler, or your target list excludes every browser that needs the prefix.
  • Extension point. The Element\* handler classes are the intended seam for adding support for a property the library doesn't know. Subclass and register rather than patching vendor code — otherwise your next composer update erases the fix.
  • Version pinning and bus factor. MIT licensed, small community (~46 stars), but actively released (latest December 2025). Pin it in composer.json, commit your golden-file fixtures, and keep a note in your README on how to replace it with PostCSS if the project ever stalls.
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib