Attention : Le contenu de ces pages n'a pas été mis à jour depuis longtemps. Il est probablement obsolète pour Firefox 4.0/Gecko 4.0 et supérieur. Pour du contenu plus récent, allez consulter developer.mozilla.org.

Modele de boite

Cette partie explique comment fonctionne le modèle de boîte dans Xul, c'est à dire, comment on positionne les composants graphiques d'un écran Xul.

Définition d'une boîte

Une boîte est un élément XUL qui contient d'autres éléments XUL. On peut l'appeler aussi conteneur (ou « container »). Elle permet de regrouper les éléments et de les afficher selon une orientation, un alignement, une direction et un type de regroupement défini. La plupart des éléments XUL sont des conteneurs, à commencer par <window>, <dialog>, <box>, <vbox>, <hbox>, etc. Tous les exemples qui suivent sont donc appliquables à la plupart des éléments XUL.

Orientation des éléments dans une boîte

Il y a un élément XUL générique,box, pour définir une boîte. Il possède entre autres choses un attribut orient, qui permet de définir l'orientation de l'alignement des éléments qui le contiennent :

;orient="vertical": les éléments sont disposés verticalement ;orient="horizontal": les éléments sont disposés horizontalement

Par défaut (si l'attribut orient n'est pas défini), l'orientation est horizontale.

Il existe deux autres éléments pour faire des boîtes, qui ont une disposition prédéfinie :

  • hbox pour contenir des éléments horizontalement (hbox pour « horizontal box »)
  • vbox pour contenir des éléments verticalement (vbox pour « vertical box »)

Chaque élément XUL peut lui-même contenir d'autres éléments XUL, et donc se comporter comme une boîte.

Direction des éléments dans une boîte

On peut indiquer la direction dans laquelle les éléments vont être disposés grâce à l'attribut dir du conteneur.

;dir="ltr": (valeur par défaut) les éléments sont disposés de la gauche vers la droite si l'orientation est horizontale (orient = "horizontal" ou <hbox>) ou du haut vers le bas si l'orientation est verticale (orient = "vertical" ou <vbox>). ;dir="rtl": les éléments sont disposés de la droite vers la gauche ou du bas vers le haut suivant l'orientation.

Note mnémotechnique : « ltr » signifie « left to right », c'est à dire « gauche à droite ». « rtl » signifie « right to left », c'est à dire « droite à gauche ».

Définir la taille d'une boîte

Il y a quatre manières de définir la taille (hauteur et largeur) d'un élément :

automatique
La taille de la boîte s'adapte à celle de son contenu. C'est le comportement par défaut. La boîte, en d'autres termes, aura la plus petite taille possible par rapport à ce qu'elle contient.
flexible
La taille de la boîte est « flexible », elle s'adapte au contexte, aux autres boîtes qui l'entourent, dans leur container, qui peut être la fenêtre elle-même (cf. plus loin).
;forcée par le conteneur: La taille peut être influencée par les attibuts align, pack et crop du conteneur de la boîte.
fixe
Il est possible de définir une hauteur (height) et une largeur (width) grâce aux attributs width et height de l'élément, soit dans la balise elle-même soit, et c'est une meilleure solution, par le biais des feuilles de styles CSS (avec les mêmes attributs width et height). Si l'on ne spécifie qu'une seule valeur (la hauteur ou la largeur), l'autre prendra une valeur par défaut. Cette façon de spécifier une taille est à proscrire car elle « casse » le modèle de boîte XUL. À n'utiliser que pour des cas particuliers, par exemple avec les calques (stack).

Flexibilité

Le modèle de boîte XUL pourrait être comparé à celui que l'on trouve souvent dans le monde unix, pour le système X, comme par exemple dans le gestionnaire de fenêtre Motif.

Il permet de définir la taille des boîtes, non pas avec des valeurs fixes, mais en indiquant des proportions. Ainsi l'agencement des boîtes dans une fenêtre se fait automatiquement en fonction de la dimension de la fenêtre, de l'apparition ou disparition d'autres éléments d'interface. Le système s'arrange toujours pour que les éléments gardent les mêmes proportions indiquées lors de la construction de l'interface.

L'attribut flex permet de spécifier ces proportions ou, plus justement, la flexibilité de l'élément. Il contient une valeur entière sans unité, déterminant la taille relativement aux tailles et la flexibilité des boîtes voisines (des boîtes sœurs). Cette proportion agit soit sur la hauteur, soit sur la largeur, en fonction de l'orientation définie par la boîte parente (le conteneur).

Dans cet exemple, les flexibilités définies pour A, B, C s'appliqueront à leur hauteur, puisque la boîte parente est une boîte verticale (vbox).

 <vbox>
   <box id="A" flex="1"/>
   <box id="B" flex="1" />
   <box id="C" flex="1"/>
 </vbox>

