Skip to content

Instantly share code, notes, and snippets.

@384400
Last active January 19, 2016 15:08
Show Gist options
  • Save 384400/c673429ed8acb1741b31 to your computer and use it in GitHub Desktop.
Save 384400/c673429ed8acb1741b31 to your computer and use it in GitHub Desktop.
[Svg] [Html] [JavaScript] [Php] [Css] Afficher des images Svg en ligne avec et sans solution de repli

Comment afficher des images Svg en ligne avec et sans solution de repli ?

Les images en ligne au format Standard Vector Graphics (Svg), commodes d'emploi, permettent une économie de bande passante. Prenons un exemple, avec l'image décrite comme suit (svg-0.html)...

<svg viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-labelledby="title-logo desc-logo">
    <title id="title-logo" class="svg-aria">Logotype</title>
    <desc id="desc-logo" class="svg-aria">Ornement</desc>
    <path fill="#ff0000" d="M12,1A3,3 0 0,1 15,4V5A1,1 0 0,1 16,6V7.07C18.39,8.45 20,11.04 20,14A8,8 0 0,1 12,22A8,8 0 0,1 4,14C4,11.04 5.61,8.45 8,7.07V6A1,1 0 0,1 9,5V4A3,3 0 0,1 12,1M12,3A1,1 0 0,0 11,4V5H13V4A1,1 0 0,0 12,3M12,8C10.22,8 8.63,8.77 7.53,10H16.47C15.37,8.77 13.78,8 12,8M12,20C13.78,20 15.37,19.23 16.47,18H7.53C8.63,19.23 10.22,20 12,20M12,12A2,2 0 0,0 10,14A2,2 0 0,0 12,16A2,2 0 0,0 14,14A2,2 0 0,0 12,12M18,14C18,13.31 17.88,12.65 17.67,12C16.72,12.19 16,13 16,14C16,15 16.72,15.81 17.67,15.97C17.88,15.35 18,14.69 18,14M6,14C6,14.69 6.12,15.35 6.33,15.97C7.28,15.81 8,15 8,14C8,13 7.28,12.19 6.33,12C6.12,12.65 6,13.31 6,14Z" />
</svg>

Le code de cette image pèse 948 octets. Au format Portable Graphic Networks (Png), le fichier équivalent pèse 413 octets pour une image de 24 pixels de côté, 2,60 kilo-octets pour une image de 128 pixels de côté, 5,48 kilo-octets pour une image de 256 pixels de côté...

Cependant, comme les navigateurs anciens n'affichent pas (en fait, ne dessinent pas !) les images au format Svg, il convient de prévoir une solution de repli.

Ici, nous distinguerons image essentielle et facultative. Une image essentielle pourra être un logotype, qui devra logiquement être affiché quel que soit le navigateur. Une image facultative pourra être, par exemple, l'icône d'un réseau social en vue de partager le contenu d'un clic de souris : dans ce cas, la description textuelle, avec un titre et une description, sera considérée comme suffisante, sans Fallback graphique.

Le titre s'affiche au survol de l'image. Quand le format Svg n'est pas supporté, la description s'affiche, au moins en principe (!), à l'écran.

La solution de repli la plus couramment utilisée repose sur la propriété <foreignObject>.

Ainsi obtenons-nous le code suivant (svg-1.html)...

<svg viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-labelledby="title-logo desc-logo">
    <title id="title-logo" class="svg-aria">Logotype</title>
    <desc id="desc-logo" class="svg-aria">Ornement</desc>
    <path fill="#ff0000" d="M12,1A3,3 0 0,1 15,4V5A1,1 0 0,1 16,6V7.07C18.39,8.45 20,11.04 20,14A8,8 0 0,1 12,22A8,8 0 0,1 4,14C4,11.04 5.61,8.45 8,7.07V6A1,1 0 0,1 9,5V4A3,3 0 0,1 12,1M12,3A1,1 0 0,0 11,4V5H13V4A1,1 0 0,0 12,3M12,8C10.22,8 8.63,8.77 7.53,10H16.47C15.37,8.77 13.78,8 12,8M12,20C13.78,20 15.37,19.23 16.47,18H7.53C8.63,19.23 10.22,20 12,20M12,12A2,2 0 0,0 10,14A2,2 0 0,0 12,16A2,2 0 0,0 14,14A2,2 0 0,0 12,12M18,14C18,13.31 17.88,12.65 17.67,12C16.72,12.19 16,13 16,14C16,15 16.72,15.81 17.67,15.97C17.88,15.35 18,14.69 18,14M6,14C6,14.69 6.12,15.35 6.33,15.97C7.28,15.81 8,15 8,14C8,13 7.28,12.19 6.33,12C6.12,12.65 6,13.31 6,14Z" />
    <foreignObject>
      <img src="ornament.png" class="" alt="Logotype" title="Logotype" />
    </foreignObject>
