documents

Introduction à la conception graphique Web
— Le positionnement —

Tous les utilisateurs novices de feuilles de style en cascade (CSS) en ont entendu parler, n'est-ce-pas ? Positionnement CSS absolu par-ci, relatif par-là. Vous avez peut-être une vague idée de ce que c'est mais n'osez pas vous lancer.

Faisons la lumière sur les sombres mystères du positionnement CSS. Si vous avez des compétences rudimentaires ou même moyennes en CSS, vous apprendrez l'essentiel pour maîtriser le positionnement, et ce n'est pas difficile une fois assimilés les principes fondamentaux derrière le concept.

Et d'un, et de deux, et de trois, et de quatre …

Il y a essentiellement un seul langage de balisage utilisable pour les document Web : HTML. (Des auteurs utilisent des déclarations de type de document XHTML, mais les documents devront quand même être servis en tant que HTML sous peine de ne pas fonctionner chez les utilisateurs majoritaires du navigateur Internet Explorer de Microsoft).

Il y a deux façons de définir la mise en pages visuelle d'un document HTML : les tables ou CSS. Les tables sont dépassées pour la mise en pages, elles sont déconseillées et nuisibles pour l'accessibilité, elles ne sont donc plus dans le coup.

Il y a trois façons de définir la mise en pages visuelle d'un document HTML avec des feuilles de style : les simili-tables, les flottants et le positionnement. Les simili-tables (avec display:table-cell, etc.) ne fonctionnent que dans les navigateurs les plus récents. Les flottants feront l'objet d'un prochain article, il nous reste donc le positionnement.

Il y a quatre types de positionnement dans CSS 2.1 : statique, relatif, absolu et fixe. En quoi sont-ils différents ? Vous le découvrirez plus loin. Lequel convient le mieux ? Cela dépend entièrement de vous.

Qu'y a-t-il dans un nom ?

Les noms des schémas de positionnements utilisés par le World Wide Web Consortium (W3C) peuvent être très ambigus, à moins de comprendre leur point de vue.

La plupart d'entre nous voyons cela du point de vue de la mise en pages, d'où des noms qui semblent assez insolites. Un élément statique ne l'est pas du tout, il se déplace lorsque nous faisons défiler la page. Un élément en position relative ne l'est que par rapport à lui-même. Un élément en position absolue ne l'est pas absolument mais relativement à un autre élément. Un élément fixe est à la fois en position absolue et en position statique.

