documents

Avoir la mise en page

Un effort continu…
Version du : 23 octobre 2007 — 8ème révision
Journal des changements
Traductions

Table des matières

  1. Introduction
  2. La propriété hasLayout : une définition
  3. Nomenclature
  4. La main qui nous a été donnée
  5. D'où vient la mise en page ?
  6. Les éléments qui ont la mise en page par défaut
  7. Les propriétés
  8. Remarques à propos des éléments de type en-ligne
  9. Réinitialiser la propriété hasLayout
  10. La propriété de script hasLayout
  11. Les bidouilles CSS
  12. La gestion des bidouilles
  13. Une brève remarque à propos d'IE Mac.
  14. La documentation MSDN
  15. Interprétation
  16. Un rappel des conséquences
  17. Le dégagement des flottants et le prolongement pour loger
  18. Les éléments à côté des flottants
  19. Les listes
  20. Les tables
  21. Les éléments en position relative
  22. Les éléments en position absolue : le bloc conteneur, quel bloc conteneur ?
  23. La propriété filter
  24. Le repositionnement des éléments rendus
  25. L'origine de l'arrière-plan
  26. La fusion des marges
  27. Les liens de type bloc
  28. La navigation au clavier dans la page : une odyssée
  29. L'enveloppe rétractable
  30. Le rognage au bord
  31. Empilement, couches et mise en page
  32. La débâcle contenteditable
  33. Les similarités avec les spécifications CSS
  34. Le mode des bizarreries (quirks mode)
  35. Mise en page : une conclusion
  36. Avoir la mise en page : est-ce une partie d'un autre moteur ?
  37. L'absurdité des bogues

Introduction

Beaucoup d'incompatibilités de rendu dans Internet Explorer peuvent être corrigées en donnant la « mise en page » (layout) à l'élément. John Gallant et Holly Bergevin ont classé ces incompatibilités dans la catégorie des « bogues dimensionnels », signifiant par-là qu'on peut souvent les résoudre en appliquant une largeur ou une hauteur. Cela amène la question de savoir pourquoi la mise en page peut changer le rendu des éléments et leurs relations. Si c'est une bonne question, il est par contre difficile d'y répondre. Dans cet article, les auteurs se concentrent sur quelques aspects de cette matière complexe. Pour des discussions approfondies et des exemples, veuillez consulter les liens fournis.

La propriété hasLayout : une définition

La mise en page est un concept propriétaire d'Internet Explorer pour Windows (IE/Win), qui détermine comment les éléments dessinent leurs contenus et les lient, interagissent avec d'autres éléments et s'y réfèrent, se comportent face aux événements de l'application/l'utilisateur et les transmettent.

Certaines propriétés CSS peuvent immanquablement déclencher cette qualité. Par défaut, certains éléments HTML ont la mise en page.

Les développeurs chez Microsoft ont décidé que des éléments devaient pouvoir acquérir une propriété (au sens de la programmation orientée objets), qu'ils ont appelée hasLayout (N.d.T., qui a la mise en page) et qui a la valeur true lorsque ce concept de rendu prend effet.

Nomenclature

Nous disons d'un élément qu'il gagne la mise en page ou qu'il a la mise en page lorsque la propriété exclusive de Microsoft hasLayout de cet élément a la valeur true. Un élément qui a la mise en page peut être n'importe quel élément qui l'a par défaut, ou qui l'a gagnée grâce au paramétrage approprié d'une propriété CSS.

La propriété hasLayout n'est pas déclenchée dans les éléments qui n'ont pas la mise en page, c'est-à-dire qu'un élément div pur, sans dimension, peut être un ancêtre qui n'a pas la mise en page.

Donner ou appliquer la mise en page à un élément qui ne l'a pas par défaut implique de paramétrer une propriété CSS qui déclenche hasLayout=true pour l'élément en question. Cf. les sections « Les éléments qui ont la mise en page par défaut » et « Les propriétés » pour des listes. Il n'y a pas d'autre moyen d'établir hasLayout=false que de supprimer ou réinitialiser la propriété CSS qui a enclenché hasLayout=true au départ.

La main qui nous a été donnée

Le problème hasLayout affecte les concepteurs (et les codeurs) à tous les niveaux d'expérience. La mise en page a des effets inhabituels et difficiles à prévoir sur l'affichage des boîtes ainsi que des implications pour leurs éléments descendants.

Avoir ou non la mise en page peut entraîner les conséquences suivantes :

La liste précédente est brève et incomplète. Cet article tente de décrire précisément les problèmes rencontrés dans l'application de la mise en page ou faute de l'appliquer.

D'où vient la mise en page ?

Contrairement aux propriétés standards, ou même aux propriétés CSS exclusives disponibles dans différents navigateurs, la mise en page n'est pas directement affectée via des déclarations CSS. En d'autres termes, il n'existe pas de « propriété layout ». Certains éléments acquièrent automatiquement la mise en page, qui s'ajoute silencieusement en présence de déclarations CSS variées.