Dans cet autre exemple, les flexibilités définies pour A, B, C s'appliqueront à leur largeur, puisque la boîte parente est une boîte horizontale (hbox).

 <hbox>
    <box id="A" flex="1"/>
    <box id="B" flex="1" />
    <box id="C" flex="1"/>
 </hbox>

Notez pour commencer que la taille de ces trois boîtes peut être différente, principalement en fonction de leur contenu respectif. C'est la raison pour laquelle ce flex ne doit pas être confondu avec la définition d'une proportion de taille.

Définir le flex des boîtes A, B et C à 1, cela signifie qu'elles réagiront toutes trois de la même façon lorsque, par exemple, la taille de leur conteneur sera modifiée.

Un exemple : Imaginons que nos trois boîtes aient pour parent la fenêtre elle-même :

 <window orient="horizontal">
    <box id="A" flex="1"/>
    <box id="B" flex="1" />
    <box id="C" flex="1"/>
 </window

Imaginons, que la boîte A ait une largeur « naturelle » de 100 pixels (déterminée par son contenu, p.e. une image qui mesure 100px sur 100px). Imaginons que la boîte B, qui contient un texte court, ait une largeur « naturelle » de 20 pixels, et que la boîte C, qui ne contient qu'un menu, ait une largeur « naturelle » de 40 pixels. Récapitulons :

  • Boîte A : 100px
  • Boîte B : 20px
  • Boîte C : 40px

Imaginons à présent que l'utilisateur modifie la taille de sa fenêtre, en la rétrécissant, en largeur, de moitié. Puisque la flexibilité des trois boîtes est égale, les trois boîtes réagiront de la même façon à ce rétrécissement. Leurs nouvelles largeurs seront :

  • Boîte A : 50px (100 / 2)
  • Boîte B : 10px (20 / 2)
  • Boîte C : 20px (40 / 2)

Notez que les boîtes réagiraient de la même façon si leur flex était à 5 :

 <vbox>
   <box id="A" flex="5"/>
   <box id="B" flex="5" />
   <box id="C" flex="5"/>
 </vbox>

Les flexibilités des boîtes sont intimement liées les unes aux autres.

À présent, si l'on modifie le flex d'une des boîtes, on modifie physiquement sa flexibilité. Mettre le flex de la boîte A à 3, par exemple, signifiera pour le générateur de rendu (choisissez la formule qui vous plaît ;-)):

  • A devra être 3 fois plus flexible que les deux autres boîtes,
  • Le container A sera 3 fois plus souple que les deux autres containers,
  • La boîte A réagira 3 fois plus que les deux autres boîtes aux changements de taille de leur container.

Vous pourrez voir ci-dessous comment calculer précisément cette flexibilité des boîtes.

Il se peut, dans certains cas, que le contenu d'une des boîtes impose une taille fixe ou une taille minimum ou maximum (avec les styles width, height, max-width, max-height…). De ce fait, selon la dimension de la boite parente (qui elle-même dépend de sa boîte parente etc. et donc par cascade, selon la dimension de la fenêtre), il est possible que les proportions ne soient pas toujours respectée (rappelez-vous qu'il s'agit plus de flexibilité que de proportion, même si les deux notions sont intimement liées). En effet, le moteur de rendu s'efforce de toujours faire en sorte que tous les éléments soient visibles, quelque soit la taille (bien sûr, quand la fenêtre atteint une taille minimum, il peut arriver qu'il ne soit plus possible de tout afficher).

Calcul des flexs

Calculer mathématiquement la flexibilité des boîtes est assez simple. On prend les valeurs des flexs des boîtes de même niveau (qui ont le même parent, ou boîtes adjacentes si vous préférez), on additionne ces flexs et cela nous donne un diviseur. Ensuite, pour obtenir la véritable proportion de chaque boîte, on divise leur flex par ce diviseur. Exemple :

 <vbox id="TOP" style="[[height:100px;"]]>
   <box id="A" flex="3"/>
   <box id="B" flex="5"/>
   <box id="C" flex="2"/>
 </vbox>

Le total des flexs vaut 10 (3 + 5 + 2). Par conséquent :

  • la boite A aura une hauteur prenant 3/10 de la hauteur totale de TOP (= 100 * (3/10) = 30 pixels),
  • la boite B aura une hauteur prenant 5/10 de la hauteur totale de TOP (= 100 * (5 / 10) = 100 * 1/2 = 50 pixels),
  • la boite C aura une hauteur prenant 2/10 de la hauteur totale de TOP (= 100 * (2 / 10) = 20 pixels).

Boîte avec ou sans flex ?

Il n'est pas necessaire de mettre un flex à chaque boîte, les boîtes ayant en priorité une taille au moins égale à celle de leur contenu. Mais il peut être interressant d'en mettre un sur certaines boites pour qu'elle prenne un maximum de place.

 <vbox id="TOP">
    <box id="A"/>
    <box id="B" flex="1" />
    <box id="C" />
 </vbox>