</svg>

<foreignObject> présente deux inconvénients. D'abord, cette propriété ne semble pas correctement gérée par les navigateurs les plus anciens. (Nos tests ont néanmoins montré qu'Internet Explorer affichait correctement le contenu au moins à partir de la version 5.) Ensuite et surtout, cette technique oblige tous les navigateurs à charger deux images : celle au format Svg, d'une part, et, d'autre part, celle au format Png.

Voilà pourquoi, nous avons conçu une méthode alternative... Quand le navigateur ne soutient pas Svg, l'image par défaut est chargée. Quand JavaScript est désactivé (nous sommes parti du principe, critiquable, que Svg n'est pas supporté non plus dans ce cas), l'image par défaut est aussi disponible (svg-2.html)...

<!-- Code Svg -->
<div id="logo-fallback">
  <noscript>
    <img src="ornament.png" title="Logotype" alt="Logotype" />
  </noscript>
</div>
<script>
function supportSvg() {
  if (document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Shape', '1.0')) {
      return true;
  }
}
document.getElementsByTagName('html')[0].className = document.getElementsByTagName('html')[0].className.replace('no-js', 'js');
if (!supportSvg()) {
  document.getElementsByTagName('html')[0].className += ' ';
  document.getElementsByTagName('html')[0].className += 'no-support-svg';
  document.getElementById('logo-fallback').innerHTML = '<img src="ornament.png" title="Logotype" alt="Logotype" />';
}
</script>

L'écriture est à peine plus contraignante !

Nos tests nous ont permis de conclure que l'image par défaut était appellée si et seulement si elle était nécessaire.

Le seul écueil est l'affichage de la description de l'image Svg originale : elle est superflue en raison du Fallback et peut compromettre le rendu du logotype. C'est pourquoi, dans ce cas, nous cachons le titre et la description avec la feuille de style.

Avec Svg, nous pouvons aussi afficher des icônes. Comme nous considérons ces images comme facultatives, aucun Fallback n'est requis (svg-3.html).

Enfin, avec un zeste de code Hypertext PreProcessor (Php), nous pouvons facilement colorier les images en passant un paramètre lors de l'appel du fichier Svg (icons.svg.php et svg.php)...

<?php 
$color = '#ff0000';
echo 'image.svg.php?color='.$color;
?>

