For a slider Gutenberg block, I added the option to enter custom CSS into a text field, that should only apply to that one block. Of course, the user should not need to write the selector that way, that it only applies to this specific block – that should be done in the background before rendering the frontend markup.
To get this done, I searched for a PHP solution for PHP parsing and found the right tool with PHP CSS Parser.
Installation of the tool is done via composer:
Code language: Bash (bash)composer require sabberworm/php-css-parser
To modify all selectors in a set of CSS rules in that way, that a unique class name is added in front, only a few lines are necessary. Lucky me, there was an example for that right there in the readme on GitHub (the CSS string exists in $attributes['customCss']
in the following code:
<?php
use Sabberworm\CSS\Parser;
// Generate unique classname.
$unique_block_classname = 'slider_' . bin2hex( random_bytes( 6 ) );
$css_parser = new Parser( $attributes['customCss'] );
$css_document = $css_parser->parse();
// Loop CSS declaration blocks and add classname to selectors.
foreach ( $css_document->getAllDeclarationBlocks() as $declaration_block ) {
foreach ( $declaration_block->getSelectors() as $selector ) {
$selector->setSelector( ".$unique_block_classname" .' '. $selector->getSelector() );
}
}
// Save modified CSS.
$custom_css = $css_document->render();
Code language: PHP (php)
First, we generate an unique class name and parse the CSS with the parse()
method of the Parser
class. Next, we loop over the declarations and inside the declarations over the selectors, to prepend every selector with the generated class:
$selector->setSelector( ".$unique_block_classname" .' '. $selector->getSelector() );
Code language: PHP (php)
With $css_document->render()
we store the modified CSS in the $custom_css
variable in the end.