Donc le W3C ne réussit un score que d'un sur quatre ? Non, il regarde ce tout avec une autre perspective : le document. Si nous le faisons aussi, tout s'explique. (Bon, c'est déjà un peu moins confus). Un élément statique est statique dans le flux du document. Un élément en position relative est relatif à lui-même en effet. Un élément en position absolue est absolu, par rapport à une autre boîte, et retiré du flux. Et un élément fixe est fixe par rapport au flux.

Fixer la valeur de la propriété position

Alors comment régler ce mystérieux positionnement ? La réponse se trouve dans la propriété position dans CSS, dont les valeurs légales sont les mots-clés static, relative, absolute et fixed, plus inherit. Les éléments descendants n'héritent pas la propriété position, mais nous pouvons forcer l'héritage avec position:inherit.

La propriété position s'aplique à tous les éléments, et nous pouvons donc l'utiliser avec des éléments de type bloc tels que div ou p, ou avec des éléments de type en-ligne tels que span ou em.

La valeur par défaut, si rien n'est indiqué, est static.

Avec les positionnements relatifs, absolus et fixes, cinq autres propriétés CSS sont intéressantes : les propriétés top, right, bottom, left et z-index. Les utilisations des quatre premières et leurs applications varient entre les trois schémas de positionnement, nous les examinerons de plus près lorsque ce sera le moment. Nous aborderons la propriété z-index à la fin de cet article.

Le positionnement statique

Un élément défini avec position:static, la valeur par défaut, n'est pas du tout positionné en réalité. Vous verrez rarement cette déclaration explicite. Le seul moment où il faudra l'utiliser sera pour défaire une règle affectant le même élément. Voici un exemple niais :

div {position:absolute}

#foo {position:static}

Cela aurait pour effet de rendre tous les éléments div avec une position absolue (ce qui est rarement une bonne idée, mais c'est juste pour l'exemple). En revanche, l'élément div avec id="foo" sera statique dans le flux du document. La deuxième règle sert à défaire la première.

Le terme « en position statique » est de ce fait mal venu. Je l'utiliserai quand même. Vous saurez ce que je veux dire.

La place d'un élément en position statique est déterminée par le contenu statique qui le précède dans le balisage. Nous pouvons bouger un peu l'élément en utilisant les propriétés margin ou padding, mais il reste principalement en place par rapport au reste du contenu.

Il faudrait trois articles entiers de la longueur de celui-ci pour expliquer comment sont disposés les éléments statiques, et vous jureriez probablement de renoncer à jamais à la conception graphique Web. Ce n'est pas le but, et nous contournerons donc le problème en disant que c'est plutôt simple et intuitif. Hmmm....

Le positionnement relatif

Comme déjà dit, la position d'un élément avec position:relative est relative à lui-même. Cela est sans doute étrange mais se révélera plutôt utile quand vous saisirez le concept.

Voici comment ça fonctionne en termes profanes : la boîte générée par l'élément est disposée comme si c'était un élément statique. La boîte rendue est alors déplacée horizontalement et/ou verticalement conformément aux valeurs des propriété top, right, bottom et left. Mais l'astuce est la suivante, tant que le reste du document est concerné : la boîte est toujours à sa place originale ! Elle est positionnée là où elle devrait être et elle occupera cette position dans le flux du document. Seule la boîte rendue est déplacée, relativement à cette position originale. Si nous la déplaçons de beaucoup, nous laisserons un trou dans le document.

Cela signifie qu'une déclaration position:relative est complètement inutile pour une disposition en colonnes par exemple. Elle n'est normalement utile que pour déplacer un élément de quelques pixels ou à peu près. Est-ce que cela veut dire que nous devons oublier position:relative ? Pas du tout. En fait, elle a un effet secondaire qui la rend tout-à-fait précieuse, ce que nous verrons dans un instant.

On peut utiliser les propriétés top, right, bottom et left pour indiquer de combien pousser la boîte rendue de sa position originale. Encore une fois, le fonctionnement peut sembler contre-intuitif au premier abord, mais il revêt une certaine logique.

Si nous indiquons top:20px pour un élément en position relative, nous le déplaçons de 20 pixels vers le bas. Vous savez quoi ? Ce n'est pas aussi fou que ça le paraît : top:20px signifie que nous poussons le bord du haut de la boîte de 20 pixels de là où elle aurait été sans positionnement. Ces valeurs peuvent même être négatives, et nous aurions donc pu utiliser bottom:-20px pour obtenir la même chose.

À ce stade, le lecteur averti réalise qu'il est inutile de définir en même temps les valeurs de top et bottom, ou de right et left. Elles s'opposeront l'une et l'autre, ou l'une sera ignorée. Par contre, définir ensemble les propriétés top et left est parfaitement juste, par exemple, si on veut pousser la boîte en bas et à droite.

Le résultat d'une déclaration position:relative sur les éléments de table (rangées, colonnes, groupes de rangées/colonnes, cellules et légendes) est indéfini dans la spécification CSS 2.1, ce qui veut dire que vous ne devriez pas vous y aventurer.

Le positionnement absolu

Le positionnement absolu peut être très utile même pour une mise en pages en colonnes. Il présente néanmoins des inconvénients. Un élément avec position:absolute est retiré du flux du document, ce qui signifie que le reste du document se comporte comme si l'élément n'était pas là. Il n'affectera pas les éléments suivants. Au lieu de cela, il pourrait finir par recouvrir d'autres éléments à moins de nous assurer que non. (Nous désirons parfois que ça se produise bien sûr, par exemple, pour des fenêtres contextuelles sans JavaScript).

Dans le positionnement absolu, les propriétés top, right, bottom et left s'appliquent aux éléments de façon très différente que dans le positionnement relatif. Elles définissent maintenant les positions des quatre bords de la boîte générée. On peut définir les valeurs en unités de longueur, tel que top:50px ou left:-8.5em. On peut aussi les définir en pourcentages, et dans ce cas c'est légèrement plus compliqué. Pour top et bottom, une valeur en pourcentage se rapporte à la hauteur du bloc conteneur, tandis que pour right et left elle se rapporte à la largeur du bloc conteneur.

C'est quoi un « bloc conteneur » ? Merci de poser la question

On dirait un de ces détails techniques ennuyeux que seuls les vrais techno-maniaques remarquent, n'est-ce pas ? Pour être honnête, c'est un détail technique ennuyeux qu'il nous faut malheureusement comprendre. Le bloc conteneur est extrêmement important lorsqu'on utilise un positionnement absolu.

Voyons ce que la spécification CSS 2.1 dit au sujet des blocs conteneurs :

Si l'élément a position: absolute, le bloc conteneur est établi par l'ancêtre le plus proche ayant une position absolute, relative ou fixed [...] S'il n'existe pas de tel ancêtre, le bloc conteneur est le bloc conteneur initial.

Bon, le bloc conteneur d'un élément en position absolue est l'ancêtre positionné le plus proche. Un ancêtre est un élément parent ou grand-parent, et ainsi de suite. Si aucun des ancêtres n'est positionné, le bloc conteneur est une certaine entité mythique appelée « bloc conteneur initial » que la spécification présente ainsi :

Le bloc conteneur où réside l'élément racine est choisi par l'agent d'utilisateur. (Il pourrait être lié à la zone de visualisation). Ce bloc conteneur est appelé le bloc conteneur initial.

Très pratique, n'est-ce pas ? L'élément racine dans n'importe quel document HTML ou XHTML est l'élément html. Donc le bloc conteneur initial est le parent de l'élément html, quoique cela puisse être. À ce point, la spécification commence à divaguer et marmonner à propos de « choisi par l'agent d'utilisateur » et « pourrait être lié à la zone de visualisation ». Dans le jargon du W3C, un agent d'utilisateur est (dans la plupart des cas) ce que nous simples mortels appellons un navigateur, et zone de visualisation une fenêtre de navigateur.

En d'autres termes, nous pouvons supposer que si un élément en position absolue n'a pas d'ancêtre positionné alors le bloc conteneur est le document même.

Si nous examinons de plus près la première citation, nous découvrirons cet effet secondaire intéressant du positionnement relatif mentionné précédemment : apparemment, un élément en position relative devient le bloc conteneur de tout sous-élément en position absolue. C'est extrêmement utile puisque ça nous permet de contrôler totalement nos blocs conteneurs.

Si nous voulons positionner un élément de façon absolue mais par rapport à un autre élément, tout ce qu'il nous reste à faire avec cet autre élément (ou un ancêtre commun) est de le transformer en bloc conteneur. Nous pouvons facilement y arriver en le déclarant avec position:relative. Nous n'avons pas du tout besoin de définir de mouvement. Le bloc conteneur ne bouge pas, il devient juste un bloc conteneur. Vite fait bien fait, non ?

Pour un élément en position absolue, les propriétés top, right, bottom et left définissent les distances depuis les bords correspondants du bloc conteneur. Plus précisément, c'est du bord d'espacement du bloc conteneur dont il est question. C'est-à-dire les limites extérieures des espacements définis sur le bloc mais sans les bordures ni l'aire de la marge.

Donc pour right:20px, cela signifie que le bord droit de l'élément en position absolue devrait se trouver à 20 pixels du bord droit du bloc conteneur.

Dans un navigateur compatible avec CSS2, nous pourrions définir les quatre propriétés afin de donner à la fois la position et les dimensions de notre élément en position absolue. Malheureusement, IE5/6 ne reconnaît pas une telle déclaration et, en réalité, il nous faudra donc définir une position verticale (soit top, soit bottom) et une position horizontale (soit left, soit right), puis définir la propriété width et parfois la propriété height.

Ces bogues concernent également les valeurs définies en pourcentages. Dans IE5/6, ces valeurs ne s'appliquent pas aux dimensions du bloc conteneur mais à celles du bloc parent. Comme nous l'avons vu, ce sont deux choses très différentes. Les bogues des pourcentages sont aussi présents dans Opera jusqu'à la version 8 comprise. Ils ont été corrigés dans Opera 9.

Je disais précédemment que les éléments en position absolue étaient retirés du flux du document. Ils n'affectent pas les éléments qui suivent dans le balisage : ceux-ci seront disposés comme si l'élément en position absolue n'était pas là. Cela rend l'utilisation du positionnement absolu impossible pour une mise en pages en plusieurs colonnes si on veut aussi un pied de page sur toute la largeur.

Mais bien qu'un élément en position absolue ne s'occupe pas de ce qui le suit, il n'est pas totalement ignorant de ce qui le précède dans le balisage. La valeur par défaut des quatre propriétés de dimension est auto, laquelle est aussi une valeur légale d'assignation explicite. Déclarer left:auto signifie que le bord gauche de l'élément en position absolue apparaîtra là où il se serait trouvé s'il avait été un élément statique normal. Nous pourrions encore fixer top:6em ou autre pour établir une position verticale. C'est parfois utile lorsqu'on veut épingler un élément dans une dimension seulement, par exemple dans des menus déroulants.

Le positionnement absolu peut se révéler très utile tant que l'on comprend son fonctionnement (et qu'on connaît les bogues des navigateurs). La clé de la réussite est de bien repérer ses blocs conteneurs.

