Outils pour utilisateurs

Outils du site


issue141:inkscape

Over the past few months, we’ve looked at various tricks and effects that can be achieved when using an SVG file in a web page via the HTML <img> element. But using an SVG like that is subject to various security restrictions imposed by the browser, preventing you from referencing external files (fonts, css, linked bitmaps) or using JavaScript. So now we’re going to move on to alternative methods of using SVG in a web page, which offer a little more scope for customisation. This instalment will look at a little CSS trick for inheriting a color from your HTML page into your SVG. Unfortunately, the laws of CSS scoping mean that this one works only if you inline your SVG code right into your HTML. This requires some care and attention, but isn’t really that difficult, as you can largely copy and paste the contents of your SVG file from within a text editor. It does bloat the size of your HTML, but, conversely, you make a saving in not having a separate SVG image to download. Let’s start with a basic HTML page (top right).

Dans les derniers mois, nous avons regardé divers astuces et effets qui peuvent être réalisés en utilisant un fichier SVG dans une page Web via l'élément HTML <img>. Mais une telle utilisation d'un fichier SVG est soumise à diverses restrictions de sécurité imposées par le navigateur, vous empêchant de faire référence à des fichiers externes (polices, css, bitmap liés) ou d'utiliser du JavaScript. Aussi, maintenant, nous allons passer à d'autres méthodes d'utilisation du SVG dans une page Web, qui offrent un plus large espace à la personnalisation.

Cet article se penchera sur une petite astuce du CSS pour hériter d'une couleur de votre page HTML dans votre SVG. Malheureusement, les lois encadrant le CSS font que celui-ci ne marche que si vous intégrez correctement votre code SVG dans votre HTML. Ceci nécessite du soin et de l'attention, mais n'est pas vraiment difficile, car vous pouvez en grande partie copier/coller le contenu de votre fichier SVG à partir d'un éditeur de texte. La taille de votre fichier HTML va enfler, mais, en retour, vous gagnerez de la place en n'ayant pas à télécharger une image SVG séparée. Commençons avec une page HTML basique (en haut à droite).

Now we need some SVG to put into the file. For this demonstration, I created a simple rounded rectangle in Inkscape, then saved it as in “Optimised SVG” format to clear out a lot of the unnecessary metadata and other content. Even then, I was able to manually trim the resulting file a little further, as the namespace declaration isn’t required, and I was left with a single <g> wrapping the content which serves no purpose in this case. One option I did select in the save dialog was to “Convert CSS attributes to XML attributes”. This breaks down the otherwise densely filled “style” attribute into a series of individual presentation attributes. You don’t have to do that – this technique works just as well with the style attribute, or even a <style> section elsewhere in the XML – but having the styling split into separate attributes makes it a little clearer to explain what’s happening. The result of the export, manual trimming, and reformatting to fit the magazine, was the chunk of SVG shown below.

Nous avons besoin maintenant d'un SVG à mettre dans le fichier. Pour cette démonstration, j'ai créé dans Inkscape un simple rectangle aux angles arrondis, puis je l'ai sauvegardé dans le format « SVG optimisé » pour effacer un bon nombre de métadonnées sans utilité et d'autres contenus. J'ai même ensuite été capable d'affiner encore un peu plus le fichier résultant à la main, car la déclaration des noms d'espace n'est pas nécessaire et je me suis retrouvé avec un <g> unique encadrant du contenu qui n'a aucun intérêt dans ce cas-ci.

Dans le dialogue de sauvegarde, j'ai pris l'option « Convertir les attributs CSS en attributs XML ». Ceci divise l'attribut « style », autrement très densément rempli, en une série d'attributs de présentation individuels. Le faire n'est pas absolument nécessaire, car cette technique marche tout aussi bien avec l'attribut style, ou même une section <style> quelque part ailleurs dans le XML, mais l'éclatement du style dans des attributs séparés rend plus claires les explications sur ce qui se passe.

Le résultat de l'exportation, de l'affinage manuel et du reformatage pour s'adapter au magazine est le bout de SVG montré ci-dessous.

