This library implements a CSS tokenizer, parser and grammar matcher in PHP.
use Wikimedia\CSS\Parser\Parser; use Wikimedia\CSS\Sanitizer\StylesheetSanitizer; /** Parse a stylesheet from a string **/ $parser = Parser::newFromString( $cssText ); $stylesheet = $parser->parseStylesheet(); /** Report any parser errors **/ foreach ( $parser->getParseErrors() as list( $code, $line, $pos ) ) { // $code is a string that should be suitable as a key for an i18n library. // See errors.md for details. $error = lookupI18nMessage( "css-parse-error-$code" ); echo "Parse error: $error at line $line character $pos\n"; } /** Apply sanitization to the stylesheet **/ // If you need to customize the defaults, copy the code of this method and // modify it. $sanitizer = StylesheetSanitizer::newDefault(); $newStylesheet = $sanitizer->sanitize( $stylesheet ); /** Report any sanitizer errors **/ foreach ( $sanitizer->getSanitizationErrors() as list( $code, $line, $pos ) ) { // $code is a string that should be suitable as a key for an i18n library. // See errors.md for details. $error = lookupI18nMessage( "css-sanitization-error-$code" ); echo "Sanitization error: $error at line $line character $pos\n"; } /** Convert the sanitized stylesheet back to text **/ $newText = (string)$newStylesheet; // Or if you'd rather have it minified too $minifiedText = Wikimedia\CSS\Util::stringify( $newStylesheet, [ 'minify' => true ] );The library follows the following grammar specifications:
- CSS Syntax Level 3, 2019-07-16
- CSS Values and Units Module Level 4, 2024-03-12
- CSS Selectors Level 3, 2018-11-06
The sanitizer recognizes the following CSS modules:
- Align Level 3, 2025-03-11
- Animations Level 1, 2023-03-02
- Backgrounds Level 3, 2024-03-11
- Break Level 3, 2018-12-04
- Cascade Level 4, 2022-01-13
- Color Level 4, 2025-04-24
- Compositing Level 1, 2024-03-21
- Counter Styles Level 3, 2021-07-27
- CSS Level 2, 2011-06-07
- Display Level 3, 2023-03-30
- Easing Level 1, 2023-02-13
- Filter Effects Level 1, 2018-12-18
- Flexbox Level 1, 2018-11-19
- Fonts Level 3, 2018-09-20
- Grid Level 1, 2025-03-26
- Images Level 3, 2023-12-18
- Lists and Counters Level 3, 2020-11-17
- Logical Properties and Values Level 1, 2018-08-27
- Masking Level 1, 2021-08-05
- Multicol Level 1, 2019-10-15
- Overflow Level 3, 2023-03-29
- Overflow Level 4, 2023-03-21
- Page Level 3, 2023-09-14
- Position Level 3, 2025-03-11
- Pseudo-Elements Level 4, 2022-12-30
- Ruby Level 1, 2022-12-31
- Scroll Snap Module Level 1
- Shapes Level 1, 2022-11-15
- Sizing Level 3, 2021-12-17
- Sizing Level 4, 2025-02-24
- Text Level 3, 2024-09-30
- Text Decorations Level 3, 2022-05-05
- Transforms Level 1, 2019-02-14
- Transforms Level 2, 2021-11-09
- Transitions Level 1, 2018-10-11
- UI 3 Level 3, 2018-06-21
- UI 4 Level 4, 2021-03-16
- Writing Modes Level 4, 2019-07-30
And also,
- The
touch-actionproperty from Pointer Events Level 2, 2019-04-04 :dir()pseudo-class from Selectors Level 4, 2022-11-11- Accessibility related media features from Media Queries Level 5 including prefers-reduced-motion, prefers-reduced-transparency, prefers-contrast and forced-colors.
light-dark()color function from Color Module Level 5, 2024-02-29
composer install --prefer-dist composer test CSS specifications typically contain a summary of value grammars in the property index section. These value grammars map directly to PHP code.
| Syntax | css-sanitizer code |
|---|---|
foo | new KeywordMatcher( 'foo' ) |
foo | bar | new KeywordMatcher( [ 'foo', 'bar' ] ) |
<string> | $matcherFactory->string() |
<url> | $matcherFactory->url() |
<integer> | $matcherFactory->integer() |
<number> | $matcherFactory->number() |
<ratio> | $matcherFactory->ratio() |
<percentage> | $matcherFactory->percentage() |
<length> | $matcherFactory->length() |
<frequency> | $matcherFactory->frequency() |
<angle> | $matcherFactory->angle() |
<time> | $matcherFactory->time() |
<resolution> | $matcherFactory->resolution() |
| Syntax | css-sanitizer code |
|---|---|
a b | new Juxtaposition( [ a, b ] ) |
a && b | UnorderedGroup::allOf( [ a, b ] ) |
a || b | UnorderedGroup::someOf( [ a, b ] ) |
a | b | new Alternative( [ a, b ] ) |
| Syntax | css-sanitizer code |
|---|---|
a* | Quantifier::star( a ) |
a+ | Quantifier::plus( a ) |
a? | Quantifier::optional( a ) |
a{3,4} | Quantifier::count( a, 3, 4 ) |
a# | Quantifier::hash( a ) |
a! | new NonEmpty( a ) |
This package uses wikimedia/update-history and its conventions.
See https://www.mediawiki.org/wiki/UpdateHistory for details.
We required a CSS sanitizer with several properties:
- Strict parsing according to modern standards.
- Includes line and character position for all errors.
- Configurable to limit unsafe constructs such as external URL references.
- Errors are easily localizable.
We could not find a library that fit these requirements, so we created one.
Additional release history is in HISTORY.md.