Le positionnement fixe

Le positionnement fixe est similaire au positionnement absolu. La seule véritable différence est que le bloc conteneur est toujours le bloc conteneur initial dans le positionnement fixe. Vous savez bien, celui qui est « choisi par l'agent d'utilisateur » et qui « pourrait être lié à la zone de visualisation ». Les propriétés top, right, bottom et left se rapportent aux bords de la fenêtre du navigateur (ou de la page pour une impression).

En fait, un élément en position fixe est collé à une position spécifique dans la fenêtre du navigateur et ne bouge pas, même si on fait défiler le document. Pour une impression, un élément fixe sera imprimé sur chaque page à la même position sur chacune.

Voilà qui est formidable, n'est-ce pas ? Ne vouliez-vous pas depuis toujours un menu de navigation qui ne défilât pas avec le document, au lieu de ces solutions JavaScript bancales qui n'étaient pas vraiment ça ? On dirait que ce truc position:fixed est la réponse à toutes vos prières et vous êtes sur le point de tomber à genoux ! Mais ensuite vous réalisez que nous parlons de CSS. Il y a toujours un « mais » quelque part. Tiraillé entre espoir et désespoir, vous parcourez la spécification CSS 2.1 sans y trouver de mise en garde. Est-ce possible ?

Non, évidemment non. Et sur quoi se fracassent ces rêves, cruellement et froidement, quoi d'autre qu'Internet Explorer de Microsoft. Les versions 5.x et 6 ne reconnaissent pas position:fixed, donc retour aux solutions JavaScript bancales après tout. Vous le sentiez au plus profond de vous, n'est-ce pas ?