Les éléments qui ont la mise en page par défaut

Les éléments suivants ont la mise en page par défaut :

Les propriétés

Les couples de propriété/valeur CSS suivants, si appliqués, permettent à un élément de gagner la mise en page.

position: absolute
Se rapporte à son bloc conteneur, c'est là où commencent les problèmes.
float: left|right
Le modèle de flottement présente beaucoup de bizarreries causées par certains aspects des éléments qui ont la mise en page.
display: inline-block
Parfois un remède lorsque l'élément est de type en-ligne et a besoin de la mise en page. L'application de la mise en page est probablement le seul effet réel de cette propriété. On peut obtenir le « comportement inline-block » dans IE mais de manière assez détournée (cf. « IE/Win : inline-block et hasLayout »).
width: toute valeur sauf "auto"
C'est souvent une correction implicite, et plus souvent le déclencheur lorsque hasLayout fait les choses de travers.
height: toute valeur sauf "auto"
La bidouille de Holly (N.d.T., de Holly Bergevin) utilise la déclaration height: 1%.
zoom: toute valeur sauf "normal" (MSDN)
Exclusivité de Microsoft, la propriété ne passe pas la validation. On peut utiliser zoom: 1 pour le débogage.
writing-mode: tb-rl (MSDN)
Exclusivité de Microsoft, la propriété ne passe pas la validation.

Depuis Internet Explorer 7 (IE 7), la propriété overflow est devenu un déclencheur pour la mise en page.

overflow: hidden|scroll|auto
Cette propriété ne s'appliquait pas dans les versions précédentes, sauf si d'autres déclencheurs ajoutaient la mise en page à la boîte.
overflow-x|-y: hidden|scroll|auto
Faisant partie du module du modèle de boîtes CSS3, la mise en œuvre des propriétés overflow-x et overflow-y n'est pas encore très répandue. Elles n'initiaient pas hasLayout dans les versions précédentes d'IE.

De nouveaux acteurs hasLayout ont fait leur apparition dans IE 7. En ce qui concerne hasLayout, les propriétés des types min/max fonctionnent de manière similaire aux propriétés width et height, et les effets des positionnements fixes et absolus semblent identiques.

position: fixed
...
min-width: toute valeur
Même la valeur 0 fait gagner la mise en page à l'élément.
max-width: toute valeur sauf "none"
...
min-height: toute valeur
Même la valeur 0 déclenche hasLayout=true
max-height: toute valeur sauf "none"
...

Ceci est fondé sur l'interrogation de la barre d'outils des développeurs d'IE (IE Developer Toolbar) et sur des tests préliminaires.

Remarques à propos des éléments de type en-ligne

Pour les éléments de type en-ligne (soit de type en-ligne par défaut comme l'élément span, soit ayant display: inline) :

Les éléments ayant à la fois la mise en page et display: inline ont un comportement similaire à ceux avec la déclaration display: inline-block définie dans les standards : ils s'écoulent horizontalement comme des mots dans un paragraphe, sont sensibles à l'alignement vertical et appliquent une sorte d'enveloppe rétractable à leurs contenus. Dès que les éléments en-ligne ont la mise en page, ils se comportent comme pour inline-block, et c'est une explication au fait que les éléments en-ligne, dans IE/Win, peuvent contenir et loger des éléments de type bloc avec moins de problèmes que dans les autres navigateurs, où pour display: inline les éléments restent en-ligne.

Réinitialiser la propriété hasLayout

La réinitialisation des propriétés suivantes à leurs valeurs par défaut dans un jeu de règles séparé réinitialisera (ou défera) hasLayout, si aucune autre propriété donnant la mise en page reste en vigueur :

Les auteurs doivent se montrer prudents pour la réinitialisation de ces propriétés. Prenons un système de menu ; changer l'état de hasLayout sur un a:hover, intentionnellement ou non, peut produire un rendu inattendu (ou une instabilité du programme avec IE 6 lorsqu'on le défait dynamiquement en combinaison avec position: relative).

La propriété display est différente : tandis que la valeur "inline-block" établit haslayout=true, le drapeau ne sera pas réinitialisé à "false" si on l'écrase ensuite avec les valeurs "block" ou "inline" dans un autre jeu de règles.

Le paramétrage des propriétés min-width et min-height à leur valeur par défaut "0" donne toujours la mise en page, mais IE 7 accepte pour elles la valeur invalide "auto", qui réinitialise hasLayout.

La propriété de script hasLayout

Nous avons choisi de considérer hasLayout comme une « propriété de script » afin de la distinguer des propriétés CSS familières.

Il n'existe aucun moyen d'initialiser ou de réinitialiser directement la propriété de script hasLayout.

On peut utiliser la propriété hasLayout pour vérifier si un élément a la mise en page : par exemple, si l'attribut id de celui-ci vaut "eid", alors il suffit simplement de taper javascript: alert(eid.currentStyle.hasLayout) dans la barre d'adresse des navigateurs IE 5.5+ pour tester son état.

