Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Dans ce chapitre, nous allons voir plusieurs nouvelles propriétés CSS pour styliser vos formes (pointillés, "tiretés", etc.).
Nous ferons aussi l'apprentissage des marqueurs, qui sont utiles pour faire, par exemple, des flèches à la fin de vos lignes.
Propriétés de trait
Tout d'abord, faisons une petite révision des propriétés de trait que nous connaissons déjà.
stroke
Spécifie la couleur du trait.
Exemple :
Code : XML1
2 | ...
<circle r="20" cx="340" cy="230" style="fill:red;stroke:#3BD200;" />...
|
stroke-opacity
Indique l'opacité du trait :
Code : XML1
2
3 | ...
<circle r="20" cx="340" cy="230" style="fill:red;stroke:#3BD200;stroke-opacity:0.7;" />
...
|
C'est tout !

Voyons maintenant
LA propriété que -j'en suis sûr- vous attendiez depuis longtemps...
stroke-width
stroke-width est la propriété qui nous permettra de changer l'épaisseur du trait !
Comme valeur, vous devez indiquer une épaisseur en pixels :
Code : XML1
2
3 | ...
<circle r="20" cx="340" cy="230" style="fill:red;fill-opacity:0.6;stroke:#3BD200;stroke-width:3;" />
...
|
stroke-linecap
stroke-linecap est une propriété qui sert à indiquer la façon dont est dessinée la fin d'une ligne, d'une ligne brisée, ou d'un tracé. Trois valeurs sont possibles :
- butt (valeur par défaut) : la ligne s'arrête à ses extrémités (normal, non
) :
- round : un cercle est dessiné aux extrémités de la ligne :

Note : ce cercle est centré à la coordonnée de début ou de fin de la ligne, et son rayon est égal à la valeur de la propriété stroke-width de la forme divisée par 2 ;
- square : un carré est dessiné aux extrémités de la ligne :

Note : le carré est centré à la coordonnée de début ou de fin de la ligne, et son côté est égale à la valeur de la propriété stroke-width.
stroke-linejoin
Cette propriété spécifie comment seront dessinés les angles aigus d'un rectangle, d'un polygone, d'une ligne brisée ou d'un tracé. Encore une fois, trois valeurs possibles :
- bevel : les angles sont tronqués :

- round : les angles sont ronds :

- miter (valeur par défaut) : les angles sont pointus :

Mais...

Un seul des angles est pointu ! Les deux premiers sont tronqués !

Pourquoi donc ?

Moi, je m'attendais à ça :

