Positionnement d’une page html par css

Ce document résume quelques notions pour le positionnement des objets html à l’aide d’un fichier css.

En théorie, il y a une documentation complète en ligne. En pratique, c’est souvent assez pénible car la documentation est souvent évasive. On peste en se demandant ou est décrit le fichu algorithme utilisé.

Cher lecteur, ce document est pour toi si comme moi tu as peiné plusieurs jours avec des objets dont le positionnement saute de façon erratique quand tu as changé un paramètre, si tu cherches à connaître l’algorithme de positionnement utilisé par le navigateur.

Le type d’objets a placer

Il y a plusieurs types d’images qui apparaissent dans une page web, au sens ou les règles de postionnement qu’on leur applique sont différentes :

  • les images qui fixent le cadre et sont fixes indépendamment des modifications ultérieures du contenu
  • les images qui s’inscrivent dans un flot texte-image et sont placées au gré du texte.
  • les elements décoratifs attachés a un contenu ( exemple: un logo de crayon en haut de chaque article )

Il y a aussi plusieurs types de positionnement pour un texte:

  • le texte fixe ( Titre d’Accueil de la page web, menus...)
  • le texte en flot, en général actualise’ au fur et à mesure des ajouts du site

Il y a enfin

  • Des textes et images qui restent toujours a la meme place sur l’ecran pour rester visibles ( par exemple un menu qui reste visible meme si on bouge l’ascenceur).

Il faut mettre les objets précédents en relation avec les options de positionnement adéquates de css.

De la racine vers les feuilles, avec les marqueurs

L’algorithme de positionnement utilisé par le navigateur qui va afficher la page web est le suivant. Le navigateur construit l’arbre d’objets de la page. Il positionne les objets en commencant par la racine et en finissant aux feuilles, en explorant toute la branche en profondeur avant de passer à la branche voisine. Lors de cette exploration de l’arbre, le positionnement de chaque objet rencontré dépend du marqueur de position associé à l’objet.

Chaque objet est muni d’un marqueur de position sous la forme d’un attribut position:valeur, où valeur est choisie parmi les quatre possibilités suivantes:

  • static ( = le défaut)
  • absolute,
  • relative,
  • fixed.

Les valeurs initial et inherit sont également possibles, mais elles redonnent après calcul l’une des quatre possibilités précédentes.

Le positionnement des static

Si le navigateur doit placer un objet “static”, il va essayer de le poser en n’empiétant pas sur les autres objets static et relative déjà posés. En revanche, le navigateur ne se préocuppe pas du chevauchement des objets static avec les objets absolute ou fixed. Autrement dit, les objets absolus ou fixed sont “inconnus/transparents” pour les objets static. Le navigateur commence par calculer la taille de l’objet static qu’il cherche à poser. Il ajoute à cette taille les valeurs des paramètres padding et border-width (si border-style n’est pas positionné à none).

Cet objet dont la taille est maintenant connu doit maintenant être posé dans une boite contenante. Cette boite contenante est est déterminée: c’est un objet div, et parmi tous les div de l’arbre, on choisit l’ancêtre le plus proche du static qu’on veut poser. En l’absence d’ancêtre, c’est le document qui sert de div par défaut.

La boite conteneur maintenant déterminée contient déja des objets static et relative. Ce sont des objets qui sont plus proches de la racine et qui ont dejà été traités par le navigateur dans les étapes précédentes de l’algorithme. Ce peuplement laisse 2 empreintes dans la boite. La petite empreinte e est formée par les objets déposés dans la boite. La grande empreinte E est formée par les objets déposés aggrandis de leurs marges. L’objet static qu’on veut poser admet de meme deux empreintes o et O, petites et grande, sans ou avec les marges. L’objet nouvellement posé devra satisfaire les 2 conditions suivantes: o et E ne se rencontrent pas, O et e ne se rencontrent pas. En d’autres termes, aucun objet ne doit chevaucher un autre objet ni sa marge.

Parmi toutes les possibilités de placement respectant ce critère, l’algorithme procède pour les objets qui ont la propriété display:inline de la même facon que lorsqu’on pose une nouvelle lettre sur une feuille de papier quand on est en train d’écrire. On cherche une place libre de la gauche vers la droite, avec passage a la ligne et retour à la gauche de la boite quand la ligne est pleine.

Pour un objet ayant la propriété display:block au lieu de display:inline un retour à la ligne est imposé avant de rechercher une place libre pour poser l’objet, à la manière d’une lettre sur une feuille de papier quand on commence un nouveau paragraphe. Par exemple, les eléments <li> d’une liste se voient attribuer par défaut display:block. En conséquence, chaque nouvel élément d’une liste engendre automatiquement un passage à la ligne. On peut changer la propriété en display:block si on a besoin de présenter une liste horizontalement dans un menu sans retour à la ligne.

La propriété display:inline-block permet de placer les éléments comme avec display:inline tout en conservant la structure de bloc. Concrètement, avec display:inline-block, les propriétés width:value et height:value sont prises en compte, alors qu’elles sont sans effet pour les objets display:inline. En termes intuitifs, cela signifie qu’un élement inline est applati pour entrer comme dans un interligne, tandis qu’un element inline-block est positionné comme une lettre usuelle sans passage à la ligne, mais conserve sa géométrie de bloc.

Si l’objet a poser a l’attribut float:none, le navigateur pose le nouvel objet dès qu’il trouve une place libre comme décrit précédemment. Si float=left ou float=right, la position ainsi trouvée par l’étape précédente n’est qu’une position intermédiaire. On poursuit avec un decalage maximal vers la gauche ou vers la droite si un tel decalage est possible.