La barre d'outils des développeurs d'IE permet d'inspecter en direct le style courant d'un élément ; lorsque la propriété hasLayout est vérifiée (true), sa valeur est signalée par "-1". En éditant en direct les attributs d'un nœud, vous pouvez donner à zoom (CSS) la valeur "1" afin de déclencher hasLayout pour les besoins du débogage.

Une autre chose à examiner est la façon dont la mise en page affecte les scripts. Les propriétés clientWidth ou clientHeight retournent toujours zéro pour les éléments sans mise en page. Ce comportement peut être déroutant pour les créateurs de scripts novices, car il diffère de celui des navigateurs de type Mozilla. Nous pouvons utiliser ce fait pour déterminer la mise en page avec IE 5.0 : si la propriété clientWidth vaut zéro, alors l'élément n'a pas la mise en page.

Les bidouilles CSS

Les bidouilles (hacks) suivantes pour déclencher hasLayout ont été testées dans IE 7 et précédents.

John Gallant et Holly Bergevin ont livré la « bidouille de Holly » en 2003 :

  1. /* \*/
  2. * html .gainlayout { height: 1%; }
  3. /* */

Cette bidouille :

Pour donner la mise en page dans IE 6 et précédents, nous pouvons aussi utiliser la bidouille du souligné :

  1. .gainlayout { _height: 0; }

Et pour donner la mise en page dans IE 7, nous pouvons utiliser la propriété min-height :

  1. .gainlayout { min-height: 0; }

Sinon, et probablement à l'épreuve du temps, il y a les commentaires conditionnels :

  1. <!--[if lte IE 6]>
  2. <style>
  3. .gainlayout { height: 1px; }
  4. </style>
  5. <![endif]-->
  1. <!--[if IE 7]>
  2. <style>
  3. .gainlayout { zoom: 1; }
  4. </style>
  5. <![endif]-->

L'utilisation d'une feuille de style externe pour toutes corrections nécessitées par IE/Win, appelée depuis un commentaire conditionnel, est une solution sûre et élégante :

  1. <link rel="stylesheet" href="touslesnavigateurs.css" type="text/css" />
  2.  
  3. <!--[if lte IE 7]>
  4. <link rel="stylesheet" href="iefix.css" type="text/css" />
  5. <![endif]-->

Pour IE 6 et précédents, il faudrait « toujours » utiliser la propriété height (si nous voulons inclure IE 5.0, il n'y a pas tellement de choix), à moins que celle-ci n'entre en conflit avec autre chose (overflow: hidden). En ce qui concerne sa valeur, les valeurs "1%", "1px" et "0" sont plus ou moins équivalentes, mais la valeur "1%" peut (quoique très rarement) poser des problèmes.

La propriété height ne peut pas être utilisée pour les éléments en-ligne en mode standard et on devrait l'éviter dans IE 7 (ou l'utiliser prudemment : seulement avec des valeurs en pourcentage et uniquement si l'élément parent n'a pas de propriété height explicite). Dans ces cas, nous préférons display: inline-block ou zoom: 1.

Nous avons vu des tentatives de bidouillage désespérées, en application sur des éléments flottants, ou sur des éléments ayant déjà une propriété width. Retenez que le but de cette bidouille n'est pas d'attribuer une hauteur mais de déclencher hasLayout=true.

Ne donnez pas la mise en page à tout : * {_height: 1px;}. C'est du poison à cette dose, avoir la mise en page n'est pas le remède, cela change fondamentalement le rendu.

La gestion des bidouilles

Comme le montre l'apparition d'IE 7, il est impossible de prévoir si les versions futures d'IE nécessiteront encore hasLayout pour corriger quelques bogues et comment elles réagiront aux filtres utilisés aujourd'hui. Dans cette perspective, on peut conseiller d'utiliser les techniques propriétaires de Microsoft, à savoir la propriété zoom et/ou les commentaires conditionnels.

  1. <!--[if lt IE 7]><style>
  2. /* style pour IE 6 + IE 5.5 + IE 5.0 */
  3. .gainlayout { height: 0; }
  4. </style><![endif]-->
  5.  
  6. <!--[if IE 7]><style>
  7. .gainlayout { zoom: 1; }
  8. </style><![endif]-->

Bien que nous pensons que l'expression « à l'épreuve du temps » soit une contradiction dans les termes, nous suggérons vigoureusement aux concepteurs Web de « jouer sûrement », de revoir leurs pages à la recherche de bidouilles explicites et implicites, et d'utiliser des commentaires conditionnels pour servir ces bidouilles aux versions appropriées des navigateurs.

Pour une vue détaillée des déclencheurs hasLayout et une comparaison des bidouilles hasLayout dans les diverses versions d'IE, cf. l'article « Réflexions sur la gestion des bidouilles pour IE ».