...
stroke-miterlimit
Ce comportement est dû à la valeur par défaut d'une autre propriété :
stroke-miterlimit, qui est fixée à 4.
Si vous examinez bien cette image,
vous pouvez voir que les pointus des 2 premiers angles se prolongent bien plus loin que la valeur de la propriété
stroke-width (ici fixée à 8).
C'est pour cette raison que les créateurs du SVG ont introduit la propriété
stroke-miterlimit. Si vous l'ajoutez au style de votre forme et que vous lui mettez une valeur plus grande que 4 (par exemple 10) :
Code : XML1
2
3 | ...
<polyline points="50,50 60,90 70,45 80,85 100,75" style="fill:none;stroke:black;stroke-width:8;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:5;" />
...
|
les angles seront pointus jusqu'au bout, comme ceci :
stroke-dasharray
C'est la dernière propriété de trait dont je vous parle, et elle est ma foi très intéressante. Son nom signifie, en anglais, "tableau des tirets de la ligne", et c'est elle qui nous permettra de faire des tiretés et des pointillés avec nos lignes.
Tiretés
L'utilisation de
stroke-dasharray est un peu plus compliquée que les autres. Il y plusieurs façons d'indiquer sa valeur, mais commençons par la plus simple : vous allez mettre deux chiffres, séparés par une virgule.
Le premier chiffre indique la longueur du premier trait, le second chiffre, celui du premier espace. Le trait et l'espace sont ensuite répétés le long de la ligne.
Pour vous aider à bien assimiler, voici un code et son résultat, zoomé et annoté :
Code : XML1
2
3 | ...
<line x1="20" y1="200" x2="640" y2="200" style="fill:none;stroke:black;stroke-width:7;stroke-dasharray:10,20;" />
...
|
Remarquez que je n'utilise pas stroke-linejoin, car c'est une simple ligne et elle n'a donc pas d'angle, et je n'utilise pas stroke-linecap non plus, car je désire laisser la valeur butt, par défaut.
Résultat du code :
Ceci est une utilisation simple de
stroke-dasharray. Car vous pouvez lui mettre plus que deux valeurs, pourvu que
le nombre de valeurs soit pair :
Code : XML1
2
3 | ...
<line x1="20" y1="200" x2="640" y2="200" style="fill:none;stroke:black;stroke-width:7;stroke-dasharray:10,20,5,7;" />
...
|
C'est alors cette liste de valeurs qui sera répétée le long de la ligne.
Résultat du code :
Vous devez porter une attention plus particulière aux valeurs de stroke-dasharray lorsque vous utilisez cette propriété ainsi que stroke-linecap avec une valeur autre que butt (square ou round). En effet, rappelez-vous que ces deux valeurs tracent respectivement un carré et un cercle dont la moitié dépasse de la ligne.
Reprenons notre premier code, et rajoutons-lui la propriété
stroke-linecap, avec une valeur de
round :
Code : XML1
2
3 | ...
<line x1="20" y1="200" x2="640" y2="200" style="fill:none;stroke:black;stroke-width:7;stroke-linecap:round;stroke-dasharray:10,20;" />
...
|
Résultat du code (les cercles rouges indiquent où devraient se terminer les tirets si
stroke-linecap était fixé à
butt) :
Vous pouvez voir que les ronds augmentent la longueur des tirets, et empiètent dans les espaces, donc diminuent la longueur de ceux-ci.
Pour vous aider à avoir les longueurs que vous désirez vraiment, voici donc
les calculs à faire lorsque vous utilisez stroke-dasharray et stroke-linecap avec round ou square :
- pour les tirets : longueur voulue - valeur de stroke-width (car il faut additionner les 2 moitiés de stroke-width aux deux extrémités du tiret) ;
- pour les espaces : longueur voulue + valeur de stroke-width.
Effectuons ces calculs sur notre code :
- pour les tirets : 10 - 7 = 3 ;
- pour les espaces : 20 + 7 = 27.
Code : XML1
2
3 | ...
<line x1="20" y1="200" x2="640" y2="200" style="fill:none;stroke:black;stroke-width:7;stroke-linecap:round;stroke-dasharray:3,27;" />
...
|
Ce qui nous donne le résultat escompté :
Pointillés
Bien entendu, pour faire des pointillés sur une ligne, il faudra mettre
stroke-linecap à
round.
Ensuite, les plus futés d'entre vous auront compris que nous allons mettre 0 comme première valeur de
stroke-dasharray, et que nous allons laisser
stroke-linecap dessiner ses deux moitiés de cercle qui formeront un cercle complet.
Seulement, on a un petit problème.
Ce code (à titre d'exemple,
à ne pas essayer) :
Code : XML1
2
3 | ...
<line x1="20" y1="200" x2="640" y2="200" style="fill:none;stroke:black;stroke-width:7;stroke-linecap:round;stroke-dasharray:0,17;" />
...
|
qui fonctionne parfaitement sur IE :
bug complètement sur FF, à cause justement du 0 de
stroke-dasharray :
Donc, pour remédier à ce problème, que notre code soit compatible IE et FF et que nos cercles aient vraiment l'air de cercles, nous n'allons pas écrire 0 comme première valeur de
stroke-linecap. Mais nous allons écrire un nombre décimal très proche de 0, comme par exemple 0.01 !
Code : XML1
2
3 | ...
<line x1="20" y1="200" x2="640" y2="200" style="fill:none;stroke:black;stroke-width:7;stroke-linecap:round;stroke-dasharray:0.01,17;" />
...
|
Encore une fois, vous devez écrire votre nombre décimal avec un point et non une virgule.
Et ce code fonctionne sur Firefox !
Propriétés de remplissage
Petite révision...
fill
fill permet d'indiquer la couleur de remplissage d'une forme.
Ex :
Code : XML1
2
3 | ...
<circle r="20" cx="340" cy="230" style="fill:red;" />
...
|
fill-opacity
Cette propriété spécifie la transparence du remplissage d'une forme (valeur comprise entre 0 et 1) :
Code : XML1
2
3 | ...
<circle r="20" cx="340" cy="230" style="fill:red;fill-opacity:0.5;" />
...
|
C'est tout ce que nous avons vu jusqu'à maintenant. Voyons maintenant une nouvelle propriété !
fill-rule
fill-rule vous sera utile pour les polygones, les lignes brisées et les tracés. Elle sert à indiquer comment sera dessiné le remplissage d'une forme lorsqu'elle se coupe elle-même, ou lorsqu'un tracé possède des sous-tracés (quand vous avez plusieurs
movetos dans votre tracé).
Deux valeurs sont possibles :
L'algorithme mathématique qui spécifie si chaque point est en-dedans ou en-dehors du tracé est assez compliqué, c'est pourquoi je ne vous en fais pas part ici.
Exemples d'utilisation
Ce code :
Code : XML1
2
3 | ...
<path d="M104,42 Q49,92 23,170 Q77,85 161,77 C130,80 70,50 51,71 Q78,96 101,144 Q81,92 104,42 Z" style="fill:black;fill-opacity:0.5;fill-rule:nonzero;stroke:#A71212;stroke-width:5;stroke-linejoin:round;" />
...
|
produira ce résultat :
Tandis que ce code :
Code : XML1
2
3 | ...
<path d="M104,42 Q49,92 23,170 Q77,85 161,77 C130,80 70,50 51,71 Q78,96 101,144 Q81,92 104,42 Z" style="fill:black;fill-opacity:0.5;fill-rule:evenodd;stroke:#A71212;stroke-width:5;stroke-linejoin:round;" />
...
|
produira ce résultat :
Je vous recommande simplement d'essayer les deux valeurs, et si vous n'obtenez pas le résultat espéré avec les deux propriétés, essayez d'échanger les points de début et de fin de vos lignes et de vos courbes.
Par exemple, ce code :
Code : XML1
2
3 | ...
<line x1="20" y1="100" x2="640" y2="200" style="fill:none;stroke:black;stroke-width:7;" />
...
|
deviendrait comme ça :
Code : XML1
2
3 | ...
<line x1="640" y1="200" x2="20" y2="100" style="fill:none;stroke:black;stroke-width:7;" />
...
|
Je ne vous promets rien, mais ça peut aider parfois.
Comme je vous l'ai annoncé en introduisant le chapitre, les marqueurs nous permettront de faire des pointes de flèches à la fin et au début de nos lignes.
Mais les marqueurs ne nous permettent pas seulement de dessiner des flèches, car en fait, un marqueur est simplement une forme qui est dessinée au début ou à la fin d'une ligne. Vous pourrez donc dessiner des marqueurs en cercle, en losange, ou en coeur si ça vous chante !
Allons-y sans plus tarder !
Comme un marqueur est un élément que vous allez sûrement utiliser plusieurs fois dans votre document, j'espère que vous vous doutiez que nous allons le placer dans la balise <defs>.
Qu'allons-nous placer dans <defs> ?
Premièrement, nous allons placer une balise de marqueur, dans laquelle vous placerez la forme que vous voulez voir se dessiner à la fin de votre ligne. Cette balise est : <marker>...</marker>.
Ce qui nous donne donc ça :
Code : XML 1
2
3
4
5
6
7
8
9
10 | ...
<defs>
<marker>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;" />
...
|
Je place déjà la ligne à laquelle nous allons associer le marqueur tout à l'heure.
La première chose à faire est d'ajouter un id au marqueur, pour pouvoir l'appeler dans notre ligne, à l'aide de la propriété
marker-end. Elle aura pour effet de dessiner le marqueur à la fin de la ligne. Comme valeur, vous indiquez une référence d'URL vers l'id du marqueur.
Code : XML 1
2
3
4
5
6
7
8
9
10 | ...
<defs>
<marker id="Triangle">
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;marker-end:url(#Triangle);" />
...
|
Puis nous pouvons y ajouter une forme, je prendrai en exemple un simple triangle :
Code : XML 1
2
3
4
5
6
7
8
9
10
11 | ...
<defs>
<marker id="Triangle">
<path d="M0,0 l10,5 l-10,5 z" style="fill:red;fill-opacity:0.5;"/>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;marker-end:url(#Triangle);" />
...
|
Je diminue de moitié son opacité pour pouvoir mieux la distinguer de notre ligne plus tard.
Ensuite, nous devons indiquer la taille du marqueur. Pour ce faire, nous allons rajouter deux attributs à notre balise <marker> :
markerWidth, la largeur du marqueur et
markerHeight, la hauteur du marqueur.
Pour savoir quoi mettre dans ces attributs, vous devez trouver les dimensions du plus petit rectangle pouvant englober votre marqueur. C'est ce que j'appelle la boîte du marqueur.
Dans notre cas, le marqueur mesure 10*10 pixels, on écrira donc :
Code : XML 1
2
3
4
5
6
7
8
9
10
11 | ...
<defs>
<marker id="Triangle" markerWidth="10" markerHeight="10">
<path d="M0,0 l10,5 l-10,5 z" style="fill:red;fill-opacity:0.5;"/>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;marker-end:url(#Triangle);" />
...
|
Si vous indiquez une boîte du marqueur plus petite que l'espace que prend véritablement votre marqueur, votre marqueur ne sera pas redimensionné ; il sera tronqué. Vous pouvez l'essayer pour voir le résultat.
Mais il nous faut tout de suite rajouter un autre attribut,
markerUnits, qui servira à indiquer comment calculer les valeurs de
markerWidth et de
markerHeight. Deux valeurs sont possibles, mais pour l'instant nous allons mettre
userSpaceOnUse.
Code : XML 1
2
3
4
5
6
7
8
9
10
11 | ...
<defs>
<marker id="Triangle" markerWidth="10" markerHeight="10" markerUnits="userSpaceOnUse">
<path d="M0,0 l10,5 l-10,5 z" style="fill:red;fill-opacity:0.5;marker-end:url(#Triangle);"/>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;" />
...
|
Vous pouvez essayer ce code, mais vous verrez qu'il manque encore quelques ajustements.
Résultat du code, zoomé (le cercle rouge indique le point de fin de la ligne) :
- Le marqueur n'est pas orienté dans le sens de la ligne
- Le marqueur n'est pas centré sur la ligne
Pour remédier à la rotation du marqueur, nous allons ajouter un autre attribut à <marker>,
orient, avec une valeur de
auto. Ceci aura pour effet de l'orienter dans le sens de notre ligne :
Code : XML 1
2
3
4
5
6
7
8
9
10
11 | ...
<defs>
<marker id="Triangle" markerWidth="10" markerHeight="10" markerUnits="userSpaceOnUse" orient="auto">
<path d="M0,0 l10,5 l-10,5 z" style="fill:red;fill-opacity:0.5;"/>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;marker-end:url(#Triangle);" />
...
|
Résultat :
Remarquez qu'on aurait aussi pu écrire un angle de rotation pour le marqueur à la place de auto. (Ex. : orient="45" aurait fait pivoter le marqueur de 45°.)
Finalement, pour que notre marqueur soit centré sur notre ligne, nous allons utiliser deux autres attributs de <marker>,
refX et
refY. Ces deux attributs vont indiquer la coordonnée dans la boîte du marqueur qui doit s'aligner exactement avec le point de fin de ligne.
Dans notre cas, ce point est (0,5), on va donc écrire :
Code : XML 1
2
3
4
5
6
7
8
9
10
11 | ...
<defs>
<marker id="Triangle" markerWidth="10" markerHeight="10" markerUnits="userSpaceOnUse" orient="auto" refX="0" refY="5">
<path d="M0,0 l10,5 l-10,5 z" style="fill:red;fill-opacity:0.5;"/>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;marker-end:url(#Triangle);" />
...
|
Ce qui nous donne ce résultat :
Les propriétés de marqueurs
Nous avons vu que pour dessiner un marqueur à la fin d'une ligne, on utilisait la propriété
marker-end :
Code : XML 1
2
3
4
5
6
7
8
9
10
11 | ...
<defs>
<marker id="Triangle" markerWidth="10" markerHeight="10" markerUnits="userSpaceOnUse" orient="auto" refX="0" refY="5">
<path d="M0,0 l10,5 l-10,5 z" style="fill:red;fill-opacity:0.5;"/>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;marker-end:url(#Triangle);" />
...
|
Pour dessiner un marqueur au début d'une ligne, c'est la propriété
marker-start que nous allons utiliser :
Code : XML 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | ...
<defs>
<marker id="Cercle" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="10" markerHeight="10" orient="auto">
<circle cx="5" cy="5" r="5" style="fill:red;fill-opacity:0.5;" />
</marker>
<marker id="Triangle" markerWidth="10" markerHeight="10" markerUnits="userSpaceOnUse" orient="auto" refX="0" refY="5">
<path d="M0,0 l10,5 l-10,5 z" style="fill:red;fill-opacity:0.5;"/>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;marker-end:url(#Triangle);marker-start:url(#Cercle)" />
...
|
Remarquez que le point de référence (
refX,
refY) n'est pas le même pour le cercle, car je désire que ça soit son centre qui soit aligné avec le point de début de ligne :
Utilisation de markerUnits avec strokeWidth
Si on reprend notre code de tout à l'heure, et que nous lui rajoutons une deuxième ligne avec une valeur de
stroke-width différente, que l'on associe aussi au marqueur,
Code : XML 1
2
3
4
5
6
7
8
9
10
11
12
13 | ...
<defs>
<marker id="Triangle" markerWidth="10" markerHeight="10" markerUnits="userSpaceOnUse" orient="auto" refX="0" refY="5">
<path d="M0,0 l10,5 l-10,5 z" style="fill:red;fill-opacity:0.5;"/>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;marker-end:url(#Triangle);" />
<line x1="40" y1="250" x2="640" y2="250" style="stroke:black;stroke-width:14;marker-end:url(#Triangle);" />
...
|
vous pouvez voir que le marqueur reste de la même grandeur pour les deux lignes. Il serait intéressant qu'il change de grosseur en fonction de la propriété
stroke-width de la forme.
C'est possible en modifiant la valeur de l'attribut
markerUnits du marqueur. Nous allons fixer sa valeur à
strokeWidth, ce qui aura pour effet de multiplier les attributs
markerHeight, markerWidth, refX, refY, ainsi que le contenu du marqueur par la valeur de la propriété
stroke-width de la forme à laquelle le marqueur est associé.
Code : XML 1
2
3
4
5
6
7
8
9
10
11
12
13 | ...
<defs>
<marker id="Triangle" markerWidth="10" markerHeight="10" markerUnits="strokeWidth" orient="auto" refX="0" refY="5">
<path d="M0,0 l10,5 l-10,5 z" style="fill:red;fill-opacity:0.5;"/>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;marker-end:url(#Triangle);" />
<line x1="40" y1="250" x2="640" y2="250" style="stroke:black;stroke-width:12;marker-end:url(#Triangle);" />
...
|
Résultat (cliquez pour agrandir) :
Seulement voilà : à présent, nous n'avons plus la même proportion entre le marqueur et la ligne que lorsque nous mettions
markerUnits à
userSpaceOnUse, car le marqueur, d'une certaine façon, a été
dessiné pour userSpaceOnUse.
Pour remédier à ce problème, donc "convertir" notre marqueur de
userSpaceOnUse à
strokeWidth, il faut diviser les valeurs de
markerHeight, markerWidth, refX, refY ainsi que toute les coordonnées de la forme à l'intérieur du marqueur, par la valeur de
stroke-width de la ligne à laquelle le marqueur était associé (alors que l'attribut
markerUnits était à
userSpaceOnUse). (On peut arrondir 2 chiffres après la virgule.)
10 / 7 = 1.43
5 / 7 = 0.71
Ce qui nous donne ce code :
Code : XML 1
2
3
4
5
6
7
8
9
10
11
12
13 | ...
<defs>
<marker id="Triangle" refX="0" refY="0.71" markerUnits="strokeWidth" markerWidth="1.43" markerHeight="1.43" orient="auto">
<path d="M0,0 l1.43,0.71 l-1.43,0.71 z" style="fill:red;fill-opacity:0.5;"/>
</marker>
</defs>
<line x1="40" y1="50" x2="640" y2="200" style="stroke:black;stroke-width:7;marker-end:url(#Triangle);" />
<line x1="40" y1="250" x2="640" y2="250" style="stroke:black;stroke-width:12;marker-end:url(#Triangle);" />
...
|
Et le résultat escompté :
Allez, un petit exercice en terminant.

Allez revoir le marqueur en cercle que j'ai utilisé pour vous montrer la propriété
marker-start, et "convertissez-le" en
strokeWidth.
Si vous voulez vous exercer encore plus, inventez vos propre marqueurs !
Quelques idées : flèches plus effilées, coeur, pique, losange, carré... Les possibilités sont infinies !