En termes techniques et inambigus. ce procédé se décrit ainsi pour placer un objet de propriétés position:static, display:inline. On note (a,b)=(coordonnee ligne,coordonnee colonne) les coordonnees du coin haut gauche du dernier objet non flottant pose’ dans la div ( a,b=0,0 si on n’a pas encore posé d’objet). Le coin haut gauche du nouvel objet sera place’ plus bas, c’est a dire en (c,d) avec c>=a. On choisit c minimum avec c>=a de sorte que la place libre sur la ligne de hauteur c soit assez grande pour poser l’objet. Si float = left, on choisit d minimal. Si float=right, on choisit d maximal. Si float=none et c=a, on choisit d minimal parmi les d>=b. Si float=none et c>a, on choisit d minimal parmi les d>=0.

En résumé, le positionnement des objets ayant position:static dépend du contenant et des propriétés de l’objet lui même (float ou pas, valeur de la propriété display...) en suivant globalement la paradigme des lettres qu’on écrit sur une feuille. Il est possible aussi d’utiliser d’autres paradigmes pour positionner des static dans un div, notamment en affectant la propriété display:flex au div conteneur. Je ne développe pas, mais ca peut être intéressant à explorer si le paradigme de l’ecriture se révèle inadapté, par exemple quand on veut poser les objets dans la div en écrivant de bas en haut ou de droite à gauche, ou que l’on veut mettre des espaces entre des mots pour remplir la ligne entièrement.

Le positionnement des objets positionnés

On dit par definition qu’un élement qui n’a pas la position “static” qu’il est “positionné”. Nous avons décrit le positionnement des objets static. Il reste à voir le positionnement des objets positionnés. Les ojbets positionnés sont munis d’attributs top:value, right:value, left:value, bottom:value qui permettent d’affiner le placement. Ces paramètres de positionnement top,right,left,bottom sont ignorés dans le cas d’un objet static.

Pour un objet dont le positionnement est position:relative, le navigateur calcule d’abord le positionnement comme dans le cas position:static. Puis l’objet est décalé de la valeur des parametres de positionnement left,right, bottom, top

Si un objet a position:absolute, la boite contenante n’est pas la même que dans les cas précédents. Le navigateur commence par rechercher le dernier div ancestral qui est un objet positionné. Si tous les div qui sont des aieux ont une position position:static, le div par défaut est la fenêtre d’affichage du navigateur (En particulier, dans ce cas, le redimensionnement du document ne changera pas la place de l’objet !). La boite ainsi définie sert de boite contenante et l’objet absolute sera placé dans cette boite contenante à l’aide des paramètres de position. Par exemple, si les paramètres left,bottom sont déclarés, la mesure se fait à partir de la gauche et du bas de cette boite contenante. Le positionnement dit absolute n’est donc pas absolu. Il est relatif à la boite contenante correspondant à la dernière boite ancestrale positionnée. Ce n’est que si cette boite ancestrale est absente que le positionnement est absolu par rapport à la fenêtre du navigateur.

Si un objet est positionné par position:fixed, les paramètres de positionnement son interprétés par rapport à la fenetre du navigateur (=mode sticky). C’est donc comme le mode position:absolute dans le cas ou l’objet absolu n’a pas de boite ancestrale positionnee.

Chevauchements

Pour régler les priorités lors des chevauchement des objets qui partagent une partie de l’écran, on dispose de la variable z-index.

Choix de positionnement pour les objets

Voici quelques possibilités pour mettre en oeuvre les elements css précédents en fonction des types d’objets rencontrés.

  • les objets “sticky” auront position:fixed. Exemple: un menu toujours visible, même quand on bouge l’ascenseur pour faire défiler la page. Les parents eventuels et le contexte n’ont pas d’influence.
  • Les objets fixes dans le document auront position:absolute. Ils sont soit orphelins, soit ont des parents qui sont eux-meme dans une position qui n’est pas susceptible de bouger.
  • Les objets qu’on souhaite localiser dans une zone d’accueil de la page et qui ont le droit de bouger dans cette zone d’accueil. On fait un div de la taille adéquate pour decrire la zone d’accueil et on décrit les objets de la zone d’accueil comme des descendants de ce div. On peut déclarer ces objets en static. Si les marges ou autres petits problèmes induisent un placement difficile, on peut utiliser position:relative pour ajouter des petits decalages.
  • Les objets décoratifs qui suivent un contenu variable. Exemple: une plume d’écrivain comme logo a droite de chaque article de longueur variable. L’article est inclus dans un div. L’élément décoratif (ici la plume) est inclus dans le même div avec position:absolute ( exemple pour la plume: right:0px top:50% ). Le div parent sera positionné ( c’est à dire non static) puisque les absolute choisissent leur boite contenant seulement parmi ascendants positionnés. Au besoin, on remplacera le positionnement static du div parent par un position:relative en laissant les paramètres top/left... à zéro.
  • Les objets alignés ou plus généralement en position précise les uns par rapport aux autres doivent tous être en position absolue et avoir le même ancêtre positionné (cet ancetre étant eventuellement non existant).

Choix des unite’s

Je préfère mettre des unite’s fixes plutot que des pourcentages. Les unités fixes se comportent bien quand on zoome ou dézoome sur une page. Les alignements son respectés. Si on mélange pourcentage et des donnees fixes, ça met parfois la pagaille, notamment pour des photos qui sont parfois exprimees en pourcentage de leur taille initiale. Les pourcentages restent indispensables quand on veut mettre une image au milieu d’une colonne dont on ne connait pas la longueur par exemple.

Quelques details utiles

Ne pas oublier de mettre height:auto aux div si on souhaite un redimensionnement convenable pour contenir les dessins (static et relative, non flottants) qui y sont inclus.

S’il reste des problemes, ajuster avec la commande overflow.