Une brève remarque à propos d'IE Mac.

IE Mac et IE pour Windows sont deux animaux différents, vivant dans des parties séparées du zoo. Chacun a son propre moteur de rendu, et IE Mac ne connaît en aucune façon le comportement hasLayout (ou contenteditable). Le moteur de rendu d'IE Mac tend à être plutôt conforme aux standards, en traitant la propriété height comme il se doit. Les bidouilles et contournements de problèmes de hasLayout (spécialement dans l'utilisation des propriétés height ou width) auront souvent des effets désastreux dans IE Mac, et il faudrait les cacher à ce navigateur. Plus sur les problèmes d'IE Mac dans « Les curiosités d'Internet Explorer 5 pour Mac ».

La documentation MSDN

Dans le site communautaire MSDN (Microsoft Developer Network), il y a peu de pages consacrées à la propriété hasLayout, et encore moins d'explications concernant l'influence de la mise en page sur le modèle de formatage visuel d'IE.

Dans IE 4 déjà, presque tous les éléments avaient une sorte de mise en page, sauf les éléments en-ligne simples en position non absolue et sans dimension (le document MSDN a été modifié [1]). Et dans ce concept précurseur de la mise en page, il y avait des « propriétés de mise en pages » (layout properties) telles border, margin, padding, qui ne pouvaient pas s'appliquer à ces éléments en-ligne simples. En d'autres termes, « avoir la mise en page » était à peu près synonyme de « peut avoir ces propriétés ».

MSDN parle toujours de « propriétés de mise en pages », mais la signification a changé, elles ne sont plus associées aux éléments ayant la mise en page. La propriété Microsoft hasLayout a été introduite dans IE 5.5, plus ou moins comme un drapeau interne.

Dans IE 5.5, la documentation de la plateforme d'édition MSHTML (qui permet d'éditer, dimensionner et faire glisser dynamiquement les éléments qui ont la mise en page via <body contenteditable=true>) révèle trois aspects importants sur le fait d'avoir la mise en page :

« Si un élément qui a la mise en page a un contenu, alors son rectangle englobant détermine la mise en page du contenu. »

« Avoir la mise en page signifie essentiellement qu'un élément est rectangulaire. »

« En interne, avoir la mise en page signifie qu'un élément est responsable du dessin de son propre contenu. »

(Plateforme d'édition : pièce retirée de la documentation MSDN [2])

Jusqu'en août 2005, les fonctionnements internes liés à la mise en page en question n'étaient pas documentés, lorsque Markus Mielke (Microsoft), à la suite de « The Web Standards Project » et du groupe d'étude de Microsoft, ouvrit les portes pour une discussion approfondie :

« En général, les éléments dans le moteur HTML dynamique d'Internet Explorer ne sont pas responsables de leur propre arrangement. Des éléments div ou p peuvent avoir une certaine position dans l'ordre de la source et dans le flux du document, mais leurs contenus sont arrangés par leur ancêtre qui a la mise en page le plus proche (fréquemment body). Ces éléments s'appuient sur la mise en page de l'ancêtre pour faire tous les gros travaux de détermination des informations de dimension et de mesure à leur place. »

(Vue d'ensemble de hasLayout)

Interprétation

Notre interprétation est une tentative d'explication de ce qui se passe dans des cas connus, et elle devrait servir de guide pour les cas qui ne sont pas entièrement démêlés. Une tentative qui consiste seulement à démystifier une boîte noire en y insérant quelques jeux d'essais et en écoutant si la sonnette retentit est vouée à l'échec. La question du pourquoi ne peut pas être résolue. Il nous faut comprendre la plateforme dans laquelle fonctionne le modèle hasLayout en entier. De cela, on peut tirer des indications (et ce ne sont que des indications pas des solutions absolues).

Nous pensons qu'elles concernent une fenêtre étroite. Le contenu d'un élément qui a la mise en page serait complètement indépendant de tout se qui se trouve hors des limites de l'élément, et le contenu ne pourrait rien affecter en dehors non plus.

La propriété Microsoft hasLayout est une sorte de drapeau : lorsqu'il est mis, l'élément a cette « qualité » mise en page, qui inclut des capacités spéciales, par exemple sur le flottement et l'empilement, pour l'élément même ou pour ses sous-éléments sans mise en page.

Cette plus grande indépendance des éléments qui ont la mise en page est probablement la raison pour laquelle ils sont généralement plus stables, et font donc disparaître quelques bogues. Le prix à payer pour ça est à la fois un écart par rapport aux standards et d'autres bogues/problèmes à leurs frontières.

On peut assimiler le modèle de la « page » de Microsoft, dans une pensée sémiotique, comme constitué de petits blocs d'histoires sans liens de parenté, tandis que le modèle de la « page » HTML du W3C est une histoire narrative complète, où les blocs d'information sont liés.

Un rappel des conséquences

Le dégagement des flottants et le prolongement pour loger

Les flottants sont auto-contenus par les éléments qui ont la mise en page. C'est une raison pour laquelle la plupart des débutants se débattent avec leurs pages construites pour IE dans les navigateurs conformes, où les flottants dépassent du conteneur s'ils ne sont pas dégagés (cleared).

Le comportement opposé : et si un flottant doit dépasser de son conteneur, par exemple, que l'auto-contenance n'est pas l'effet désiré ? Pour une démonstration des problèmes frustrants que l'on peut rencontrer, jetez un coup d'œil à notre discussion approfondie :

Dans IE, un flottant « appartiendra » toujours à son conteneur qui a la mise en page. Les éléments suivants peuvent respecter le conteneur qui a la mise en page mais pas le flottant lui-même.

Ce comportement et celui de prolongement d'un conteneur pour loger un contenu plus large d'IE 6 (le « prolonger pour loger ») peuvent être vus comme un aspect de la règle du « rectangle englobant déterminant la mise en page ».

Pire encore : la propriété clear ne peut pas affecter un flottant hors du conteneur qui a la mise en page de l'élément dégageur. Les mises en pages de flottants comptant sur ce bug dans IE ne sont pas transférables et elles ne pourront fonctionner dans un navigateur conforme sans une refonte générale.

L'auto-contenance du flottant d'IE, qui est parfois inévitable, ne peut pas être obtenue dans d'autres navigateurs : cf. notre section « Les similarités avec les spécifications CSS » pour des concepts de confinement des flottants.

Les éléments à côté des flottants

Lorsqu'un élément de type bloc suit un élément flottant, il devrait (en tant que bloc) ignorer le flottant, toutefois son contenu devrait être déplacé par le flottant : le texte dans un élément de type bloc à côté d'un élément flottant à gauche devrait s'écouler à la droite du flottant puis (s'il est plus long que le flottant) continuer sous lui. Mais si le bloc a la mise en page, par exemple du fait de l'affectation d'une largeur, alors l'élément entier est déplacé par le flottant, comme s'il était lui-même un flottant, et son contenu textuel n'épouse donc plus le contour du flottant (il reste à sa droite dans sa forme rectangulaire).

Dans IE 5, une largeur en pourcentage se calcule d'après l'espace disponible à côté du flottant, et dans IE 6, d'après la largeur disponible entière du bloc parent. Donc, dans IE 6, une déclaration width: 100% se traduit par quelque chose qui ne tient pas à côté du flottant, avec tous les problèmes de mise en pages causés par les blocs qui ne se logent pas.

Voici les jeux d'essais pour des blocs hasLayout adjacents de blocs flottants :

De la même façon en réalité, les éléments en position relative à côté de flottants devraient se décaler par rapport au bord d'espacement du parent (c'est-à-dire que la déclaration left: 0; sur une élément en position relative devrait le placer au sommet d'une boîte flottant à gauche précédente). Dans IE 6, un décalage left: valeur commence au bord de la marge droite du flottant, provoquant un désalignement horizontal de la totalité de la largeur (total outer width) du flottant (un palliatif serait d'utiliser margin-left à la place, mais attention aux anomalies bizarres des pourcentages).

Selon les spécifications, les flottants s'entrelacent avec les boîtes suivantes. Cela ne peut pas être réalisé avec des rectangles en deux dimensions qui ne s'entrecroisent pas.

Si l'auteur abdique devant les insuffisances d'IE, la question se pose alors de savoir comment rendre les boîtes dans les navigateurs conformes aux standards similaires à ces boîtes avec mise en page qui « se rétractent » pour laisser de la place à un flottant précédent. Nous donnons des pistes afin d'établir un nouveau contexte de formatage de bloc à côté du flottant dans notre section « Les similarités avec les spécifications CSS ».

En (re)visitant cette page-ci de bogues dans IE 6 :

Nous constatons que la boîte avec la mise en page suivant le flottant ne montre pas l'écart de 3 pixels du texte, parce que l'entourage codé de 3 pixels du flottant ne peut plus affecter le contenu dans l'élément qui a la mise en page, mais pousse l'élément qui a la mise en page entier de 3 pixels. Tel un bouclier, la mise en page empêche d'affecter le contenu mais l'énergie de poussée du flottant déplace la boîte protégée en question.

Les listes

Les listes sont affectées par la mise en page, qu'elle s'applique à la liste (ol, ul), ou bien aux éléments de la liste (li). Les diverses versions d'IE réagissent différemment. Les effets les plus visibles touchent aux marqueurs de listes (les listes entièrement personnalisées, où les marqueurs sont supprimés, n'ont pas ces problèmes). Les marqueurs sont probablement créés par l'addition interne, plutôt instable, d'éléments en quelque sorte « accrochés » aux éléments de listes (habituellement accolés à eux). Malheureusement, comme ce sont seulement des objets « internes », on ne peut pas y accéder pour tenter d'en corriger les inconduites.

Les effets les plus visibles sont les suivants :

On peut parfois les rétablir en changeant les marges des éléments de listes (li). Cela semble provenir du fait qu'un élément qui a la mise en page tend à rogner les éléments internes qui s'y accrochent.

Un autre problème (dans les listes ordonnées) est que tout élément de liste qui a la mise en page semble avoir son propre compteur. Supposons que nous ayons une liste ordonnée de cinq éléments où seul le troisième a la mise en page. Nous verrons ceci :

1... 2... 1... 4... 5...

En outre, lorsqu'un élément de liste qui a la mise en page s'affiche sur plusieurs lignes, le marqueur s'aligne en bas (et non en haut comme on s'y attendrait).

Tous ces problèmes ne peuvent pas être résolus, et si on souhaite des marqueurs, il vaut donc mieux éviter la mise en page sur les listes et éléments de listes. Si on a besoin d'appliquer des dimensions, il vaut mieux le faire sur les autres éléments : par exemple, on peut appliquer une largeur à une enveloppe extérieure et une hauteur au contenu de chaque élément de liste.

Un autre problème commun avec les listes dans IE survient lorsque le contenu d'un élement li est une ancre avec la déclaration display: block. Dans ces conditions, les caractères blancs (whitespace) entre les éléments de liste ne sont pas ignorés et s'affichent habituellement comme une ligne supplémentaire pour chaque li. Une méthode pour supprimer cet espace vertical en trop est de donner la mise en page à ces ancres de type bloc. Cela présente aussi l'avantage de rendre cliquable la totalité de la zone rectangulaire de l'ancre.

Les tables

Un élément table a toujours la mise en page et se comporte toujours comme un objet à largeur définie. Dans IE 6, la déclaration table-layout: fixed se traduit normalement par une table large de 100%, avec tous les problèmes que ça comporte (erreurs d'arrondis). En note marginale, quelques petites choses sur la situation dans IE 5.5 et dans IE 6 en « mode des bizarreries ».

Les éléments en position relative

Notez que position: relative ne déclenche pas hasLayout, ce qui conduit à quelques erreurs de rendu, principalement du contenu disparu ou mal placé. On peut rencontrer des incompatibilités lors du rechargement de la page, du redimensionnement ou du défilement de la fenêtre, de la sélection. Avec cette propriété, IE décale l'élément en semblant oublier d'envoyer un signal de « rafraîchissement » à ses sous-éléments qui ont la mise en page (comme un élément qui a la mise en page l'aurait correctement fait en l'envoyant dans la chaîne de commande des événéments de rafraîchissement).

Les pages précédentes en offrent des descriptions proches. En règle générale, ne jamais positionner un élément relativement sans établir la mise en page. De plus, on peut vérifier si le parent d'une telle construction a aussi besoin de la mise en page et/ou de position: relative, cela devient crucial lorsque des flottants sont affectés.

Les éléments en position absolue : le bloc conteneur, quel bloc conteneur ?

Il est essentiel de comprendre le concept CSS du bloc conteneur, qui répond à la question de savoir à quoi rapporter un élément en position absolue pour définir l'origine des décalages et calculer les pourcentages des longueurs.

Pour les éléments en position absolue, le bloc conteneur est établi par son ancêtre positionné le plus proche. S'il n'y en a pas, le bloc conteneur initial html est utilisé.

Normalement, un tel bloc conteneur serait établi via position: relative. Cela signifie que nous pouvons laisser les éléments en position absolue se rapporter aux longueurs et aux origines indépendamment du flux des éléments, c'est-à-dire de satisfaire aux besoins du concept d'accessibilité du « contenu d'abord » ou de faciliter les choses dans les mises en pages complexes avec des flottants.

Cette conception est remise en cause par IE : les décalages d'un éléments en position absolue sont correctement calculés seulement si le bloc conteneur a la mise en page, et la largeur en pourcentage d'un élément en position absolue peut se rapporter au mauvais ancêtre. Sur ce point, IE 5 et IE 6 se comportent différemment, mais tous deux ont des problèmes. IE 7b2 a un comportement plus cohérent, pourtant erroné dans certains cas. Si possible, essayez de vous tenir aux cas dans lesquels le bloc conteneur a la mise en page et est le parent de l'élément en position absolue (c'est-à-dire, qu'il ne doit pas y avoir d'autres ancêtres entre l'élément en position absolue et le bloc conteneur).

Supposons un parent sans mise en page en position relative, il nous faut impérativement lui donner la mise en page pour que le décalage fonctionne :

Supposons qu'un parent non positionné doive avoir une dimension, et que le plan repose sur le calcul d'une largeur en pourcentage, nous pouvons abandonner cette idée en absence de mise en œuvre dans les navigateurs :

La propriété filter

La propriété exclusive de Microsoft filter ne s'applique qu'aux éléments qui ont la mise en page. Elle présente des défauts spécifiques.

Le repositionnement des éléments rendus

Une fois tous les éléments rendus, IE repositionne le bloc conteneur qui a la mise en page lorsqu'une transition :hover (c'est-à-dire un changement de la propriété background du lien) se produit. Les éléments se trouvent parfois à une nouvelle position car toutes les largeurs et tous les décalages des éléments concernés ne sont connus d'IE qu'au moment de la transition hover. Il est peu probable que ce soit le cas lors du premier chargement, où la largeur n'est pas encore déterminée, à cause de la caractéristique de « prolongement-pour-loger» (expand-to-fit). Il peut y avoir un à-coup lors du hover.