Ici il n'y a que la boîte B qui a un flex, les autres valant 0 par défaut. Si on suit les calculs, on aura alors :

  • la boite A aura une hauteur prenant 0/1 de la hauteur totale de TOP
  • la boite B aura une hauteur prenant 1/1 de la hauteur totale de TOP
  • la boite C aura une hauteur prenant 0/1 de la hauteur totale de TOP

On remarque donc que la boîte B prendra toute la hauteur de TOP dans l'idéal. En effet, A et C ayant probablement un contenu, elles auront donc une hauteur minimum imposée. Cela permet donc de dire que B devra prendre 100% de la place disponible (c'est à dire la place restant entre la boîte A et la boîte B).

Autre exemple :

  <vbox id="TOP">
    <box id="A"/>
    <box id="B" flex="1" />
    <box id="C" flex="1" />
  </vbox>

ici, B et C se partageront la hauteur restant sous la boîte A (puisque proportion de 1/2 chacune).

Attributs align, pack

Ces deux attributs permettent de préciser le positionnement des élèments dans une boite.

  • pack permet de positionner les élements, dans le sens de l'orientation
  • align permet de positionner les éléments dans le sens contraire de l'orientation (si l'orientation est horizontale, align permet de préciser le positionnement vertical des élements, et vice-versa).

Les valeurs possibles de pack sont "start", "center", "end".

  • si la boite est orientée horizontalement
    • "start" mettra tout les élements vers la gauche (valeur par défaut)
    • "center" mettra tout les elements vers le milieu
    • "end" mettra tout les élements vers la gauche
  • si la boite est orientée verticalement
    • "start" mettra tout les élements vers le haut (valeur par défaut)
    • "center" mettra tout les elements vers le milieu
    • "end" mettra tout les élements vers le bas

Pour en voir le résultat, cela implique qu'il n'y ait pas de flex sur les élements.

Les valeurs possibles de align sont "stretch", "start", "center", "end", "baseline"

  • si la boite est orientée horizontalement
    • "stretch" : les élements prendront toute la hauteur (valeur par défaut)
    • "start" mettra tout les élements vers le haut
    • "center" mettra tout les elements vers le milieu
    • "end" mettra tout les élements vers le bas
    • "baseline" mettra les élements au niveau de la "ligne de base"
  • si la boite est orientée verticalement
    • "stretch" : les élements prendront toute la largeur (valeur par défaut)
    • "start" mettra tout les élements vers la gauche
    • "center" mettra tout les elements vers le milieu
    • "end" mettra tout les élements vers la droite
    • "baseline" mettra les élements au niveau de la "ligne de base"

Attribut crop

Indique ce qu'il faut couper dans le contenu textuel, si celui ci est trop grand par rapport à la largeur du contenant.

Spacer

Un spacer n'est rien d'autre qu'une boîte vide, transparente, qui permet d'espacer les éléments. Tous les attributs décrits précédement s'appliquent, et tout particulièrement la flexibilité : on peut lui donner une taille proportionnelle à ses boîtes voisines. On pourra l'utiliser par exemple pour insérer un espace entre deux boîtes, calant chacune de ces deux boîtes aux extrémités de leur container : il suffit de mettre un flex="1" sur <spacer/>, et pas de flex sur les autres boîtes :

  <hbox id="mes-boutons">
    <button id="bouton-annulation" label="Annuler" />
    <spacer flex="1" />
    <button id="bouton-OK" label="OK" />
  </hbox>

Dans ce cas, si la boîte "mes-boutons" fait toute largeur de la fenêtre, le bouton « Annuler » se retrouvera tout à gauche et le bouton « OK » tout à droite (le spacer occupant pour sa part toute la place restante entre les deux boutons).

Exemple

Pour comprendre le rôle de tous les attributs et les différentes manières de positionner et spécifier les éléments, vous pouvez utiliser ce testeur de modèle de boîte : http://xulfr.org/sources/tutoriel/boite/(..)

Correspondance entre attributs et propriétés css

Les attributs que l'on a vu fixent en fait des styles CSS. On peut donc tout à fait mettre toutes ces propriétés d'agencement, non pas dans le fichier XUL, mais dans un fichier CSS. C'est fortement conseillé, pour séparer d'un côté le contenu et de l'autre l'aspect que doit prendre ce contenu dans la page.

Voici les équivalences

attribut XUL propriété CSS
flex -moz-box-flex
pack -moz-box-pack
align -moz-box-align
width width
height height

(crop ne semble pas avoir d'équivalent)

(à compléter)

Il faut savoir aussi que les éléments XUL ont une propriété CSS display:-moz-box

ToDo


Copyright © 2003-2013 association xulfr, 2013-2016 Laurent Jouanneau - Informations légales.

Mozilla® est une marque déposée de la fondation Mozilla.
Mozilla.org™, Firefox™, Thunderbird™, Mozilla Suite™ et XUL™ sont des marques de la fondation Mozilla.