Nota. Les icônes proviennent de [Material Design Icons] (https://materialdesignicons.com/).

<svg display="none" width="0" height="0" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-facebook-box" viewBox="0 0 24 24"><!-- #facebook -->
<title>Facebook</title>
<desc>Facebook</desc>
<path fill="<?php echo $color; ?>" d="M19,4V7H17A1,1 0 0,0 16,8V10H19V13H16V20H13V13H11V10H13V7.5C13,5.56 14.57,4 16.5,4M20,2H4A2,2 0 0,0 2,4V20A2,2 0 0,0 4,22H20A2,2 0 0,0 22,20V4C22,2.89 21.1,2 20,2Z"></path>
</symbol>
<symbol id="icon-twitter-box" viewBox="0 0 24 24"><!-- #twitter -->
<title>Twitter</title>
<desc>Twitter</desc>
<path fill="<?php echo $color; ?>" d="M17.71,9.33C17.64,13.95 14.69,17.11 10.28,17.31C8.46,17.39 7.15,16.81 6,16.08C7.34,16.29 9,15.76 9.9,15C8.58,14.86 7.81,14.19 7.44,13.12C7.82,13.18 8.22,13.16 8.58,13.09C7.39,12.69 6.54,11.95 6.5,10.41C6.83,10.57 7.18,10.71 7.64,10.74C6.75,10.23 6.1,8.38 6.85,7.16C8.17,8.61 9.76,9.79 12.37,9.95C11.71,7.15 15.42,5.63 16.97,7.5C17.63,7.38 18.16,7.14 18.68,6.86C18.47,7.5 18.06,7.97 17.56,8.33C18.1,8.26 18.59,8.13 19,7.92C18.75,8.45 18.19,8.93 17.71,9.33M20,2H4A2,2 0 0,0 2,4V20A2,2 0 0,0 4,22H20A2,2 0 0,0 22,20V4C22,2.89 21.1,2 20,2Z"></path>
</symbol>
<symbol id="icon-google-plus-box" viewBox="0 0 24 24"><!-- #google -->
<title>Google +</title>
<desc>Google +</desc>
<path fill="<?php echo $color; ?>" d="M19,12H17V14H16V12H14V11H16V9H17V11H19M9.07,19.2C6.27,19.2 5,17.64 5,16.18C5,15.73 5.14,14.59 6.5,13.8C7.25,13.33 8.33,13 9.62,12.89C9.43,12.64 9.28,12.34 9.28,11.9C9.28,11.75 9.3,11.59 9.34,11.44H8.95C7,11.44 5.8,9.89 5.8,8.39C5.8,6.66 7.09,4.8 9.91,4.8H14.13L13.79,5.14L13.08,5.85L13,5.91H12.3C12.71,6.33 13.2,7 13.2,8.07C13.2,9.47 12.46,10.16 11.64,10.8C11.5,10.92 11.22,11.18 11.22,11.5C11.22,11.82 11.46,12 11.61,12.14C11.74,12.25 11.9,12.36 12.08,12.5C12.89,13.05 14,13.83 14,15.36C14,17.13 12.71,19.2 9.07,19.2M20,2H4A2,2 0 0,0 2,4V20A2,2 0 0,0 4,22H20A2,2 0 0,0 22,20V4C22,2.89 21.1,2 20,2M10.57,13.81C10.46,13.8 10.38,13.8 10.25,13.8H10.23C9.97,13.8 9.08,13.85 8.41,14.07C7.77,14.31 7,14.79 7,15.77C7,16.85 8.04,18 9.96,18C11.5,18 12.4,17 12.4,16C12.4,15.25 11.94,14.79 10.57,13.81M11.2,8.87C11.2,7.85 10.57,5.85 9.12,5.85C8.5,5.85 7.8,6.29 7.8,7.5C7.8,8.7 8.42,10.45 9.77,10.45C9.83,10.45 11.2,10.44 11.2,8.87Z"></path>
</symbol>
</defs>
</svg>
<!DOCTYPE html>
<html>
<head>
<title>Raw Svg</title>
<style>
#logo svg {
width: 128px;
height: 128px;
}
</style>
</head>
<body>
<div id="logo">
<svg viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-labelledby="title-logo desc-logo">
<title id="title-logo" class="svg-aria">Logotype</title>
<desc id="desc-logo" class="svg-aria">Ornement</desc>
<path fill="#ff0000" d="M12,1A3,3 0 0,1 15,4V5A1,1 0 0,1 16,6V7.07C18.39,8.45 20,11.04 20,14A8,8 0 0,1 12,22A8,8 0 0,1 4,14C4,11.04 5.61,8.45 8,7.07V6A1,1 0 0,1 9,5V4A3,3 0 0,1 12,1M12,3A1,1 0 0,0 11,4V5H13V4A1,1 0 0,0 12,3M12,8C10.22,8 8.63,8.77 7.53,10H16.47C15.37,8.77 13.78,8 12,8M12,20C13.78,20 15.37,19.23 16.47,18H7.53C8.63,19.23 10.22,20 12,20M12,12A2,2 0 0,0 10,14A2,2 0 0,0 12,16A2,2 0 0,0 14,14A2,2 0 0,0 12,12M18,14C18,13.31 17.88,12.65 17.67,12C16.72,12.19 16,13 16,14C16,15 16.72,15.81 17.67,15.97C17.88,15.35 18,14.69 18,14M6,14C6,14.69 6.12,15.35 6.33,15.97C7.28,15.81 8,15 8,14C8,13 7.28,12.19 6.33,12C6.12,12.65 6,13.31 6,14Z" />
</svg> return false;
</div>
</body>
</html>
<!DOCTYPE html>
<html class="no-js">
<head>
<title>Svg with foreignObject</title>
<style>
.js.no-support-svg #logo .svg-aria {
display: none;
}
#logo svg {
width: 128px;
height: 128px;
}
</style>
</head>
<body>
<div id="logo">
<svg viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-labelledby="title-logo desc-logo">
<title id="title-logo" class="svg-aria">Logotype</title>
<desc id="desc-logo" class="svg-aria">Ornement</desc>
<path fill="#ff0000" d="M12,1A3,3 0 0,1 15,4V5A1,1 0 0,1 16,6V7.07C18.39,8.45 20,11.04 20,14A8,8 0 0,1 12,22A8,8 0 0,1 4,14C4,11.04 5.61,8.45 8,7.07V6A1,1 0 0,1 9,5V4A3,3 0 0,1 12,1M12,3A1,1 0 0,0 11,4V5H13V4A1,1 0 0,0 12,3M12,8C10.22,8 8.63,8.77 7.53,10H16.47C15.37,8.77 13.78,8 12,8M12,20C13.78,20 15.37,19.23 16.47,18H7.53C8.63,19.23 10.22,20 12,20M12,12A2,2 0 0,0 10,14A2,2 0 0,0 12,16A2,2 0 0,0 14,14A2,2 0 0,0 12,12M18,14C18,13.31 17.88,12.65 17.67,12C16.72,12.19 16,13 16,14C16,15 16.72,15.81 17.67,15.97C17.88,15.35 18,14.69 18,14M6,14C6,14.69 6.12,15.35 6.33,15.97C7.28,15.81 8,15 8,14C8,13 7.28,12.19 6.33,12C6.12,12.65 6,13.31 6,14Z" />
<foreignObject>
<img src="ornament.png" class="" alt="Logotype" title="Logotype" />
</foreignObject>
</svg>
</div>
<script>
function supportSvg() {
if (document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Shape', '1.0')) {
return true;
}
return false;
}
document.getElementsByTagName('html')[0].className = document.getElementsByTagName('html')[0].className.replace('no-js', 'js');
document.getElementsByTagName('html')[0].className = document.getElementsByTagName('html')[0].className.replace('no-js', 'js');
if (!supportSvg()) {
document.getElementsByTagName('html')[0].className += ' ';
document.getElementsByTagName('html')[0].className += 'no-support-svg';
}
</script>
</body>
</html>
<!DOCTYPE html>
<html class="no-js">
<head>
<title>Svg with Fallback</title>
<style>
.no-js svg, .js.no-support-svg svg, .js.no-support-svg #logo .svg-aria {
display: none;
}
.no-js #logo-fallback, .js.no-support-svg #logo-fallback {
display: block;
}
.js.no-support-svg #logo-fallback {
display: block;
}
#logo svg {
width: 128px;
height: 128px;
}
</style>
</head>
<body>
<div id="logo">
<svg viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-labelledby="title-logo desc-logo">
<title id="title-logo" class="svg-aria">Logotype</title>
<desc id="desc-logo" class="svg-aria">Ornement</desc>
<path fill="#ff0000" d="M12,1A3,3 0 0,1 15,4V5A1,1 0 0,1 16,6V7.07C18.39,8.45 20,11.04 20,14A8,8 0 0,1 12,22A8,8 0 0,1 4,14C4,11.04 5.61,8.45 8,7.07V6A1,1 0 0,1 9,5V4A3,3 0 0,1 12,1M12,3A1,1 0 0,0 11,4V5H13V4A1,1 0 0,0 12,3M12,8C10.22,8 8.63,8.77 7.53,10H16.47C15.37,8.77 13.78,8 12,8M12,20C13.78,20 15.37,19.23 16.47,18H7.53C8.63,19.23 10.22,20 12,20M12,12A2,2 0 0,0 10,14A2,2 0 0,0 12,16A2,2 0 0,0 14,14A2,2 0 0,0 12,12M18,14C18,13.31 17.88,12.65 17.67,12C16.72,12.19 16,13 16,14C16,15 16.72,15.81 17.67,15.97C17.88,15.35 18,14.69 18,14M6,14C6,14.69 6.12,15.35 6.33,15.97C7.28,15.81 8,15 8,14C8,13 7.28,12.19 6.33,12C6.12,12.65 6,13.31 6,14Z" />
</svg>
</div>
<div id="logo-fallback">
<noscript>
<img src="ornament.png" title="Logotype" alt="Logotype" />
</noscript>
</div>
<script>
function supportSvg() {
if (document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Shape', '1.0')) {
return true;
}
return false;
}
document.getElementsByTagName('html')[0].className = document.getElementsByTagName('html')[0].className.replace('no-js', 'js');
if (!supportSvg()) {
document.getElementsByTagName('html')[0].className += ' ';
document.getElementsByTagName('html')[0].className += 'no-support-svg';
document.getElementById('logo-fallback').innerHTML = '<img src="ornament.png" title="Logotype" alt="Logotype" />';
}
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Svg Icons</title>
<style>
.icon {
width: 64px;
height: 64px;
}
</style>
</head>
<body>
<svg display="none" width="0" height="0" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-facebook-box" viewBox="0 0 24 24"><!-- #facebook -->
<title>Facebook</title>
<desc>Facebook</desc>
<path fill="#ff0000" d="M19,4V7H17A1,1 0 0,0 16,8V10H19V13H16V20H13V13H11V10H13V7.5C13,5.56 14.57,4 16.5,4M20,2H4A2,2 0 0,0 2,4V20A2,2 0 0,0 4,22H20A2,2 0 0,0 22,20V4C22,2.89 21.1,2 20,2Z"></path>
</symbol>
<symbol id="icon-twitter-box" viewBox="0 0 24 24"><!-- #twitter -->
<title>Twitter</title>
<desc>Twitter</desc>
<path fill="#ff0000" d="M17.71,9.33C17.64,13.95 14.69,17.11 10.28,17.31C8.46,17.39 7.15,16.81 6,16.08C7.34,16.29 9,15.76 9.9,15C8.58,14.86 7.81,14.19 7.44,13.12C7.82,13.18 8.22,13.16 8.58,13.09C7.39,12.69 6.54,11.95 6.5,10.41C6.83,10.57 7.18,10.71 7.64,10.74C6.75,10.23 6.1,8.38 6.85,7.16C8.17,8.61 9.76,9.79 12.37,9.95C11.71,7.15 15.42,5.63 16.97,7.5C17.63,7.38 18.16,7.14 18.68,6.86C18.47,7.5 18.06,7.97 17.56,8.33C18.1,8.26 18.59,8.13 19,7.92C18.75,8.45 18.19,8.93 17.71,9.33M20,2H4A2,2 0 0,0 2,4V20A2,2 0 0,0 4,22H20A2,2 0 0,0 22,20V4C22,2.89 21.1,2 20,2Z"></path>
</symbol>
<symbol id="icon-google-plus-box" viewBox="0 0 24 24"><!-- #google -->
<title>Google +</title>
<desc>Google +</desc>
<path fill="#ff0000" d="M19,12H17V14H16V12H14V11H16V9H17V11H19M9.07,19.2C6.27,19.2 5,17.64 5,16.18C5,15.73 5.14,14.59 6.5,13.8C7.25,13.33 8.33,13 9.62,12.89C9.43,12.64 9.28,12.34 9.28,11.9C9.28,11.75 9.3,11.59 9.34,11.44H8.95C7,11.44 5.8,9.89 5.8,8.39C5.8,6.66 7.09,4.8 9.91,4.8H14.13L13.79,5.14L13.08,5.85L13,5.91H12.3C12.71,6.33 13.2,7 13.2,8.07C13.2,9.47 12.46,10.16 11.64,10.8C11.5,10.92 11.22,11.18 11.22,11.5C11.22,11.82 11.46,12 11.61,12.14C11.74,12.25 11.9,12.36 12.08,12.5C12.89,13.05 14,13.83 14,15.36C14,17.13 12.71,19.2 9.07,19.2M20,2H4A2,2 0 0,0 2,4V20A2,2 0 0,0 4,22H20A2,2 0 0,0 22,20V4C22,2.89 21.1,2 20,2M10.57,13.81C10.46,13.8 10.38,13.8 10.25,13.8H10.23C9.97,13.8 9.08,13.85 8.41,14.07C7.77,14.31 7,14.79 7,15.77C7,16.85 8.04,18 9.96,18C11.5,18 12.4,17 12.4,16C12.4,15.25 11.94,14.79 10.57,13.81M11.2,8.87C11.2,7.85 10.57,5.85 9.12,5.85C8.5,5.85 7.8,6.29 7.8,7.5C7.8,8.7 8.42,10.45 9.77,10.45C9.83,10.45 11.2,10.44 11.2,8.87Z"></path>
</symbol>
</defs>
</svg>
<div id="share">
<svg class="icon"><use xlink:href="#icon-facebook-box" /></svg>
<svg class="icon"><use xlink:href="#icon-twitter-box" /></svg>
<svg class="icon"><use xlink:href="#icon-google-plus-box" /></svg>
</div>
</body>
</html>
<?php
ob_start();
$color = '#0000ff';
include('icons.svg.php');
$icons = ob_get_contents();
ob_end_clean();
?>
<!DOCTYPE html>
<html>
<head>
<title>Svg with Php</title>
<style>
.icon {
width: 64px;
height: 64px;
}
</style>
</head>
<body>
<?php echo $icons; ?>
<div id="share">
<svg class="icon"><use xlink:href="#icon-facebook-box" /></svg>
<svg class="icon"><use xlink:href="#icon-twitter-box" /></svg>
<svg class="icon"><use xlink:href="#icon-google-plus-box" /></svg>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment