Corriger les erreurs d’affichage de vos SVG sous WordPress

Mis à jour le :

Certains fichiers vectoriels qui portent l’extension SVG pour Scalable Vector Graphics s’affichent mal une fois importés sous WordPress, avec des visuels réduits à 1 pixel en largeur et en hauteur. En cause : WordPress ne sait pas lire les dimensions d’un SVG, et certains fichiers ne les indiquent pas correctement. Par chance, il existe un filtre pour corriger ce comportement.

Avant d’aller plus loin, rappelons que les fichiers SVG ne sont pas des fichiers images traditionnels comme par exemple les JPEG. Il s’agit de fichiers constitués de lignes de code et qui peuvent donc présenter un risque de sécurité lors de l’envoi sur votre site WordPress.

C’est pour cela que, par défaut, WordPress n’autorise pas l’envoi de fichiers SVG. Pour débloquer cette possibilité en limitant les risques, suivez ces instructions : utilisez une extension qui nettoie chaque fichier, comme Safe SVG, ou autorisez les SVG par code en réservant leur envoi aux administrateurs et en nettoyant chaque fichier envoyé.

Maintenant que vous êtes en mesure d’envoyer de tels fichiers, il est possible que le rendu navigateur pose problème. Voici quelques conseils pour limiter les bugs d’affichage :

  1. Les textes doivent être convertis en courbe de sorte que vous ne soyez pas dépendant de la police utilisée. C’est pour cela que certains fichiers vectoriels embarquant du texte affichent ce dernier dans une police native comme Serif ou Times ;
  2. Le fichier doit indiquer ses dimensions : des attributs de largeur et de hauteur, width et height en anglais, spécifiés en pixels ou sans unité, ainsi qu’un attribut viewBox. Des valeurs en pourcentage ne donnent aucune taille au dessin. Sans largeur ni hauteur, le navigateur étire le SVG sur toute la largeur disponible s’il possède un viewBox, et l’affiche en 300 × 150 pixels s’il n’en a pas ;
  3. Vérifiez le poids du fichier généré : plus de 50 Ko pour une image vectorielle c’est trop lourd, cela signifie que le format n’est probablement pas adapté. Dans ce cas, un export au format PNG sera à privilégier pour des questions de performances ;

Pourquoi WordPress affiche-t-il vos SVG en 1 × 1 pixel ?

WordPress ne sait pas lire les dimensions d’un SVG : à l’envoi, il n’enregistre ni largeur ni hauteur pour ce type de fichier. Lorsqu’il génère lui-même la balise d’image dans une taille précise (miniature, taille moyenne, vue liste de la médiathèque…), il ajuste ces dimensions inconnues à la taille demandée, avec un minimum de 1 pixel : l’image reçoit alors les attributs width="1" et height="1". Les images insérées avec le bloc Image ne sont pas concernées, car WordPress ne leur ajoute aucune dimension : c’est le navigateur qui décide de leur taille, d’où l’importance des conseils précédents.

Si vous utilisez l’extension Safe SVG, elle lit ces dimensions dans le fichier, à partir de l’attribut viewBox ou, à défaut, des attributs width et height : le code ci-dessous est alors inutile. Il s’adresse aux sites qui autorisent les SVG par code.

Rétablir les dimensions de vos SVG

Ce code lit la largeur et la hauteur indiquées dans le fichier, ou à défaut son viewBox, et les transmet à WordPress, qui les ajuste ensuite à la taille demandée. Comme toujours, vous pouvez coller ces lignes dans le fichier functions.php de votre thème ou dans un mu-plugin, par exemple celui qui autorise déjà vos SVG.

/**
 * Returns the width and height of an SVG file, read from its width and height attributes
 * (unitless or in pixels) or, failing that, from its viewBox. Returns null if the file declares no size.
 */