Ces bogues relationnels, liés au problème du repositionnement, créent des problèmes dans les mises en pages liquides dans lesquelles l'utilisation de pourcentages pour les marges et espacements est la plus courante.

L'origine de l'arrière-plan

La propriété hasLayout de Microsoft affecte l'extension et le positionnement de l'arrière-plan. Par exemple, conformément à spécification CSS, la déclaration background-position: 0 0 devrait se rapporter au « bord de l'espacement » (padding edge) de l'élément. Dans IE/Win, elle se rapporte au « bord de la bordure » (border edge) si hasLayout=false, et au « bord de l'espacement » si hasLayout=true :

La fusion des marges

La propriété hasLayout de Microsoft affecte la fusion des marges (collapsing of margins) entre une boîte et ses descendants. Selon la spécification, la marge du haut d'une boîte sans espacement haut ni espacement bas et la marge du haut de son premier sous-élément de type bloc dans le flux devraient fusionner :

Dans IE/Win, ce n'est jamais le cas si la boîte a la mise en page : il semble que la mise en page empêche les marges du sous-élément de dépasser de la boîte englobante. En plus, si hasLayout=true, que ce soit sur le conteneur ou sur le sous-élément, d'autres erreurs de calcul des marges apparaissent :

La propriété hasLayout affecte la zone cliquable/sensible au survol des ancres de type bloc. Normalement, avec hasLayout=false, seule la partie couverte par le texte est sensible. Avec hasLayout=true, la totalité de l'aire du bloc est sensible. C'est la même chose pour tout élément de type bloc auquel est associé un gestionnaire d'événement onclick/onmouseover.

La navigation au clavier dans la page : une odyssée

Lorsqu'on « tabule » à travers une page et qu'on arrive sur un lien interne à la page, la pression suivante de la touche « tabulation » ne reprend pas sur l'ancre suivante :

La touche « tabulation » mènera l'utilisateur, souvent en le trompant, à la première cible de l'ancêtre qui a la mise en page le plus proche (si cet ancêtre est représenté par un élément table, div, span, et d'autres éléments).

L'enveloppe rétractable

Certaines propriétés appliquées aux éléments avec width: auto les poussent à calculer leur largeur selon un algorithme de rétractation. Comme exemples de ces propriétés : float: left|right, position: absolute|fixed, display: table|table-cell|inline-block|inline-table.

Cela fonctionne dans IE/Win et se limite bien sûr aux propriétés gérées. Mais lorsque l'élément qui devrait se rétracter contient un élément de type bloc affecté d'une mise en page, alors dans la plupart des cas, ce sous-élément s'étend sur toute la largeur disponible, indépendamment de son contenu, et empêche l'effet de rétractation du parent.

Exemple :
Un élément ul de navigation verticale flottant ne se rétracte pas, car il fallait une déclaration a {display: block; zoom: 1;} sur les liens pour corriger le bogue de la ligne blanche des listes et pour étendre la zone cliquable.

La rétractation reste en vigueur seulement si le sous-élément avec la mise en page est affecté d'une largeur, ou s'il a lui-même une propriété à rétractation telle que float.

Le rognage au bord

En général, lorsqu'une boîte contient des structures plus complexes, comme un contenu qui dépasse, la propriété hasLayout est souvent nécessaire sur ce conteneur pour éviter des problèmes de rendu. Cette quasi obligation entraîne un dilemme aux frontières, puiqu'un élément de type bloc gagnant la mise en page devient une sorte de boîte auto-contenue.

Les boîtes de contenu imbriquées poussées hors de cet élément (par exemple, en utilisant des marges négatives) sont rognées.

Les parties rognées peuvent être rétablies en déclenchant hasLayout sur cette boîte de contenu, et dans IE 6, il faudra aussi utiliser position: relative. Le comportement d'IE 7 montre un léger mieux puisque la déclaration position: relative n'est plus nécessaire.

Empilement, couches et mise en page

Il semble y avoir deux ordres des couches et de l'empilement au sein d'IE/Win :

Les deux modèles d'empilement, incompatibles, sont des résidents du moteur de rendu d'IE. En règle générale, pendant le débogage, ne pas oublier de surveiller les deux suspects. Nous voyons régulièrement des problèmes liés dans les menus déroulants ou de complexité similaire, où l'empilement, le positionnement et le flottement peuvent concourir à des désastres variés, et les corrections de bogues peuvent consister en mises en pages positionnées en couches, mais c'est variable, vous êtes prévenus.

La débâcle contenteditable

L'attribut contenteditable=true, affecté à une balise HTML tel que <body contenteditable=true>, permet l'édition, le glissement et le redimensionnement en direct de l'élément qui a la mise en page et ses sous-éléments. Essayez donc ça avec des éléments flottants ou des éléments li qui ont la mise en page dans une liste ordonnée.

Afin de manipuler les éléments (les éditer), contenteditable et hasLayout introduisent un ordre d'empilement séparé pour les éléments avec hasLayout=true.

La plateforme d'édition (un document retiré du réseau MSDN [2]) hérite du concept de mise en page, preuve que contenteditable est la raison de la conception erronée de la mise en page (avec l'implication que les applications intégrant quelque peu le moteur d'édition d'IE forcent une rétrocompatibilité vers ce concept de mise en page).