Copying this code and pasting it inside the <div> in the HTML file results, as you might expect, in the browser drawing a rounded rectangle, with a dark red fill. No surprises so far. The next step is to throw away the “color” attribute entirely: it’s not needed in SVG, where we already have fill and stroke colors, but if it’s left in place it will affect the CSS cascade and prevent the effect we’re trying to achieve. That effect is to get the SVG to use the current font color from the parent HTML page. We’ll use it for the fill in this case, so that our rectangle basically becomes a giant color swatch displaying the browser’s font color. To do this, we simply have to replace the value of the “fill” attribute with the keyword “currentColor” (note the spelling and capitalisation). Code is shown top right on this page.

Une copie de ce code et son collage dans le <div> du fichier HTML a pour résultat, comme vous pouvez vous y attendre, le dessin dans le navigateur d'un rectangle à angles arrondis, avec un remplissage rouge foncé. Pas de surprise jusque-là.

L'étape suivante est de se débarrasser entièrement de l'attribut « color » (couleur) : il n'est pas nécessaire dans le SVG, où nous avons déjà les couleurs de remplissage et de contour, mais, si nous le gardons, il aura un effet sur la cascade CSS et empêchera l'effet que nous voulons de se produire .

Cet effet est pour obliger le SVG d'utiliser la couleur de police en cours dans la page HTML parente. Dans ce cas, nous l'utiliserons pour le remplissage, de sorte que notre rectangle deviendra en gros un nuancier géant affichant la couleur de la police du navigateur. Pour ce faire, nous devons simplement remplacer la valeur de l'attribut « fill » (remplissage) par le mot-clé « currentColor » (noter l'orthographe et la majuscule). Le code est présenté en haut à droite de cette page.

Reloading the page will most likely show the rectangle filled with black. What else were you expecting? Black is the default color for text in an HTML page if you haven’t styled things differently. But we can change that by setting the CSS “color” property on the <svg> element or, crucially, one of its ancestors. For example, let’s change the <div>: <body> <div style=“color: red;”> <svg width=“250” height=“250”> … Now reloading the page in the browser gives the result shown below left.

Le rechargement de la page montrera sans doute le rectangle rempli de noir. Qu'attendiez-vous d'autre ? Le noir est la couleur par défaut du texte dans une page HTML si vous n'avez pas précisé d'autres éléments de style. Mais nous pouvons la changer en paramétrant correctement la propriété « color » du CSS dans l'élément <svg> ou, fondamentalement, l'un de ses ancêtres. Par exemple, changeons <div> :

<body>

<div style=“color: red;”>

<svg width=“250” height=“250”>

  ...

Maintenant, le rechargement de la page dans le navigateur présente le résultat montré ci-dessous à gauche.

You’d be forgiven for not getting terribly excited by this, but take a step back and think about what you’ve achieved: you’ve set a color inside your SVG content based on a CSS value in your HTML. Still not getting it? Let’s add an ID to the <rect> element, then create a couple more divs (below). In case you hadn’t guessed, the <use> element lets you re-use a snippet of SVG elsewhere, by referencing its ID in the fragment identifier part of the URL in the “href” attribute. In this case, we’re referencing an element in the same file, so we don’t need the full URL – just the fragment identifier (the ID preceded by a hash). So this code just tells the browser to render three copies of our <rect>, but the CSS in each <div>, combined with the use of currentColor in the SVG, results in some rather cubist looking traffic lights:

Vous serez pardonné de ne pas être terriblement enthousiasmé par ceci, mais, revenez un pas en arrière et pensez à ce que vous avez réalisé : vous avez fixé une couleur dans votre contenu SVG, basée sur une valeur du CSS de votre HTML. Vous ne comprenez toujours pas ? Ajoutons un identifiant (ID) dans l'élément <rect>, puis créons quelques sections <div> supplémentaires (ci-dessous).

