Jusqu’ici, notre code était très verbeux. Par exemple, même si plusieurs objets avaient les mêmes propriétés CSS, il fallait les écrire à chaque fois dans l’attribut style. De même, on ne pouvais pas réutiliser un carré déjà tracé pour le placer un peu plus loin et tourné. SVG bénéficiant des avantages de la syntaxe XML, il est facilement stylable avec CSS et fortement réutilisable grâce aux id. Au final, on peut très fortement optimiser un document SVG et lui faire adopter une structure logique qui facilitera toute modification du code.
SVG étant un langage XML, il est très facile de le styler avec CSS. Il existe quatre manière de styler un élément SVG :
Il existe tout un tas d’attributs de présentation pour styler un élément. Par exemple, pour avoir un carré rouge, on peut écrire :
On peut aussi utiliser stroke, stroke-width, fill-opacity, etc. Cependant, on oubliera vite ce mode de styling parcequ’il ne respecte pas la règle de séparation des données et de la présentation, allourdit le fichier, et tout simplement ne permet pas de profiter des avantages des CSS.
C’est grâce au style en ligne que nous avons stylé nos dessin jusqu’à maintenant. En effet, les balises SVG acceptent toutes l’attribut style dans lequel on spécifie les couples propriété/valeur séparés par des point-virgules.
À l’instar d’XHTML, SVG permet d’inclure une feuille de style interne grâce à la balise style placée comme premier enfant d’une balise SVG. On prendra le soin de placer tout cela dans une section CDATA, pour ne pas s’embêter avec les ', ", &, < et >. On devra aussi préciser que le style est du css, grâce à l’attribut type que nous fixerons à text/css qui est le type MIME de CSS.
Les sections CDATA font parti de la syntaxe de base de XML (1.0). Elles permettent d’éviter à l’auteur de devoir
échapper les caractères spéciaux XML. Par exemple, ceci créera une erreur car 10 < 20 est
considéré comme un début de balise :
<p>Hey les gars, 10 est inférieur à 20 ! En langage mathématique, on note 10 < 20 !</p>
On peut facilement échapper le texte en grâce à une section CDATA comme ceci :
<p><![CDATA[Hey les gars, 10 est inférieur à 20 ! En langage mathématique, on note 10 < 20 !]]></p>
Une section CDATA ne peut pas contenir la chaîne « ]]> ».
Par exemple, pour un même carré rouge :
Toutes les balises XML peuvent avoir les attributs id et class. En CSS, on désigne un id par le croisillon (#) et la classe par le point (.). Par exemple, circle#cadran désigne le cercle dont l’id est cadran et .red_stroke désigne tous les éléments qui ont un attribut class qui vaut red_stroke.
Avoir une feuille de style interne est très pratique car elle permet de styler facilement toute sorte d’éléments. Vous souvenez vous de notre première forme ? C’était un rectangle noir. Noir parceque par défaut, une forme est remplie en noir. CSS nous permet de fixer d’autres valeurs par défaut. Si, par exemple, on veut que toutes nos formes soient par défaut non remplies et avec une bordure violette de 3 pixels, on fera :
Le signe étoile (*) désigne, en CSS, tous les éléments présents. *{display:none;} n’affichera rien.
En général, on place style en début de page. On peut aussi préciser le média associé, grâce à l’attribut media qui peut prendre les valeurs suivantes :
Les types qui nous intéresserons principalement seront screen et print. Rien ne vous empêche d’avoir un élément style pour le média screen, un autre pour le média print, un troisième pour screen, etc.
Le seul inconvénient avec les feuilles de style internes, c’est qu’on ne peut pas proposer de feuilles de styles alternatives. Ce problème est résolu par l’utilisation de…
Pour utiliser des feuilles de style externes, il n’y a pas, comme en (X)HTML, de balise link : on doit donc utiliser la processing-instruction xml-stylesheet ….
La PI xml-stylesheet accepte 6 « attributs » :
Ces PI doivent être placées dans le prologue du document, c’est
à dire juste après le prologue XML. On pourrait donc écrire :
xml-stylesheet href="doc.css" type="text/css" title="Feuille de style principale, pour tous les medias"
charset="utf-8"
xml-stylesheet href="screen.css" type="text/css" title="Design clair" media="screen" charset="utf-8"
xml-stylesheet href="screen2.css" type="text/css" title="Design sombre" media="screen" charset="utf-8" alternate="yes"
xml-stylesheet href="print.css" type="text/css" title="Imprimer en couleurs claires" media="print" charset="Big5"
xml-stylesheet href="print2.css" type="text/css" title="Imprimer en couleurs sombres" media="print" charset="Big5"
alternate="yes"
Cette PI est malheureusement encore mal implémentée, notamment au niveau de
alternate.
Pour plus d’informations, lisez la spécification.
Dorénavant, on n’utilisera plus que cette méthode pour styler du SVG, tout simplement car c’est la méthode la plus flexible. Elle permet en outre de styler un nombre important de documents SVG grâce à un seul fichier. Reprenons notre carré rouge. Maintenant, on fera :
Et le CSS
Dans cet exemple, les deux fichiers sont bien sur dans le même dossier. Lorsqu’on voudra changer la couleur de notre rectangle, il suffira de modifier le fichier CSS : on n’aura pas besoin de toucher à la structure du fichier XML, comme on l’aurait fait avec des attributs de présentation. Puissant, non ?
Une « astuce », que beaucoup ne connaissent pas, à propos de CSS : il est possible de spécifier plusieurs classes pour un même élément. C’est très simple : on utilise toujours l’attribut class mais on sépare les noms des classes par une espace. Par exemple, on peut faire class="rempli-en-rouge bords-en-bleu".
Nous avons déjà vu que la racine d’un document SVG doit être l’élément svg. Il est néanmoins possible d’intégrer d’autres balises svg à l’intérieur du dessin. On peut donc écrire :
Pour rappel, les commentaires en CSS sont délimités par /* et */. Ils peuvent être placés n’importe où.
Rien de bien compliqué : le troisième svg est situé par rapport aux second svg. Ses coordonnées dans le premier svg sont donc 50+30,40+80 soit 80,120 (on ajoute les coordonnées des second et troisème svg).
Intéressons nous maintenant à la zone de dessin en elle même : si je vous demande comment on dessine le premier pixel (celui tout en haut à gauche), vous me répondez ? Ceux qui sont habitués à travailler sur du bitmap pensent sans doute qu’il faut écrire :
Et bien non ! En fait, les points de coordonées 1,1, 10,20, 400,300, etc ne désignent pas des pixels mais les intersections des lignes des abscisses et des ordonnées. Pour dessiner le pixel tout-en-haut-à-gauche, on devra faire :
Voici un schéma pour bien visualiser la chose.
Dans un dessin vectoriel, on a souvent besoin de réutiliser des formes déjà créées. À notre niveau, si on souhaite dessiner trois sapin, on devra à chaque fois redessiner toutes les formes en prenant soin de recalculer leurs coordonnées. SVG permet heureusement de regrouper plusieurs formes dans une seule balise dans le but de pouvoir réutiliser cette « brique graphique ». On utilisera la balise g.
Essayons d’abord de dessiner un sapin dans une balise g :
Je suis nul en dessin
Comme vous le voyez, la balise g ne change strictement rien : sans elle, il serait dessiné exactement la même chose. C’est maintenant que ça va devenir intéressant : il est possible de réutiliser ce dessin grâce à l’ élément use. use doit avoir un attribut xlink:href (qui appartient à l’espace de nommage XLink) qui pointe vers une balise g. On aura pris soin d’attribuer un id à notre brique graphique. L’élément use accepte aussi les attributs x et y mais nous allons plutôt nous servir de quelquechose que nous avons vu pour replacer notre brique : les transformations. Pour une meilleur lisibilité, on n’utlisera que l’attribut transform (et non pas x et y). Exemple avec des translations :
Tout simplement . Et ça marche aussi avec scale :
Le changement d’échelle a bien sur pour point d’origine le coin haut gauche de notre brique graphique. Essayons avec rotate, skewX et skewY :
Vous avez remarqué que la rotation ne s’est pas faite à partir du coin haut droit de la zone de dessin svg mais du point de coordonnées 0,0 de notre brique graphique g. C’est pourquoi il peut paraître utile de centrer notre dessin contenu dans notre g. C’est en fait très facile : il suffit d’utiliser des coordonnées négatives. Exemple :
Maintenant, on aimerais éviter le dessin en haut à gauche. En fait, on souhaite déclarer notre dessin sans l’afficher puis l’utiliser ensuite. SVG met a disposition la balise defs qui contient tout ce qu’on défini et qu’on souhaite utiliser ensuite. Les balises contenus dans defs ne seront donc jamais affichées directement. Dans notre cas, nous pouvons faire :
C’est aussi dans cette balise que nous stockerons les dégradés, les motifs, etc.
use étant une balise XML, on peut la styler comme les autres. Mais que va-t-on styler au juste puisque la balise use ne s’affiche pas à proprement parler ? Et bien c’est ce qui est appelé qui sera stylé, ou restylé pusqu’il aura déjà les styles appliqués sur lui avant :
En CSS, le sélecteur « + » est appelé « sélecteur d’enfants adjacent ».
Dans l’expression
balise1 + balise2, la balise concernée est balise2. On pourrait
traduire par toutes les balise2 précédées par un balise1.
Spécification
Je crois que cet exemple montre bien la simplicité de la programmation en SVG et la puissance de ce langage. Et vous n’avez encore rien vu .
Pour favoriser l’accessibilité, il peut être utile d’indiquer un titre et une description sur chaque élément de notre dessin. L’élément g accepte justement les attributs title et desc. Ne nous en privons pas : ça nous facilitera la relecture.
menant hors du contenu SVG
Il existe deux types de liens : les liens
menant hors du contenu SVG
et les liens
menant dans un contenu SVG
. À notre stade, nous ne
nous intéresserons pas au deuxième type de lien faisant appel à des connaissance que nous n’avons pas (encore).
SVG utilise XLink pour les liens. Comme en XHTML, l’élément qui permet de décrire un lien est a. Deux attributs nous seront utiles : xlink:href et xlink:title. Seuls les liens de type simple sont autorisés en SVG. On mettra les objets qu’on voudra lier dans la balise a. Exemple :
Il est impératif d’écrire l’attribut xlink:title même si certaines implémentations ne le rendent pas (notamment le viewer SVG d’Adobe, version 6 bêta). En effet, en XHTML, on a la plupart du temps du texte dans la balise a ce qui n’est pas toujours le cas en SVG. Ici, sans xlink:title, on ne sait pas où on va.
Il est possible d’afficher des images PNG, JPEG et SVG grâce à la balise image. Cet affichage se fait très simplement grâce aux attributs x et y, optionnels et par défaut à 0, width et height qui eux sont requis. Par défaut, le ratio de l’image est conservé, ce qui veut dire que si les attributs width et height renseigné dans le document SVG ne sont pas les mêmes que les longueur et largeur de l’image, elle ne sera pas étirée mais elle conservera son ratio et sera centrée à l’intérieur du rectangle de coordonnées (x,y), de longueur width et de hauteur height. Le lien vers l’image est réalisé via l’attribut xlink:href. Prenons par exemple cette image :
Ici, pas de problème : les longueurs sont respectées. Mais il peut en être autrement :
Le viewer d’Adobe semble ne pas supporter cette partie de la spécification.
On peut contrôler la manière dont la ratio est conservé ou décider qu’il ne doit pas être conservé, mais cela fait appel à des notions plutôt compliquées que nous verrons plus tard.
En attendant que xml:id soit reconnu par les parsers XML, il est possible d’attribuer à tous les éléments SVG l’attribut id. Il devient ainsi facile de manipuler un document XML via l’API DOM, avec le langage de script ECMAScript par exemple.
De même, l’attribut xml:base peut être appliqué à toutes les balises SVG. Cet attribut sert à désigner un chemin de base du tous les chemins relatifs enfants. En gros, lorsque vous vous affichez xlink:href="image.jpg", le navigateur va chercher l’image dans le répertoire dans lequel se situe le dessin SVG. Avec l’attribute xml:base, on ira chercher l’image spécifiée dans le répertoire indiqué par l’attribut.
Il deux autres attributs de l’espace de nommage xml : xml:lang et xml:space.
Pour le référencement, il est préférable d’indiquer la langue du document grâce à xml:lang, même si ce n’est pas obligatoire. Ensuite, on peut placer cet attribut sur les éléments susceptibles de contenir du texte. svg est bien susceptible de contenir du texte tandis que des balises comme rect ou ellipse n’en contiendrons jamais.
xml:space, tout comme xml:lang ne s’applique qu’aux éléments pouvant contenir du texte. Il accepte de valeurs : default (valeur par défaut) et preserve.
Nous reviendront sur ces deux attributs lors du chapitre traitant du texte.
Maintenant que nous savons bien organiser un document SVG, nous allons voir quelquechose de beaucoup plus compliqué : les paths .