Z-Index

Un élément en position relative occupe l'espace à un seul endroit mais la boîte rendue peut se trouver ailleurs. Les éléments en position absolue et en position fixe sont retirés du flux du document. Dans les trois cas, cela peut se terminer par des boîtes superposées par-dessus d'autres : un chevauchement. Il faut le savoir et s'assurer de leur laisser de la place si cet effet est indésirable.

L'effet de recouvrement des boîtes est parfois désirable mais il serait peut-être bien de pouvoir contrôler quelle boîte est dessus. Nous pouvons le faire avec la propriété z-index qui s'applique aux éléments positionnés (c'est-à-dire tous ceux sans position:static). En plus des mots-clés auto et inherit, cette propriété accepte une valeur entière (qui peut être négative).

L'écran d'un ordinateur a deux dimensions (pour l'instant). C'est une aire plane avec une largeur et une hauteur sur laquelle nous pouvons rendre nos boîtes CSS. Mais CSS fonctionne en réalité en trois dimensions. L'axe des X et l'axe des Y sont respectivement notre axe horizontal et notre axe vertical normaux. L'axe des Z est perpendiculaire à ces deux-là. Imaginez-le comme pointant tout droit en avant et en arrière de l'écran. Plus la valeur de la propriété z-index est élevée, plus l'élément est proche de l'utilisateur. C'est ce qu'on appelle le niveau d'empilement.

Cet article n'a pas l'ambition d'examiner en détails les contextes et les niveaux d'empilement, alors disons juste qu'un élément positionné établit ce qu'on appelle un contexte d'empilement. L'élément et ses sous-éléments positionnés peuvent recevoir un niveau d'empilement en utilisant la propriété z-index. Toutefois, ce niveau d'empilement s'applique au sein du contexte d'empilement du parent. Ou dit autrement, on peut seulement changer l'ordre d'empilement des éléments au sein du même contexte d'empilement.

Examinons le fragment de balisage suivant :

<div id="premier">

<div id="a">...</div>

<div id="b">...</div>

</div>

<div id="suivant">

<div id="c">...</div>

<div id="d">...</div>

</div>

Supposons que les éléments div avec id="premier" et id="suivant" ont une position relative, ce sont donc les blocs conteneurs de sous-éléments en position absolue. Supposons également que les éléments div internes (a, b, c et d) sont en position absolue. Nous pouvons modifier l'ordre d'empilement de « a » et « b » avec z-index car ils se trouvent dans le même contexte d'empilement (celui de « premier »). Si nous voulons que « a « soit au-dessus de « b », nous pouvons déclarer z-index:1 pour « a » (ou z-index:5, ou z-index:99, la valeur importe peu, elle doit simplement être supérieure au z-index de l'élément au-dessus duquel on veut placer l'élément en question).

Nous pouvons aussi modifier l'ordre d'empilement de « premier » et « suivant », s'ils se chevauchaient, car ils se trouvent dans le même contexte d'empilement.

Mais si on voulait glisser « suivant » ou « c » entre « a » et « b » ? Pas de chance car « suivant » et « c » existent dans des contextes d'empilement différents de ceux de « a » et « b », et il n'y a aucun moyen de les insérer entre ces deux-là.

De même, on ne peut pas alterner les sous-éléments de « b » avec les sous-éléments de « a » puisque « a » et « b » établissent leurs propres contextes d'empilement séparés.

Tout comme le bloc conteneur dans le positionnement absolu, il est très important de connaître le contexte d'empilement pour l'utilisation de z-index.

Pour conclure

J'ai créé un exemple montrant les divers schémas de positionnements en action. Il ne fonctionnera pas correctement avec les navigateurs Internet Explorer 5.x ou 6, puisqu'ils ne reconnaissent pas le positionnement fixe, mais les utilisateurs des navigateurs Opera 9, Firefox, Safari ou Internet Explorer 7 pourront en profiter.

Tout le code CSS contrôlant la mise en pages est présent dans le balisage, et il suffit d'examiner la source de la page pour voir comment c'est fait.

Le positionnement CSS a ses utilisations mais, dans beaucoup d'applications réelles, il n'est pas si pratique que ça pour la mise en pages. Les flottants sont souvent mieux placés quoiqu'empêtrés dans les bogues de navigateurs.

Si vous savez toujours quelle colonne est la plus longue, vous pourrez alors utiliser le positionnement pour la mise en pages. À l'heure actuelle, il faut éviter le positionnement fixe, au moins dans les sites publics, parce que le navigateur le plus répandu ne le reconnaît pas.

Compléments de lecture

© 1999-2008 yoyodesign.org — Certains droits réservés