function wpc_svg_get_dimensions( $file ) {
	// Local files only: stream wrappers (http://, s3://...) are never read.
	if ( wp_is_stream( $file ) || ! is_readable( $file ) || ! class_exists( 'DOMDocument' ) ) {
		return null;
	}

	// LIBXML_NONET: no network access. Without LIBXML_NOENT or LIBXML_DTDLOAD, external entities and DTDs are never loaded.
	$dom             = new DOMDocument();
	$internal_errors = libxml_use_internal_errors( true );
	$loaded          = $dom->loadXML( (string) file_get_contents( $file ), LIBXML_NONET );
	libxml_clear_errors();
	libxml_use_internal_errors( $internal_errors );

	$svg = $loaded ? $dom->documentElement : null;

	if ( null === $svg || 'svg' !== $svg->localName ) {
		return null;
	}

	// Percentages and other units (em, cm...) do not give a size in pixels: they are ignored.
	$size = array();
	foreach ( array( 'width', 'height' ) as $attribute ) {
		$size[ $attribute ] = preg_match( '/^\s*(\d*\.?\d+)\s*(px)?\s*$/i', $svg->getAttribute( $attribute ), $match ) ? (float) $match[1] : 0.0;
	}

	// viewBox="min-x min-y width height": gives the size, or the missing width or height.
	$viewbox = array_map( 'floatval', preg_split( '/[\s,]+/', trim( $svg->getAttribute( 'viewBox' ) ) ) );

	if ( 4 === count( $viewbox ) && $viewbox[2] > 0 && $viewbox[3] > 0 ) {
		if ( ! $size['width'] && ! $size['height'] ) {
			$size = array( 'width' => $viewbox[2], 'height' => $viewbox[3] );
		} elseif ( ! $size['height'] ) {
			$size['height'] = $size['width'] * $viewbox[3] / $viewbox[2];
		} elseif ( ! $size['width'] ) {
			$size['width'] = $size['height'] * $viewbox[2] / $viewbox[3];
		}
	}

	$width  = (int) round( $size['width'] );
	$height = (int) round( $size['height'] );

	return ( $width > 0 && $height > 0 ) ? array( $width, $height ) : null;
}

/**
 * Gives WordPress the real dimensions of SVG files, scaled to the requested image size,
 * instead of the 1 x 1 pixel it uses when it cannot read them.
 */
function wpc_svg_image_downsize( $downsize, $attachment_id, $size ) {
	if ( $downsize || 'image/svg+xml' !== get_post_mime_type( $attachment_id ) ) {
		return $downsize;
	}

	$url        = wp_get_attachment_url( $attachment_id );
	$file       = get_attached_file( $attachment_id );
	$dimensions = ( $url && $file ) ? wpc_svg_get_dimensions( $file ) : null;

	if ( null === $dimensions ) {
		return $downsize;
	}

	list( $width, $height ) = image_constrain_size_for_editor( $dimensions[0], $dimensions[1], $size );

	return array( $url, $width, $height, false );
}
add_filter( 'image_downsize', 'wpc_svg_image_downsize', 10, 3 );

Un SVG de 120 × 60 pixels conserve ainsi ses dimensions dans les tailles Miniature, Moyenne et Grande, et s’affiche en 60 × 30 pixels dans la vue liste de la médiathèque au lieu d’un simple point. Un SVG plus grand est réduit proportionnellement aux limites de la taille demandée. Le code agit dans l’administration comme sur votre site, pour les SVG déjà envoyés comme pour les nouveaux. En revanche, si le fichier n’indique aucune dimension exploitable (ni width et height en pixels, ni viewBox), il ne peut rien faire : corrigez alors le fichier dans votre logiciel de dessin.

Écran Médias > Médiathèque de WordPress en vue liste, avec le code de l’article actif : les trois SVG de démonstration banniere-grand-format.svg, pictogramme-viewbox.svg et logo-demo.svg s’affichent chacun en vignette de 60 × 30 pixels dans la colonne Fichier, avec l’autrice Claire Martin et la mention (Non attaché) ; le menu latéral montre Médias ouvert sur Médiathèque.
Avec ce code, les SVG retrouvent leurs proportions dans la vue liste de la médiathèque

Si vous aviez ajouté la fonction wpc_fix_svg_size_attributes() proposée auparavant dans cet article, supprimez-la : elle retirait simplement les dimensions sur le site public, sans corriger l’administration, et elle annule l’effet de ce nouveau code.

Les fichiers SVG sont insérés comme des images en passant l’URL dans l’attribut src lorsque vous les envoyez dans l’éditeur de WordPress. Ils ne sont pas affichés directement comme vous pourriez le faire en modifiant votre thème. Si vous analysez le code de ce site, vous noterez que j’utilise très souvent du code pour générer les logos et autres icônes. De cette manière, le rendu est impeccable y compris sur écrans à haute densité de pixels.

Grâce à cette astuce, vos fichiers SVG s’afficheront aux bonnes dimensions. Libre à vous ensuite d’ajuster le résultat via la feuille de style du thème.

Un fichier SVG refuse toujours de s’afficher correctement ? Mon support technique WordPress peut analyser le fichier et votre thème.

Pour les autres formats d’image, consultez mon guide complet de la gestion des images sous WordPress.

Avatar de Aurélien Denis

Protégez votre site WordPress

Vos données sont précieuses,
ne prenez pas le risque de tout perdre.
Confiez-moi votre maintenance !

Ces articles devraient t’intéresser…