Allowing SVG in WordPress Content

I ran into an issue when trying to save SVG as part of a block. If you are having the same issue, or similar with non-typical tags being used; then here’s how you can fix it.

In creating a Gutenberg block, adding an SVG element as part of the save() function it was being stripped out. The same element was included as the block icon, and the edit() function; these showed fine. Anything I tried after saving and viewing on the front-end the SVG was gone and no console log or errors.

The reason it was being stripped out was due to the allowed tags defined in the wp_kses_allowed_html filter. Hat tip to Joyously for the pointer!

WordPress has a set of allowed html tags as a means to limit exposure to malicious or invalid code being inserted. The SVG was being caught up in this check. KSES is a recursive acronym standing for “KSES Strips Evil Scripts”.

The SVG definition I was using is relatively simple, so the following filter solved it for me. You may need to include additional tags and attributes if you use them. For example, circle, rect, x, y, cx, cy, r, …

add_filter( 'wp_kses_allowed_html', function( $tags ) {

    $tags['svg'] = array(
        'xmlns' => array(),
        'fill' => array(),
        'viewbox' => array(),
        'role' => array(),
        'aria-hidden' => array(),
        'focusable' => array(),
    );
    $tags['path'] = array(
        'd' => array(),
        'fill' => array(),
    );
    return $tags;

}, 10, 2);

For completeness, here are the other relevant pieces of my block.

I moved the SVG to JavaScript to make it easier to import and use multiple times. My SVG file is named icon.js containing:

const  { Path, SVG } = wp.components;

export default (
    <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" role="img" aria-hidden="true" focusable="false">
        <Path fill="none" d="M0 0h24v24H0V0z"/>
        <Path d="M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8-8 8z"/>
    </SVG>
);

My block definition, pared down to the interesting parts: the import and the save() usage:

import ArrowIcon from './icon';

registerBlockType( '...', {

    icon: ArrowIcon,

    save: ( { className } ) => {
        return (
            <div> { ArrowIcon } </div>
        );
    },

} );