Title: safecss_filter_attr
Published: April 25, 2014
Last modified: February 24, 2026

---

# safecss_filter_attr( string $css, string $deprecated ): string

## In this article

 * [Parameters](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#source)
 * [Hooks](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#hooks)
 * [Related](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#changelog)
 * [User Contributed Notes](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#user-contributed-notes)

[ Back to top](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#wp--skip-link--target)

Filters an inline style attribute and removes disallowed rules.

## 󠀁[Parameters](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#parameters)󠁿

 `$css`stringrequired

A string of CSS rules.

`$deprecated`stringrequired

Not used.

## 󠀁[Return](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#return)󠁿

 string Filtered string of CSS rules.

## 󠀁[Source](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#source)󠁿

    ```php
    function safecss_filter_attr( $css, $deprecated = '' ) {
    	if ( ! empty( $deprecated ) ) {
    		_deprecated_argument( __FUNCTION__, '2.8.1' ); // Never implemented.
    	}

    	$css = wp_kses_no_null( $css );
    	$css = str_replace( array( "\n", "\r", "\t" ), '', $css );

    	$allowed_protocols = wp_allowed_protocols();

    	$css_array = explode( ';', trim( $css ) );

    	/**
    	 * Filters the list of allowed CSS attributes.
    	 *
    	 * @since 2.8.1
    	 *
    	 * @param string[] $attr Array of allowed CSS attributes.
    	 */
    	$allowed_attr = apply_filters(
    		'safe_style_css',
    		array(
    			'background',
    			'background-color',
    			'background-image',
    			'background-position',
    			'background-repeat',
    			'background-size',
    			'background-attachment',
    			'background-blend-mode',

    			'border',
    			'border-radius',
    			'border-width',
    			'border-color',
    			'border-style',
    			'border-right',
    			'border-right-color',
    			'border-right-style',
    			'border-right-width',
    			'border-bottom',
    			'border-bottom-color',
    			'border-bottom-left-radius',
    			'border-bottom-right-radius',
    			'border-bottom-style',
    			'border-bottom-width',
    			'border-bottom-right-radius',
    			'border-bottom-left-radius',
    			'border-left',
    			'border-left-color',
    			'border-left-style',
    			'border-left-width',
    			'border-top',
    			'border-top-color',
    			'border-top-left-radius',
    			'border-top-right-radius',
    			'border-top-style',
    			'border-top-width',
    			'border-top-left-radius',
    			'border-top-right-radius',

    			'border-spacing',
    			'border-collapse',
    			'caption-side',

    			'columns',
    			'column-count',
    			'column-fill',
    			'column-gap',
    			'column-rule',
    			'column-span',
    			'column-width',

    			'color',
    			'filter',
    			'font',
    			'font-family',
    			'font-size',
    			'font-style',
    			'font-variant',
    			'font-weight',
    			'letter-spacing',
    			'line-height',
    			'text-align',
    			'text-decoration',
    			'text-indent',
    			'text-transform',
    			'white-space',

    			'height',
    			'min-height',
    			'max-height',

    			'width',
    			'min-width',
    			'max-width',

    			'margin',
    			'margin-right',
    			'margin-bottom',
    			'margin-left',
    			'margin-top',
    			'margin-block-start',
    			'margin-block-end',
    			'margin-inline-start',
    			'margin-inline-end',

    			'padding',
    			'padding-right',
    			'padding-bottom',
    			'padding-left',
    			'padding-top',
    			'padding-block-start',
    			'padding-block-end',
    			'padding-inline-start',
    			'padding-inline-end',

    			'flex',
    			'flex-basis',
    			'flex-direction',
    			'flex-flow',
    			'flex-grow',
    			'flex-shrink',
    			'flex-wrap',

    			'gap',
    			'column-gap',
    			'row-gap',

    			'grid-template-columns',
    			'grid-auto-columns',
    			'grid-column-start',
    			'grid-column-end',
    			'grid-column',
    			'grid-column-gap',
    			'grid-template-rows',
    			'grid-auto-rows',
    			'grid-row-start',
    			'grid-row-end',
    			'grid-row',
    			'grid-row-gap',
    			'grid-gap',

    			'justify-content',
    			'justify-items',
    			'justify-self',
    			'align-content',
    			'align-items',
    			'align-self',

    			'clear',
    			'cursor',
    			'direction',
    			'float',
    			'list-style-type',
    			'object-fit',
    			'object-position',
    			'opacity',
    			'overflow',
    			'vertical-align',
    			'writing-mode',

    			'position',
    			'top',
    			'right',
    			'bottom',
    			'left',
    			'z-index',
    			'box-shadow',
    			'aspect-ratio',
    			'container-type',

    			// Custom CSS properties.
    			'--*',
    		)
    	);

    	/*
    	 * CSS attributes that accept URL data types.
    	 *
    	 * This is in accordance to the CSS spec and unrelated to
    	 * the sub-set of supported attributes above.
    	 *
    	 * See: https://developer.mozilla.org/en-US/docs/Web/CSS/url
    	 */
    	$css_url_data_types = array(
    		'background',
    		'background-image',

    		'cursor',
    		'filter',

    		'list-style',
    		'list-style-image',
    	);

    	/*
    	 * CSS attributes that accept gradient data types.
    	 *
    	 */
    	$css_gradient_data_types = array(
    		'background',
    		'background-image',
    	);

    	if ( empty( $allowed_attr ) ) {
    		return $css;
    	}

    	$css = '';
    	foreach ( $css_array as $css_item ) {
    		if ( '' === $css_item ) {
    			continue;
    		}

    		$css_item        = trim( $css_item );
    		$css_test_string = $css_item;
    		$found           = false;
    		$url_attr        = false;
    		$gradient_attr   = false;
    		$is_custom_var   = false;

    		if ( ! str_contains( $css_item, ':' ) ) {
    			$found = true;
    		} else {
    			$parts        = explode( ':', $css_item, 2 );
    			$css_selector = trim( $parts[0] );

    			// Allow assigning values to CSS variables.
    			if ( in_array( '--*', $allowed_attr, true ) && preg_match( '/^--[a-zA-Z0-9-_]+$/', $css_selector ) ) {
    				$allowed_attr[] = $css_selector;
    				$is_custom_var  = true;
    			}

    			if ( in_array( $css_selector, $allowed_attr, true ) ) {
    				$found         = true;
    				$url_attr      = in_array( $css_selector, $css_url_data_types, true );
    				$gradient_attr = in_array( $css_selector, $css_gradient_data_types, true );
    			}

    			if ( $is_custom_var ) {
    				$css_value     = trim( $parts[1] );
    				$url_attr      = str_starts_with( $css_value, 'url(' );
    				$gradient_attr = str_contains( $css_value, '-gradient(' );
    			}
    		}

    		if ( $found && $url_attr ) {
    			// Simplified: matches the sequence `url(*)`.
    			preg_match_all( '/url\([^)]+\)/', $parts[1], $url_matches );

    			foreach ( $url_matches[0] as $url_match ) {
    				// Clean up the URL from each of the matches above.
    				preg_match( '/^url\(\s*([\'\"]?)(.*)(\g1)\s*\)$/', $url_match, $url_pieces );

    				if ( empty( $url_pieces[2] ) ) {
    					$found = false;
    					break;
    				}

    				$url = trim( $url_pieces[2] );

    				if ( empty( $url ) || wp_kses_bad_protocol( $url, $allowed_protocols ) !== $url ) {
    					$found = false;
    					break;
    				} else {
    					// Remove the whole `url(*)` bit that was matched above from the CSS.
    					$css_test_string = str_replace( $url_match, '', $css_test_string );
    				}
    			}
    		}

    		if ( $found && $gradient_attr ) {
    			$css_value = trim( $parts[1] );
    			if ( preg_match( '/^(repeating-)?(linear|radial|conic)-gradient\(([^()]|rgb[a]?\([^()]*\))*\)$/', $css_value ) ) {
    				// Remove the whole `gradient` bit that was matched above from the CSS.
    				$css_test_string = str_replace( $css_value, '', $css_test_string );
    			}
    		}

    		if ( $found ) {
    			/*
    			 * Allow CSS functions like var(), calc(), etc. by removing them from the test string.
    			 * Nested functions and parentheses are also removed, so long as the parentheses are balanced.
    			 */
    			$css_test_string = preg_replace(
    				'/\b(?:var|calc|min|max|minmax|clamp|repeat)(\((?:[^()]|(?1))*\))/',
    				'',
    				$css_test_string
    			);

    			/*
    			 * Disallow CSS containing \ ( & } = or comments, except for within url(), var(), calc(), etc.
    			 * which were removed from the test string above.
    			 */
    			$allow_css = ! preg_match( '%[\\\(&=}]|/\*%', $css_test_string );

    			/**
    			 * Filters the check for unsafe CSS in `safecss_filter_attr`.
    			 *
    			 * Enables developers to determine whether a section of CSS should be allowed or discarded.
    			 * By default, the value will be false if the part contains \ ( & } = or comments.
    			 * Return true to allow the CSS part to be included in the output.
    			 *
    			 * @since 5.5.0
    			 *
    			 * @param bool   $allow_css       Whether the CSS in the test string is considered safe.
    			 * @param string $css_test_string The CSS string to test.
    			 */
    			$allow_css = apply_filters( 'safecss_filter_attr_allow_css', $allow_css, $css_test_string );

    			// Only add the CSS part if it passes the regex check.
    			if ( $allow_css ) {
    				if ( '' !== $css ) {
    					$css .= ';';
    				}

    				$css .= $css_item;
    			}
    		}
    	}

    	return $css;
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/kses.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/6.9.4/src/wp-includes/kses.php#L2638)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/6.9.4/src/wp-includes/kses.php#L2638-L2961)

## 󠀁[Hooks](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#hooks)󠁿

 [apply_filters( ‘safecss_filter_attr_allow_css’, bool $allow_css, string $css_test_string )](https://developer.wordpress.org/reference/hooks/safecss_filter_attr_allow_css/)

Filters the check for unsafe CSS in `safecss_filter_attr`.

 [apply_filters( ‘safe_style_css’, string[] $attr )](https://developer.wordpress.org/reference/hooks/safe_style_css/)

Filters the list of allowed CSS attributes.

## 󠀁[Related](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#related)󠁿

| Uses | Description | 
| [wp_kses_no_null()](https://developer.wordpress.org/reference/functions/wp_kses_no_null/)`wp-includes/kses.php` |

Removes any invalid control characters in a text string.

  | 
| [wp_kses_bad_protocol()](https://developer.wordpress.org/reference/functions/wp_kses_bad_protocol/)`wp-includes/kses.php` |

Sanitizes a string and removed disallowed URL protocols.

  | 
| [wp_allowed_protocols()](https://developer.wordpress.org/reference/functions/wp_allowed_protocols/)`wp-includes/functions.php` |

Retrieves a list of protocols to allow in HTML attributes.

  | 
| [_deprecated_argument()](https://developer.wordpress.org/reference/functions/_deprecated_argument/)`wp-includes/functions.php` |

Marks a function argument as deprecated and inform when it has been used.

  | 
| [apply_filters()](https://developer.wordpress.org/reference/functions/apply_filters/)`wp-includes/plugin.php` |

Calls the callback functions that have been added to a filter hook.

  |

[Show 2 more](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#)

| Used by | Description | 
| [WP_Style_Engine_CSS_Declarations::filter_declaration()](https://developer.wordpress.org/reference/classes/wp_style_engine_css_declarations/filter_declaration/)`wp-includes/style-engine/class-wp-style-engine-css-declarations.php` |

Filters a CSS property + value pair.

  | 
| [WP_Theme_JSON::is_safe_css_declaration()](https://developer.wordpress.org/reference/classes/wp_theme_json/is_safe_css_declaration/)`wp-includes/class-wp-theme-json.php` |

Checks that a declaration provided by the user is safe.

  | 
| [wp_kses_attr_check()](https://developer.wordpress.org/reference/functions/wp_kses_attr_check/)`wp-includes/kses.php` |

Determines whether an attribute is allowed.

  |

## 󠀁[Changelog](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#changelog)󠁿

| Version | Description | 
| [6.9.0](https://developer.wordpress.org/reference/since/6.9.0/) | Added support for `white-space`. | 
| [6.6.0](https://developer.wordpress.org/reference/since/6.6.0/) | Added support for `grid-column`, `grid-row`, and `container-type`. | 
| [6.5.0](https://developer.wordpress.org/reference/since/6.5.0/) | Added support for `background-repeat`. | 
| [6.4.0](https://developer.wordpress.org/reference/since/6.4.0/) | Added support for `writing-mode`. | 
| [6.3.0](https://developer.wordpress.org/reference/since/6.3.0/) | Extended support for `filter` to accept a URL and added support for repeat().
 Added support for `box-shadow`. | 
| [6.2.0](https://developer.wordpress.org/reference/since/6.2.0/) | Added support for `aspect-ratio`, `position`, `top`, `right`, `bottom`, `left`, and `z-index` CSS properties. | 
| [6.1.0](https://developer.wordpress.org/reference/since/6.1.0/) | Added support for `min()`, `max()`, `minmax()`, `clamp()`, nested `var()` values, and assigning values to CSS variables. Added support for `object-fit`, `gap`, `column-gap`, `row-gap`, and `flex-wrap`. Extended `margin-*` and `padding-*` support for logical properties. | 
| [5.8.0](https://developer.wordpress.org/reference/since/5.8.0/) | Added support for `calc()` and `var()` values. | 
| [5.7.1](https://developer.wordpress.org/reference/since/5.7.1/) | Added support for `object-position`. | 
| [5.3.1](https://developer.wordpress.org/reference/since/5.3.1/) | Added support for gradient backgrounds. | 
| [5.3.0](https://developer.wordpress.org/reference/since/5.3.0/) | Added support for `grid`, `flex` and `column` layout properties. Extended `background-*` support for individual properties. | 
| [5.2.0](https://developer.wordpress.org/reference/since/5.2.0/) | Added support for `background-position` and `grid-template-columns`. | 
| [5.1.0](https://developer.wordpress.org/reference/since/5.1.0/) | Added support for `text-transform`. | 
| [5.0.0](https://developer.wordpress.org/reference/since/5.0.0/) | Added support for `background-image`. | 
| [4.6.0](https://developer.wordpress.org/reference/since/4.6.0/) | Added support for `list-style-type`. | 
| [4.4.0](https://developer.wordpress.org/reference/since/4.4.0/) | Added support for `min-height`, `max-height`, `min-width`, and `max-width`. | 
| [2.8.1](https://developer.wordpress.org/reference/since/2.8.1/) | Introduced. |

[Show 12 more](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#)

## 󠀁[User Contributed Notes](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#user-contributed-notes)󠁿

 1.   [Skip to note 2 content](https://developer.wordpress.org/reference/functions/safecss_filter_attr/?output_format=md#comment-content-5760)
 2.    [Aleksej](https://profiles.wordpress.org/zutigrm/)  [  4 years ago  ](https://developer.wordpress.org/reference/functions/safecss_filter_attr/#comment-5760)
 3.  [You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fsafecss_filter_attr%2F%23comment-5760)
     Vote results for this note: 0[You must log in to vote on the helpfulness of this note](https://login.wordpress.org?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fsafecss_filter_attr%2F%23comment-5760)
 4.  It is very handy for filtering css rules in functions that render the inline styles
 5.  Helper functions:
 6.      ```php
         /**
          * Render style tag and background-image, with optional
          * extra css styles
          * @param $img_url string image url
          * @param $extra_css array list of css rules in key => value pair
          */
         function prefix_bg_get_image( $img_url, $extra_css = array() ) {
         	$css = ''; 
         	if ( ! empty( $img_url ) ) {
         		$css .= sprintf( 'background-image: url(%s);', esc_url( $img_url ) ); 
         	}
     
         	if ( $extra_css ) {
         		$extra_css = array_map('prefix_join_css', array_keys($extra_css), array_values($extra_css));
         		$css .= join( '', $extra_css );
         	}
     
             if ( empty ( $css ) ) return; // prevent printing empty style="" attr
     
             // use css filter to clean the all combined $css
         	return sprintf( 'style="%s"', safecss_filter_attr( $css ) );
         }
     
         function prefix_render_bg_image( $img_url, $extra_css = array() ) {
         	echo prefix_bg_get_image( $img_url, $extra_css );
         }
     
         function prefix_join_css($key, $val) {
         	return "$key: $val;";
         }
         ```
     
 7.  then just printing the inline bg image style:
 8.      ```php
         // we just need to get image url, for example acf, custom meta or settings
         // get acf field image id
         $image_id  = get_feild( 'background_image' );
         $image_url = wp_get_attachment_image_src( $image_id );
         $bg_css = array(
         	'background-repeat'   => 'no-repeat',
         	'background-position' => 'center',
         	'background-size'     => 'cover',
         );
         ```
     
 9.      ```php
         <!-- pass the url and styles array to render bg image -->
         <div class="prefix-somecalss" <?php prefix_render_bg_image( $image_url, $bg_css ); ?>></div>
         ```
     
 10.  [Log in to add feedback](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fsafecss_filter_attr%2F%3Freplytocom%3D5760%23feedback-editor-5760)

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2Fsafecss_filter_attr%2F)
before being able to contribute a note or feedback.