Au cas où vous ne l'auriez pas deviné, l'élément <use> vous permet de réutiliser une bribe du SVG ailleurs, en référençant son ID dans la partie de l'URL faite pour l'identificateur de fragment, dans l'attribut « href ». Ici, nous faisons référence à un élément du même fichier ; aussi, nous n'avons pas besoin de l'URL complète, seulement l'identificateur de fragment (l'ID précédé d'un #). Ainsi, ce code dit simplement au navigateur de faire le rendu de trois copies de notre <rect> ; mais, avec le CSS de chaque <div>, en combinaison avec l'utilisation de currentColor dans le SVG, le résultat est un feu tricolore d'aspect cubiste.

Let’s put this to a more practical use. How about icons for a website? Here (shown right) I’ve created four icons, each in a separate layer in Inkscape, and given each layer a descriptive ID. The details of the paths are omitted for brevity. The “color” attributes are removed, and the fill or stroke color set to “currentColor” as necessary. Then the whole SVG block is hidden using CSS in the <svg> element. Now each individual icon in the set can be displayed on the page via a <use> element, with its size and color set on the SVG element that contains the <use>, or even on a parent element above that – as demonstrated with these couple of sections (next page, top right).

Faisons de ceci une utilisation plus pratique. Pourquoi pas des icônes pour un site Web ? Ici (voir à droite), j'ai créé quatre icônes, chacune sur un calque séparé dans Inkscape, et donné à chaque calque un ID descriptif. Les détails des chemins sont omis pour faire court. Les attributs « color » sont enlevés, et les couleurs de remplissage et de contour sont réglées sur « currentColor » comme il se doit. Ensuite, tout le bloc SVG est masqué en utilisant le CSS de l'élément <svg>.

Maintenant, chaque icône de cet ensemble peut être affichée individuellement sur la page via un élément <use>, avec sa taille et sa couleur définies dans l'élément SVG qui contient le <use>, ou même, dans l'élément parent qui est au-dessus de lui, comme démontré avec ces quelques sections (page suivante, en haut à droite).

Of course the color could be set at a much higher level on the page, so it needs to be set only once for the whole page – or you could use CSS variables for the same effect. Now a change to a single color will alter all the icons used on your page: you’ve just created a means of applying a theme. Because the CSS “color” property also affects the text on the page, you can ensure that your icons are kept in sync with the text, whichever theme is selected. As a demonstration, suppose we use a block like this several times (next page, bottom right). For each copy of this block, we’ll change the color values in the <div>. A little extra CSS adds a border that also has its color set to “currentColor”, and for some of the copies we’ll even put in a “background” property to produce an inverted look. Here’s the result of a few minutes of copying, pasting, and editing some CSS – all with only a single copy of the SVG icons, each referenced multiple times:

Bien sûr, la couleur pourrait être définie à un niveau beaucoup plus haut dans la page afin qu'elle ne doive l'être qu'une seule fois pour toute la page - ou vous pourriez utiliser des variables du CSS pour obtenir le même effet. Attention : la modification d'une seule couleur changera toutes les icônes utilisées sur votre page : vous venez de créer un moyen d'appliquer un thème. Comme la propriété « color » du CSS s'applique aussi au texte de la page, vous pouvez vous assurer que vos icônes restent synchronisées avec le texte, quel que soit le thème sélectionné. Pour le démontrer, supposez que nous utilisions plusieurs fois un bloc comme celui-ci (page suivante, en bas à droite).

Pour chaque copie de ce bloc, nous changerons les valeurs des couleurs dans <div>. Un petit supplément de CSS ajoute une bordure dont la couleur est aussi réglée sur « currentColor » et, pour certaines de ces copies, nous ajouterons même une propriété « background » pour produire un effet inversé. Voici le résultat de quelques minutes passées à copier, coller et modifier un peu de CSS - tout ça avec une copie unique des icônes SVG, chacune référencée plusieurs fois.

I’ll confess this trick of using currentColor in SVG is a limited one. The SVG has to be inlined with your HTML, and you can change only a single color. But, with a cleverly designed SVG file, it’s possible to give the impression of something more sophisticated – by masking the colored element with a gradient, or using a filter to alter the color, for example. There is one interesting thing to note about this technique: it will work in Internet Explorer right the way back to version 9! If you need to theme some icons on a website, but still need IE support (so no CSS variables), this might be just the trick you need.

Je dois avouer que cette astuce d'utiliser currentColor dans SVG a des limites. Le SVG doit être intégré dans votre HTML, et vous ne pouvez changer qu'une seule couleur. Mais, avec un fichier SVG intelligemment conçu, il est possible de donner l'impression de quelque chose de plus sophistiqué, en masquant l'élément coloré avec un dégradé ou en utilisant un filtre pour altérer la couleur, par exemple. Une chose est intéressante à noter à propos de cette technique : elle fonctionnera bien dans Internet Explorer, version 9 et supérieures! Si vous avez besoin d'appliquer un thème à quelques icônes dans un site Web, mais avez encore besoin de prendre IE en charge (donc sans variables CSS), celui-ci pourrait être l'astuce dont vous avez besoin.

issue141/inkscape.txt · Dernière modification : 2019/02/09 07:14 de andre_domenech