Outils pour utilisateurs

Outils du site


issue172:inkscape

Ceci est une ancienne révision du document !


Drawing with Inkscape – Part 112 By Mark Crutch

I’m going to start this month with yet another complaint about the state of font support in web browsers. Once again, a single browser vendor has effectively scuppered a format that is supported by their peers, leaving us users and developers without a practical alternative. I’ve written in the past about how Firefox’s lack of support for SVG fonts effectively killed the format. This was a real blow: the ability for a web developer to dynamically modify fonts on-the-fly using JavaScript could have been truly revolutionary. More recently, it looked like SVG in OpenType would provide some new capabilities in terms of color fonts and bitmap support, but Google has closed the relevant issue on the Chromium bug tracker (#306078) with a status of WONTFIX, indicating that they won’t be adding support for this format to the browser. Given Chrome’s dominant market share, this effectively neuters some of the new font support in Inkscape 1.0 that I covered in part 108 of this series. Variable fonts, as described in that article, already work and will continue to do so. It’s the SVG in OpenType format that is now effectively dead, despite being supported in Firefox, Safari and even older versions of Edge. My own experiments suggested some level of support for the fonts I was using (e.g. the Gilbert Color font was rendered in Chrome, but only as a monochrome font). I now suspect that was due to the fonts themselves providing non-SVG fallback content, rather than Chrome providing any support at all for this format.

What’s most disheartening about this development is that Google’s primary reason for not supporting SVG in OpenType appears to be that they are developing their own format for color fonts (again, embedded into OpenType). If you were in any doubt that Google might use their market dominance to force the direction of web standards, perhaps this will make you realise that a single vendor having so much control is not really in the best interest of the users. The need for multiple, independent rendering engines is the reason I continue to use Firefox as my daily driver. The battle against IE may have been won, but the war for a truly open and independent web still wages. Time will tell whether or not Google’s new format will win out, or font foundries will just embed both the Google and the SVG versions of color glyphs into ever-more-bloated font files. For now, however, despite Inkscape’s support for color fonts – and its partial support for bitmap fonts – you might want to think twice about using these in your projects.

CSS in SVG The main topic for this month was supposed to be the Selectors and CSS dialog that was added experimentally in Inkscape v1.0, and then promoted to non-experimental in v1.0.1. But in order to understand what this dialog does, it’s essential to first have a decent grounding in how CSS works in a stand-alone SVG file. This month’s article will put in that ground work – if you’re already a CSS aficionado, then you may want to skip this one and come back next month for the details of the dialog. Let’s begin with some history. The SVG format has always been a little confused about its identity. It was created during the great XML uprising of the late 1990s, when the World Wide Web Consortium (W3C) were pushing for a world in which XML formed a common basis for many file formats, allowing for tools and workflows that could easily combine and convert different types of data. SVG was a stand-alone vector format, not yet directly integrated into any web browsers, but the intention was clear that it should conform to, and work with, existing web standards. This left it with something of a dichotomy: on the one hand, it needed a way to directly define fonts, colors and dimensions in order to be used as a generic vector format with no dependency on a browser engine; on the other hand, it had to work well with the growing power of CSS to define styles for those users who did want to work in a more web-focused way.

And so we have ended up with a profusion, and confusion, of ways to style SVG content. First there are the classic “presentation attributes” from the SVG format. These are attributes that can be applied directly to SVG elements in order to style them individually. For example, a red rectangle with a thick black border might be defined like this: <rect x=“20” y=“20” width=“100” height=“100” fill=“red” stroke=“black” stroke-width=“10” /> This approach requires only the consuming program to understand XML and SVG, and doesn’t impose the need for a complete CSS parser (though things like color values and most units are still taken from the CSS spec).

In the early days of HTML, presentation attributes were common there, too. Veteran web developers might remember the “border”, “color” and “bgcolor” attributes, amongst others, but those capabilities were rapidly subsumed by the growing scope of CSS. In order to override CSS styles on a per-element basis, the relevant CSS rules had to be combined into a single “style” attribute. This method also works with SVG, meaning that our thick-stroked red rectangle could also be written like this: <rect x=“20” y=“20” width=“100” height=“100” style=“fill: red; stroke: black; stroke-width: 10;” /> If CSS only offered a way to put all the style information into a single attribute, it wouldn’t be terribly useful. But as well as setting styles on each element individually, CSS also offers a mechanism for applying styles across an entire document (or even across multiple documents, but that doesn’t work with Inkscape). It makes it trivial to give all your rectangles the same fill color; or to divide your objects into common classes that share similar styles; or to add override rules that make, for example, the third rectangle in a group have a different stroke width to the others.

Dans les premiers temps du HTML, les attributs de présentation étaient courants. Les développeurs Web chevronnés se souviennent peut-être des attributs « border », « color » et « bgcolor », entre autres, mais ces fonctionnalités ont rapidement été supplantées par la portée croissante de CSS. Afin de remplacer les styles CSS par élément, les règles CSS pertinentes ont dû être combinées en un seul attribut « style ». Cette méthode fonctionne également avec le SVG, ce qui signifie que notre rectangle rouge à traits épais pourrait également être écrit comme ceci : <rect x=“20” y=“20”

width="100" height="100"
style="fill : red ; stroke : black ; stroke-width : 10 ;"

/>

Si CSS ne proposait qu'un moyen de placer toutes les informations de style dans un seul attribut, il ne serait pas très utile. Mais en plus de définir des styles individuellement pour chaque élément, CSS offre également un mécanisme pour appliquer des styles à l'ensemble d'un document (ou même à plusieurs documents, mais cela ne fonctionne pas avec Inkscape). Il est ainsi facile de donner à tous vos rectangles la même couleur de remplissage, de diviser vos objets en classes communes qui partagent des styles similaires, ou d'ajouter des règles de remplacement qui font que, par exemple, le troisième rectangle d'un groupe a une largeur de trait différente de celle des autres.

These tricks are achieved by moving the style information out of the style attributes, and into a common stylesheet in a <style> element. The style attribute still applies, and will override the stylesheet, as shown in this abridged example where both the <rect> elements share the same fill color, stroke width, and their width and height, but have a different stroke color: <style> rect { fill: red; stroke-width: 10; width: 100; height: 100; } </style> <rect x=“20” y=“20” style=“stroke: black;” /> <rect x=“60” y=“60” style=“stroke: darkred;” /> Notice that the syntax of the stylesheet is quite different to that of the SVG content. I won’t go into details about how to write CSS here, but suffice to say that it’s made up of multiple rules (delimited by curly braces: { and } ), with each rule starting with a “selector” that determines what elements the rule will apply to. In this case, the selector is just the string “rect” which will make this rule apply to all the <rect> elements in the document.

Ces astuces sont réalisées en déplaçant les informations de style hors des attributs de style, dans un élément <style> dans une feuille de style commune. L'attribut de style s'applique toujours, et remplacera la feuille de style, comme le montre cet exemple abrégé où les deux éléments <rect> partagent les mêmes couleur de remplissage et largeur du trait, ainsi que leur largeur et leur hauteur, mais ont des couleurs de trait différentes : <style>

rect {
  fill : red ;
  stroke-width : 10 ;
  width : 100 ;
  hauteur : 100 ;
}

</style>

<rect x=“20” y=“20”

style="stroke : black ;"

/> <rect x=“60” y=“60”

style="stroke : darkred ;"

/>

Remarquez que la syntaxe de la feuille de style est très différente de celle du contenu SVG. Je n'entrerai pas dans les détails de l'écriture d'une feuille de style CSS ici, mais il suffit de dire qu'elle est composée de plusieurs règles (délimitées par des accolades : { et } ), chaque règle commençant par un « sélecteur » qui détermine les éléments auxquels la règle s'applique. Dans ce cas, le sélecteur est simplement la chaîne « rect », ce qui signifie que la règle s'appliquera à tous les éléments <rect> du document.

We can target a specific element by ensuring it has an “id” attribute in the SVG content (which Inkscape does by default), then using that ID, prefixed with a hash character (#), as our selector. In this next example, we have three rectangles which all share a common base style, but one of them has its fill color overridden in this way. <style> rect { fill: red; stroke: black; stroke-width: 10; width: 100; height: 100; } #r2 { fill: blue; } </style> <rect id=“r1” x=“20” y=“20” /> <rect id=“r2” x=“60” y=“60” /> <rect id=“r3” x=“100” y=“100” /> We can also target multiple items by giving them the same value in a “class” attribute and using it preceded by a dot (.) as the CSS selector. This example has four rectangles, split into two different classes. Note that an element can have more than one class, separated by spaces, which allows for a huge amount of flexibility in combining objects into overlapping sets.

Nous pouvons cibler un élément spécifique en nous assurant qu'il possède un attribut « “id » dans le contenu du SVG (ce qu'Inkscape fait par défaut), puis en utilisant cet ID, préfixé par un caractère dièse (#), comme sélecteur. Dans cet exemple, nous avons trois rectangles qui partagent tous un style de base commun, mais l'un d'entre eux a sa couleur de remplissage surchargée de cette façon :

<style>

rect {
  fill : red ;
  stroke : black ;
  stroke-width : 10 ;
  largeur : 100 ;
  hauteur : 100 ;
}
#r2 {
  remplissage : bleu ;
}

</style>

<rect

id="r1"
x="20" y="20"

/> <rect

id="r2"
x="60" y="60"

/> <rect

id="r3"
x="100" y="100"

/>

Nous pouvons également cibler plusieurs éléments en leur donnant la même valeur dans un attribut « class » et en l'utilisant précédé d'un point (.) comme sélecteur CSS. Cet exemple comporte quatre rectangles, répartis en deux classes différentes. Notez qu'un élément peut avoir plus d'une classe, séparée par des espaces, ce qui permet une grande flexibilité dans la combinaison d'objets en ensembles superposés.

<style> rect { stroke: black; stroke-width: 10; width: 100; height: 100; } .important { fill: red; } .warning { fill: orange; } </style> <rect class=“important” x=“20” y=“20” /> <rect class=“warning” x=“60” y=“60” /> <rect class=“important high” x=“100” y=“100” /> <rect class=“p3 warning low” x=“140” y=“140” /> CSS in web browsers also provides attribute selectors. These give the ability to select elements based on the presence, and optionally the value, of specific attributes on the elements. This would be particularly useful when dealing with some of Inkscape’s native objects, some of which are implemented as <path> elements, with a custom attribute to tell Inkscape which sort of native objects they are. Similarly, groups and layers are both implemented as SVG <g> elements, with an Inkscape-specific attribute indicating which ones are layers, so this would offer a means to distinguish between them in CSS selectors. Unfortunately it appears that the Selectors and CSS dialog doesn’t recognise the syntax for attribute selectors, so I shan’t consider it further here.

<style>

rect {
  stroke: black;
  stroke-width: 10;
  width: 100;
  height: 100;
}
.important {
  fill: red;
}
.warning {
  fill: orange;
}

</style>

<rect

class="important"
x="20" y="20"

/> <rect

class="warning"
x="60" y="60"

/> <rect

class="important high"
x="100" y="100"

/> <rect

class="p3 warning low"
x="140" y="140"

/>

Les CSS des navigateurs Web fournissent également des sélecteurs d'attributs. Ceux-ci donnent la possibilité de sélectionner des éléments en fonction de la présence, et éventuellement de la valeur, d'attributs spécifiques sur les éléments. Cela serait particulièrement utile pour traiter certains objets natifs d'Inkscape, dont certains sont implémentés comme des éléments <path>, avec un attribut personnalisé pour indiquer à Inkscape de quelle sorte d'objets natifs il s'agit. De même, les groupes et les couches sont tous deux implémentés comme des éléments SVG <g>, avec un attribut spécifique à Inkscape indiquant lesquels sont des calques, ce qui offrirait donc un moyen de les distinguer dans les sélecteurs CSS. Malheureusement, il semble que la boîte de dialogue Sélecteurs et CSS ne reconnaisse pas la syntaxe des sélecteurs d'attributs, aussi je n'y réfléchirai pas davantage ici.

These basic selectors can be combined to further refine the elements that will match. Using “rect.important”, for example, would only match <rect> elements with a class of “important”. It would not match <rect class=“warning”> or <path class=“important”>. In a similar manner, “#r1.high.important” would only match the element with an id of “r1” if it also had both the “important” and “high” classes assigned. The browser provides some classes for free, in the form of “pseudo-classes” which allow you to create selectors that target things that the browser calculates at runtime. These may change dynamically, especially if your page uses JavaScript to manipulate the document. Most of them aren’t applicable to the non-dynamic world of Inkscape, but some relate to the order in which elements appear in the document model, and do work in a limited manner in the Selectors and CSS dialog. For example, a selector of “rect:first-child” would select any <rect> element that is the first child of its parent (e.g. the first element inside a group). Inkscape doesn’t quite allow this syntax, though, but there is a workaround. I’ll take a deeper dive into pseudo-elements and how to work with them in Inkscape as we progress with the Selectors and CSS dialog. Selectors can be combined in different ways to match more elements, or to further refine the match based on the hierarchical structure of the SVG document. “#id1, #id2, .important” would match the two elements with the specified IDs, but also any element with the “important” class. “text + path”, meanwhile, would match any <path> element that is an immediate sibling of a <text> element. That one can be useful for styling any underlines you’ve drawn with your text elements, for example.

Ces sélecteurs de base peuvent être combinés pour affiner davantage les éléments qui correspondent. L'utilisation de « rect.important », par exemple, ne correspondrait qu'aux éléments <rect> dont la classe est « important”. Elle ne correspondrait pas à <rect class=“warning”> ou <path class=“important”>. De la même manière, “#r1.high.important” ne correspondrait à l'élément dont l'id est “r1” que si les classes “important » et « high » lui sont également attribuées.

Le navigateur fournit gratuitement certaines classes, sous la forme de « pseudo-classes », qui vous permettent de créer des sélecteurs ciblant des éléments que le navigateur calcule au moment de l'exécution. Ces éléments peuvent changer de façon dynamique, notamment si votre page utilise JavaScript pour manipuler le document. La plupart d'entre eux ne sont pas applicables au monde non dynamique d'Inkscape, mais certains concernent l'ordre dans lequel les éléments apparaissent dans le modèle de document, et fonctionnent de manière limitée dans la boîte de dialogue Sélecteurs et CSS. Par exemple, un sélecteur « rect:first-child » sélectionnerait tout élément <rect> qui est le premier enfant de son parent (par exemple, le premier élément à l'intérieur d'un groupe). Inkscape ne permet pas tout à fait cette syntaxe, cependant, mais il existe une solution de contournement. J'approfondirai les pseudo-éléments et la façon de les utiliser dans Inkscape au fur et à mesure que nous progresserons dans la boîte de dialogue Sélecteurs et CSS.

Les sélecteurs peuvent être combinés de différentes manières pour faire correspondre plus d'éléments, ou pour affiner la correspondance en fonction de la structure hiérarchique du document SVG. « #id1, #id2, .important » correspondrait aux deux éléments avec les ID spécifiés, mais aussi à tout élément avec la classe « important ». « text + path », quant à lui, correspondrait à tout élément <path> qui est un frère immédiat d'un élément <text>. Celui-là peut être utile pour styliser tout soulignement que vous avez dessiné avec vos éléments de texte, par exemple.

A simple space character creates a rule that matches if the second element is a descendent (possibly even a deeply nested descendent) of the first. E.g. “g.primary rect” matches a <rect> that is somewhere inside a group with a class of “primary”. On the other hand, “g.primary > rect” would only match the <rect> if it’s an immediate child of the primary group, not if it’s nested further inside other groups. With the information from the last few paragraphs, see if you can make sense of this example file: <style> rect { stroke: black; stroke-width: 10; width: 100; height: 100; } g.primary rect { fill: yellow; } g.primary > rect { fill: green; } g > rect:first-child { fill: purple; } </style> <g class=“primary”> <rect x=“20” y=“20” /> <rect x=“60” y=“60” /> <g transform=“translate(200)”> <rect x=“20” y=“20” /> <rect x=“60” y=“60” /> </g> </g> There’s even more to CSS than the rules I’ve laid out here, but these are the ones that are most useful or relevant when working with the Selectors and CSS dialog. Even so, it’s a lot to take on board if you’re not already familiar with CSS. Next month, it will hopefully start to make a bit more sense as we begin our look at the new dialog.

Un simple caractère espace crée une règle qui correspond si le deuxième élément est un descendant (éventuellement même un descendant profondément imbriqué) du premier. Par exemple, “g.primary rect” correspond à un <rect> qui se trouve quelque part à l'intérieur d'un groupe dont la classe est “primary”. D'autre part, “g.primary > rect” ne correspondrait au <rect> que s'il est un enfant immédiat du groupe primaire, et non s'il est imbriqué plus loin dans d'autres groupes.

Avec les informations des derniers paragraphes, voyez si vous pouvez donner un sens à ce fichier d'exemple : <style>

rect {
  stroke: black;
  stroke-width: 10;
  width: 100;
  height: 100;
}
g.primary rect {
  fill: yellow;
}
g.primary > rect {
  fill: green;
}
g > rect:first-child {
  fill: purple;
}

</style>

<g class=“primary”>

<rect x="20" y="20" />
<rect x="60" y="60" />

<g transform="translate(200)">
  <rect x="20" y="20" />
  <rect x="60" y="60" />
</g>

</g>

Les règles CSS ne se limitent pas à celles que j'ai exposées ici, mais ce sont celles qui sont les plus utiles ou pertinentes lorsque vous travaillez avec la boîte de dialogue Sélecteurs et CSS. Malgré tout, il y a beaucoup de choses à assimiler si vous n'êtes pas déjà familier avec CSS. Le mois prochain, nous espérons que tout cela aura un peu plus de sens lorsque nous commencerons à examiner la nouvelle boîte de dialogue.

issue172/inkscape.1630331118.txt.gz · Dernière modification : 2021/08/30 15:45 de d52fr