sabberworm/php-css-parser
Parse and manipulate CSS in PHP with a fast, flexible parser. Convert CSS into an object model, inspect and edit rules, selectors, and declarations, then render back to CSS. Useful for minifying, rewriting assets, or building CSS tooling.
composer require sabberworm/php-css-parser
use Sabberworm\CSS\Parser;
$css = file_get_contents('styles.css');
$parser = new Parser($css);
$document = $parser->parse();
echo $document->render();
Parser, Document, RuleSet, and Rule classes.OutputFormat for customizing rendered CSS.Parsing and Modifying CSS:
$parser = new Parser($css);
$document = $parser->parse();
// Modify rules (e.g., add a prefix to all selectors)
foreach ($document->getAllDeclarationBlocks() as $block) {
foreach ($block->getSelectors() as $selector) {
$selector->setSelector('.prefix-' . $selector->getSelector());
}
}
// Output the modified CSS
echo $document->render();
Conditional Rule Removal:
foreach ($document->getAllRuleSets() as $ruleSet) {
$ruleSet->removeRule('font-'); // Removes all font-related rules
}
Dynamic Value Adjustment:
foreach ($document->getAllValues() as $value) {
if ($value instanceof \Sabberworm\CSS\Value\Size && !$value->isRelative()) {
$value->setSize($value->getSize() * 0.8); // Scale down sizes
}
}
$this->app->singleton(Parser::class, function () {
return new Parser(file_get_contents(storage_path('app/public/css/styles.css')));
});
public function handle($request, Closure $next) {
$document = app(Parser::class)->parse();
// Modify $document here...
$response = $next($request);
$response->headers->set('Content-Type', 'text/css');
return $response->setContent($document->render());
}
Blade::directive('processCss', function ($expression) {
$css = file_get_contents($expression);
$document = (new Parser($css))->parse();
// Modify $document...
return "<?php echo \$document->render(); ?>";
});
Usage in Blade:
<style>{{ @processCss('css/styles.css') }}</style>
Strict Parsing:
Settings::create()->beStrict()) will throw exceptions on invalid CSS. Useful for debugging but may break in production if CSS is user-generated.$parser = new Parser($css, Settings::create()->beStrict());
$document = $parser->parse(); // Throws on invalid CSS
Multibyte Support:
withMultibyteSupport(false)) speeds up parsing but may fail with non-ASCII characters. Only disable if you control the input CSS.$parser = new Parser($css, Settings::create()->withMultibyteSupport(false));
Selector Specificity:
Selector class does not compute specificity by default. Use third-party libraries (e.g., league/cssselector) if you need specificity calculations.Nested At-Rules:
@media @media) may not parse as expected. Flatten or simplify nested structures before parsing.var_dump($document) or print_r($document) to debug the parsed structure. The README provides a var_dump example for reference.Rule, Selector, etc.) include lineNumber properties. Useful for error messages:
foreach ($document->getAllRuleSets() as $ruleSet) {
foreach ($ruleSet->getRules() as $rule) {
if ($rule->getLineNumber() > 100) {
// Log or handle rules from specific lines
}
}
}
Custom Value Types:
Extend Value or ValueList to handle domain-specific CSS values (e.g., custom units or functions):
class CustomUnit extends \Sabberworm\CSS\Value\Size {
public function render() {
return $this->size . 'custom-unit';
}
}
Output Format Extensions:
Subclass OutputFormat to add custom formatting rules:
class CustomFormat extends \Sabberworm\CSS\OutputFormat {
public function renderRule($rule) {
// Custom logic for rendering rules
return parent::renderRule($rule);
}
}
Pre/Post-Processing Hooks: Use Laravel's service container to wrap the parser with custom logic:
$this->app->resolving(Parser::class, function ($parser, $app) {
$parser->setCss($app['custom.css.processor']->process($parser->getCss()));
});
Document object for multiple modifications:
$parser = new Parser($css);
$document = $parser->parse();
// Multiple modifications...
$document->render(); // Output once
getAllValues():
This method traverses the entire AST. Cache results if used repeatedly:
$values = $document->getAllValues(); // Expensive
// Store $values for later use
$cacheKey = 'css.styles';
$document = Cache::remember($cacheKey, now()->addHours(1), function () {
return (new Parser(file_get_contents('styles.css')))->parse();
});
// mix.js
const { Parser } = require('sabberworm/php-css-parser');
mix.process('styles.css', (content) => {
const parser = new Parser(content);
const document = parser.parse();
// Modify document...
return document.render();
});
How can I help you explore Laravel packages today?