Les similarités avec les spécifications CSS

Vos pages conçues pour IE sont-elles défaillantes dans les autres navigateurs ? Ce n'est pas une fatalité, sachez-le ! N'importe quel bon navigateur peut tout aussi bien manipuler les conceptions d'IE si vous lui demandez gentiment (et lui servez du CSS valide).

L'utilisation des « quelques » similarités trouvées entre hasLayout et l'établissement d'un « nouveau contexte de formatage de bloc », nous donne le moyen de reproduire l'effet de hasLayout pour le « confinement des flottants » et le comportement des « éléments à côté d'un élément flottant » dans les navigateurs conformes aux standards.

Le mode des bizarreries

Veuillez consulter « Le mode des bizarreries dans IE 6 et IE 7 » (quirks mode) pour des renseignements à propos de ce mode de rendu.

Mise en page : une conclusion

Le concept de la mise en page dans son ensemble n'est pas compatible avec plusieurs concepts CSS de base du modèle de formatage visuel, comprenant notamment ceux de flux, de flottement et des couches.

Cela entraîne des violations propres à IE/Win de la spécification CSS dues à la présence ou l'absence de mise en page sur les éléments de la page.

Avoir la mise en page : est-ce une partie d'un autre moteur ?

Le modèle d'objets dans Explorer paraît être l'hybride d'un modèle de document et de leur modèle d'application traditionnel. J'en fait mention car c'est important pour comprendre comment Explorer rend les pages. La bascule pour sauter d'un modèle de document à un modèle d'application est le fait de donner la mise en page à un élément.

(Dean Edwards)

Parfois, il est impossible de donner une interprétation d'un certain comportement : c'est simplement comme si, en fonction de l'état de hasLayout, l'un des deux moteurs de rendus différents était utilisé, chacun avec ses propres bizarreries et bogues.

L'absurdité des bogues

Les bogues des logiciels sont les conséquences d'erreurs humaines et d'une absence de prise en compte du global et de logique pendant le processus de création. C'est un défaut humain fondamental pour lequel il reste à découvrir un remède durable.
Toutes les tentatives de corriger un programme bogué sans le recréer à zéro aboutira inévitablement à encore plus de bogues plus complexes trouvant leur chemin dans le logiciel à cause de ces mêmes défauts humains.
Tout programme qui repose sur d'autres, y compris (bien sûr) les systèmes d'exploitation, héritera aussi de leurs bogues. Nous obtenons ainsi une cascade de bogues de tous les bouts de code impliqués, qui rend l'idée même de trouver un programme sans bogues complètement absurde.

(Molly le chat)

Cet article est d'abord paru le 30 juin 2005 et a été révisé pour la dernière fois le 23 octobre 2007.

Rédacteurs :
Holly Bergevin
Ingo Chao
Bruno Fassino
John Gallant
Georg Sørtun
Philippe Wittenbergh
Remerciements spéciaux pour leur soutien du projet à :
Dean Edwards, Molly le chat, David Laakso et Corina Rudel
Traductions :
Portugais brésilien, de Mauricio Samy Silva
Bulgare, de Yordan Stoev
Chinois, de old9
Allemand, de Corina Rudel
Italien, de Gabriele Romanato
Russe, de DreamwinD
Français, de Jean-Jacques Solari
Les traductions sont les bienvenues, veuillez nous contacter.
Discuter de cet article :
dean.edwards.name/weblog/
Nous contacter :
Droits d'auteurs :
Ce travail est publié sous licence Creative Commons.

Adresse permanente : http://www.satzansatz.de/cssd/onhavinglayout.html

  1. Le document original a été modifié dans la documentation MSDN. Nous nous référons à une version disponible dans les archives Internet (Contrôler la présentation avec les propriétés de mesure et d'emplacement) ;
  2. Le document original qui a été retiré de la documentation MSDN est disponible dans les archives Internet (« La plateforme d'édition MSHTML dans Internet Explorer 5.5 »).
© 1999-2008 yoyodesign.org — Certains droits réservés