Über hasLayout

Ein »Work-In-Progress«.
Originalartikel (englisch): On having layout
Diese Version: Rev. 7 2007–05–09
Verzeichnis der Änderungen
Übersetzungen
Inhaltsverzeichnis

Einführung

Viele Darstellungsprobleme des Internet Explorer lassen sich beheben, indem man einem Element »Layout« gibt. John Gallant und Holly Bergevin haben diese Ungereimtheiten als »dimensional bugs« bezeichnet, Fehler also, die durch Angabe einer Höhe (height) oder Breite (width) beseitigt werden können. Das führt zur Frage, weshalb »Layout« die Darstellung und die Beziehungen von Elementen beeinflussen kann. Eine gute Frage, die sich allerdings nur schwer beantworten lässt. In diesem Artikel beleuchten die Autoren einige Aspekte dieser komplizierten Angelegenheit. Für weitergehende Diskussionen und Beispiele folgen Sie bitte den angebotenen Links.

hasLayout — Eine Definition

»Layout« ist ein proprietäres Konzept des IE/Win, das bestimmt, wie Elemente ihren Inhalt zeichnen und begrenzen, wie sie mit anderen Elementen interagieren und in welcher Beziehung sie stehen und wie sie auf Anwendungs- oder Benutzeraktionen reagieren und sie übertragen.

Diese Qualität wird unwiderruflich von einigen CSS-Eigenschaften hervorgerufen. Einige Elemente haben von vornherein »Layout«.

Die Entwickler bei Microsoft haben entschieden, dass Elemente eine »Eigenschaft« (im Sinne objektorientierter Programmierung) annehmen können, die sie hasLayout nennen. Diese wird auf true gesetzt, sobald dieses Darstellungskonzept greift.

Nomenklatur

Wir sprechen davon, dass ein Element »Layout erhält« oder »Layout hat«, wenn die Microsoft-proprietäre Eigenschaft hasLayout für dieses Element auf true gesetzt ist. Ein »Layout-Element« kann jedes Element sein, das »Layout« von vornherein besitzt oder »Layout« durch bestimmte CSS-Eigenschaften erhält.

Bei »Nicht-Layout«-Elementen ist hasLayout nicht gesetzt, z.B. kann ein div ohne Dimension ein »Nicht-Layout-Vorfahre« sein.

Wenn man einem Element, das nicht von vornherein »Layout« hat, »Layout« zuweisen will, so ist es erforderlich, eine CSS-Eigenschaft anzuwenden, die hasLayout = true für das fragliche Element verursacht. Eine entsprechende Auflistung finden Sie unter Elemente, die von vornherein »Layout« haben und Eigenschaften. Es gibt keine Möglichkeit, hasLayout = false zu setzen, außer diejenige CSS-Eigenschaft zu löschen oder zurückzusetzen, die hasLayout = true ursprünglich hervorgerufen hat.

Womit wir es zu tun haben

Mit dem hasLayout-Problem haben Designer (und Coder) unabhängig von ihrer Erfahrung zu schaffen. »Layout« hat ungewöhnliche und schwer vorhersehbare Auswirkungen auf die Darstellung von Boxen – und ebenso Folgen für deren Nachfahrenelemente.

Ob ein Element »Layout« hat (oder auch nicht) kann u.a. Folgendes nach sich ziehen:

Die obige Liste ist kurz und unvollständig. Dieser Artikel versucht, die Probleme gründlicher zu beschreiben, die durch Hinzugabe (oder durch das Fehlen) von »Layout« auftreten.

Woher »Layout« kommt

Anders als bei Standard-Eigenschaften, oder sogar anders als bei proprietären Eigenschaften verschiedener Browser, wird »Layout« nicht unmittelbar durch eine CSS-Angabe zugewiesen. Mit anderen Worten: es gibt keine »Layout-Eigenschaft«. Bestimmte Elemente haben automatisch »Layout«, und es wird stillschweigend mit verschiedenen CSS-Angaben hinzugefügt.

Elemente, die von vornherein »Layout« haben

Die folgenden Elemente scheinen grundsätzlich »Layout« zu haben.

Eigenschaften

Bei Anwendung der folgenden CSS-Eigenschaft/Wert-Paare kann ein Element »Layout« erhalten.

position: absolute
Bezieht sich auf das umgebende Element (containing block), und damit fangen die Probleme an.
float: left|right
Das Float-Modell hat viele Unstimmigkeiten, die auf einige Aspekte eines Layout-Elements zurückzuführen sind.
display: inline-block
Machmal ein Heilmittel, wenn ein Element auf Inline-Level »Layout« braucht. Es ist vermutlich der einzige wirkliche Effekt dieser Eigenschaft. Das »Inline-Block-Verhalten« selbst kann im IE erzielt werden, jedoch gänzlich unabhängig: IE/Win: inline-block und hasLayout.
width: jeder Wert außer 'auto'
Das ist oft eine unbeabsichtigte Lösung, noch öfter der Auslöser für Fehlverhalten durch hasLayout.
height: jeder Wert außer 'auto'
height: 1% wird beim Holly Hack verwendet.
zoom: jeder Wert außer 'normal' (MSDN)
Microsoft-proprietär, nicht valide. zoom: 1 kann bei der Fehlersuche eingesetzt werden.
writing-mode: tb-rl (MSDN)
Microsoft-proprietär, nicht valide.

Im IE7 ist die overflow-Eigenschaft ein Auslöser für »Layout« geworden.

overflow: hidden|scroll|auto
Diese Eigenschaft wurde in früheren Versionen erst dann angewendet, wenn die Box auf andere Art »Layout« erhielt.
overflow-x|-y: hidden|scroll|auto
Als Teil des CSS3-Box-Modell-Moduls werden overflow-x und-y noch nicht umfassend unterstützt. In früheren Versionen des IE haben sie nicht hasLayout ausgelöst.

Und neue hasLayout-Akteure betreten die Bühne im IE7. Was hasLayout angeht, verhalten sich die Eigenschaften min-/max-height und min-/max-width wie height und width, und die Auswirkungen von fixer und absoluter Positionierung scheinen identisch zu sein.

position: fixed
./.
min-width: jeder Wert
Sogar durch den Wert 0 erhält ein Element »Layout«.
max-width: jeder Wert außer 'none'
./.
min-height: jeder Wert
Sogar der Wert 0 setzt haslayout=true
max-height: jeder Wert außer 'none'
./.

Beruht auf Befragung der IE Developer Toolbar und vorläufigen Tests.

Anmerkungen zu Elementen auf Inline-Level

Für Inline-Elemente (entweder standardmäßig inline, wie span, oder durch display:inline) gilt:

Elemente, die sowohl »Layout« als auch display: inline haben, verhalten sich in einer ähnlichen Weise, wie es die Standards für inline-block vorsehen: Sie ordnen sich nebeneinander an wie Wörter in einem Textabsatz, sie reagieren auf vertical-align und passen ihre Breite auf eine Art ihrem Inhalt an (shrink-wrapping). Sobald Inline-Elemente »Layout« haben, verhalten sie sich wie inline-block; das erklärt, weshalb Inline-Elemente im IE/Win weniger Probleme bereiten, wenn sie Blockelemente enthalten, als es in anderen Browsern der Fall ist, wo display: inline stets inline bleibt.

hasLayout zurücksetzen

Wenn folgende Eigenschaften in einer separaten Regel auf ihren Initialwert zurückgesetzt werden, so wird hasLayout zurückgesetzt (oder aufgehoben), sofern nicht eine andere layout-verursachende Eigenschaft bestehen bleibt:

Autoren müssen vorsichtig sein beim Zurücksetzen dieser Eigenschaften. Man denke an ein Menüsystem: Eine Änderung des hasLayout-Status bei a:hover – beabsichtigt oder nicht – kann eine unerwartete Darstellung nach sich ziehen (oder Programminstabilität im IE6, wenn das Zurücksetzen dynamisch in Kombination mit position: relative geschieht).

Die display-Eigenschaft weicht davon ab: während 'inline-block' haslayout = true auslöst, so wird es nicht auf haslayout = false zurückgesetzt, wenn der Wert später in einem anderen Regelsatz durch 'block' oder 'inline'  überschrieben wird.

Die Eigenschaften min-width, min-height verursachen auch dann hasLayout, wenn sie auf ihren Ursprungswert '0' gesetzt werden, doch IE7 akzeptiert den nicht-validen Wert 'auto', der hasLayout zurücksetzt.

Die Script-Eigenschaft hasLayout

Wir haben uns entschieden, hasLayout eine »Script-Eigenschaft« zu nennen, um sie von den bekannten CSS-Eigenschaften abzugrenzen.

Es gibt keine Möglichkeit, die Script-Eigenschaft hasLayout direkt zu setzen oder zurückzusetzen.

Mit der hasLayout-Eigenschaft kann man überprüfen, ob ein Element Layout hat: wenn ein Element zum Beispiel die id »eid« hat, dann kann man im IE5.5+ durch Eingabe von javascript: alert(eid.currentStyle.hasLayout) in der Adressleiste den hasLayout-Status überprüfen.

Mit der IE Developer Toolbar kann man unmittelbar die aktuellen Style-Zuweisungen für ein Element überprüfen; wenn hasLayout auf »true« gesetzt ist, so wird der Wert »-1« ausgegeben. Bei Direktänderung der Attribute eines Knotens kann man zur Fehlersuche hasLayout setzen, indem man »zoom (css)« auf den Wert »1« setzt.

Nicht zu vergessen der Einfluss von »Layout« auf Scripting. Die Eigenschaften clientWidth/clientHeight liefern immer Null für Elemente, die kein »Layout« haben. Das kann für Neulinge verwirrend sein und unterscheidet sich vom Verhalten der Mozilla-Browser. Wir können diese Tatsache nutzen, um »Layout« im IE5.0 zu bestimmen: Wenn clientWidth Null liefert, dann hat ein Element kein »Layout«.

CSS-Hacks

Die folgenden Hacks lösen haslayout aus und sind umfassend in IE6 und darunter getestet. Zukünftige IE-Versionen werden möglicherweise anders reagieren. Wir werden uns damit erneut befassen, wenn neue Versionen dieses Browsers allgemein verfügbar sind.

John Gallant and Holly Bergevin haben 2003 den Holly Hack veröffentlicht:

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

Wir können auch den Unterstrich-Hack nutzen:

  1. .gainlayout { _height: 0; }

Alternativ, und möglicherweise zukunftssicherer, sind Bedingte Kommentare (Conditional Comments):

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

Die Verwendung eines externen Stylesheets für alles, was IE-Win benötigt – aus einem bedingten Kommentar verlinkt – ist ebenso eine sichere und elegante Lösung:

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

Wir bevorzugen height: 0 und 1px. height sollte »immer« verwendet werden, außer es gibt Konflikte mit einer anderen Angabe (overflow: hidden). Wir ziehen es vor, den Wert 1% zu vermeiden, da er (wenn auch nur sehr selten) Probleme verursachen kann.

height kann nicht bei Inline-Elementen im Standardmodus eingesetzt werden. In diesem Fall können wir display: inline-block oder zoom: 1 verwenden.

Wir haben verzweifelte Versuche von »Holy«-Hacks (sic!) gesehen, die auf Float-Elemente oder Elemente, die bereits eine Breite hatten, angewendet wurden. Denken Sie daran: Das Ziel eines solchen Hacks ist es nicht, einem Element eine Höhe zu geben, sondern hasLayout = true auszulösen.

Geben Sie nicht allem und jedem »Layout«: * {_height: 1px;}. In dieser Dosis wird »Layout« zum Gift, nicht zum Heilmittel; es verändert die Darstellung grundlegend.

Der Umgang mit Hacks

Doch die Browser, sie ändern sich – und wir haben der Tatsache ins Auge zu sehen, dass in Abhängigkeit von den Fehlern, die im IE7 und höher beseitigt werden, unvermeidbare Hacks für den IE6 in neuen Browserversionen scheitern (oder gar Schaden anrichten) können, oder dass neue Browserversionen zwar ähnliche Darstellungsfehler aufweisen, jedoch keine Filter wie * html mehr mitbringen. So gesehen kann man die Verwendung der MS-proprietären zoom-Eigenschaft empfehlen.

  1. <!--[if lt IE 7]><style>
  2. /* style for IE 6 + IE5.5 + IE5.0 */
  3. .gainlayout { height: 0; }
  4. </style><![endif]-->
  5.  
  6. <!--[if IE 7]><style>
  7. .gainlayout { zoom: 1;}
  8. /* oder was auch immer wir in Zukunft brauchen werden */
  9. </style><![endif]-->

Obwohl wir »zukunftssicher« für einen Widerspruch in sich halten, empfehlen wir dringend, dass Webdesigner auf »Nummer sicher« gehen und ihre Dokumente nach gewollten und ungewollten »Hacks« durchsuchen – und Conditional Comments nutzen, um diese Hacks den passenden Browserversionen zukommen lassen.

Eine kurze Anmerkung zum IE Mac.

IE Mac und IE für Windows sind zwei verschiedene Tierarten, die in getrennten Bereichen des Zoos leben. Jeder hat seine eigene Rendering Engine und IE Mac kennt das »hasLayout«-Verhalten (oder contenteditable) auf keinerlei Art. Die Rendering Engine des IE Mac entspricht eher den Standards, so wird z.B. height behandelt, wie es sein sollte. Hacks und Workarounds für »hasLayout«-Probleme haben – ganz besonders, wenn height oder width verwendet werden – oft schädliche Auswirkungen im IE Mac und sollten vor diesem Browser verborgen bleiben. Mehr zu Problemen im IE Mac finden Sie auf den Seiten IE Mac, Fehler und Besonderheiten (IE Mac, bugs and oddities).

Die MSDN-Dokumentation

In der MSDN-Dokumentation beziehen sich nur sehr wenige Dokumente auf die  MS-Eigenschaft hasLayout; und noch weniger wird erklärt, wie »Layout« mit dem visuellen Formatierungsmodell des IE zusammenhängt .

Zu Zeiten des IE4 hatte nahezu jedes Element eine Art von »Layout", außer einfache Inline-Elemente, die nicht absolut positioniert und ohne eine Dimensionsangabe waren (MSDN – das Dokument wurde modifiziert1). Und in diesem frühen Layout-Konzept gab es »Layout-Eigenschaften« wie border, margin, padding, die einem solchen einfachen Inline-Element nicht zugewiesen werden konnten. Mit anderen Worten: »Layout haben« war eine andere Formulierung für etwas wie: »kann diese Eigenschaften haben«.

MSDN spricht noch immer von »Layout-Eigenschaften (layout properties), doch die Bedeutung hat sich verändert. Sie sind nicht mehr mit Elementen verknüpft, die »Layout haben«. Im IE 5.5 wurde die MS-Eigenschaft hasLayout eingeführt, mehr oder weniger eine interne Auszeichnung.

Für IE 5.5 enthüllt die Dokumentation der MSHTML Editing Platform (die es mittels <body contenteditable=true> erlaubt, Layout-Elemente »live« zu editieren, zu skalieren und zu verschieben) drei bedeutende Aspekte bezüglich »Layout«:

Wenn ein Layout-Element Inhalte hat, wird die Anordnung dieser Inhalte durch das begrenzende Rechteck des Elements bestimmt.

»Layout haben« heißt hauptsächlich, dass ein Element rechteckig ist.

Intern bedeutet Layout, dass ein Element verantwortlich für das Zeichnen seines Inhalts ist.

(Editing Platform – das Dokument wurde aus dem MSDN entfernt2)

Die interne Arbeitsweise bezüglich »Layout« selbst wurde bis August 2005 nicht dokumentiert, bis Markus Mielke [MSFT] – als Ergebnis des The Web Standards Project und der Microsoft Task Force – die Tür für eine gründlichere Diskussion öffnete:

Im Allgemeinen sind Elemente in der Dynamic HTML Engine des Internet Explorer nicht verantwortlich für ihre eigene Anordnung. Ein div- oder ein p-Element mag eine bestimmte Position in der Code-Reihenfolge und im Dokumentfluss haben, aber ihre Inhalte werden bezüglich ihres nächsten Vorfahren mit »Layout« (meist body) angeordnet. Diese Elemente verlassen sich darauf, dass der Layout-Vorfahre all die Schwerstarbeit für sie übernimmt, ihre Größe und Ausmaße festzulegen.

(HasLayout-Übersicht (HasLayout Overview))

Interpretation

Unsere Interpretation ist ein Versuch zu erklären, was sich bei bekannten Fällen abspielt, und sie soll als Anhaltspunkt für die nicht vollständig bekannten Fälle dienen. Der Versuch, unbekannte Gefilde allein dadurch zu ergründen, dass man ein paar Testfälle hineinwirft und abwartet, ob sich etwas regt, ist zum Scheitern verurteilt. Die Frage nach dem »Warum« lässt sich nicht beantworten. Wir müssen die Rahmenbedingungen verstehen, unter denen das gesamte »hasLayout«-Modell arbeitet und wie es die Darstellung eines Web-Dokuments beeinflusst. Ausgehend davon können Richtlinien erarbeitet werden (und diese können nur Richtlinien sein, keine vollkommenen Lösungen).

Wir glauben, sie sprechen von einem kleinen Fenster. Der Inhalt eines Layout-Elements ist völlig unabhängig von allem, was außerhalb der Grenzen des Elements liegt, und auch der Inhalt  kann nichts außerhalb beeinflussen.

Die MS-eigene hasLayout-Eigenschaft ist eine Art Markierung (flag): wenn sie gesetzt ist, hat das Element eine »Layout-Qualität«, die für das Element selbst und seine »Nicht-Layout«-Nachfahren besondere Fähigkeiten nach sich zieht – z.B. bezüglich Float und Stapelreihenfolge.

Diese größere Unabhängigkeit der Layout-Elemente ist vermutlich der Grund, weshalb sie meistens stabiler sind und so einige Fehler verschwinden lassen. Der Preis dafür können sowohl Abweichungen von den Standards als auch weitere Fehler/Probleme dort sein, wo das Layout-Element an andere grenzt.

Das MS »Seiten«-Modell kann man – bildlich gesprochen – als kleine, unzusammenhängende Kurzgeschichten betrachten, wohingegen das »Seiten«-Modell von HTML und W3C eine vollständige, zusammenhängende Erzählstruktur hat.

Eine Übersicht der Auswirkungen

Clear bei Float und Mitwachsen

Floats werden von Layout-Elementen automatisch eingeschlossen. Das ist einer der Gründe, weshalb die meisten Anfänger mit ihren für IE erstellten Seiten in standardkonformen Browsern kämpfen; dort hängen die Floats aus dem umgebenden Container heraus, wenn es kein clear gibt.

Das gegenteilige Verhalten: was, wenn ein Float aus seinem Container herausragen muss, z.B. wenn automatisches Einschließen nicht gewünscht ist? Eine Demonstration der frustrierenden Probleme, mit denen man konfrontiert werden kann, finden Sie in unserer Untersuchung:

Im IE »gehört« ein Float immer zu seinem Layout-Container. Nachfolgende Elemente mögen zwar den Layout-Container respektieren, nicht jedoch das Float selbst.

Dies und die Eigenart des IE6, Elemente mit übergroßem Inhalt auszudehnen (»extend-to-fit«), kann man als einen Aspekt der Regel »wird durch das begrenzende Rechteck des Elements bestimmt« sehen.

Sogar noch schlimmer: clear kann nicht auf ein Float wirken, das außerhalb des Layout-Elements liegt, welches das Clear umgibt. Float-Layouts, die auf diesen Fehler des IE bauen, funktionieren nicht ohne umfassende Überarbeitung in einem standardkonformen Browser.

Das – manchmal unvermeidliche – automatische Einschließen von Floats kann man auch in anderen Browsern erreichen. In unserem Bereich »Ähnlichkeiten mit der der CSS-Spezifikation« finden Sie Konzepte zum Einschließen von Floats.

Elemente nach Floats

Wenn ein Blockelement auf ein Float folgt, dann sollte es – als Block – das Float ignorieren, doch seine Inhalte sollten dem Float ausweichen: der Text in einem Block-Level-Element nach einem Element mit float:left sollte rechts am Float vorbeifließen und dann (wenn der Inhalt länger als das Float ist) unter dem Float fortgesetzt werden. Doch wenn das Element »Layout« hat – sagen wir, aus irgendeinem Grund ist eine Breite gesetzt – so wird das gesamte Element neben das Float gesetzt – als wäre es selbst ein Float – und so fließt der Text nicht mehr um das Float herum (er bleibt rechts daneben, begrenzt durch ein Rechteck).

Eine Breite in Prozent wird im IE 5 auf Grundlage des verfügbaren Platzes neben dem Float berechnet; im IE 6 auf Grundlage der gesamten verfügbaren Breite des Elternelements. Ein Element mit width:100% passt daher im IE 6 nicht neben das Float – mit allen Konsequenzen, die ein nicht-passendes Element nach sich zieht.

Testfälle für Elemente mit Layout, die an Floats grenzen:

Ähnlich dazu sollten relativ positionierte Elemente nach Floats eigentlich bezogen auf die Padding-Kante des Elternelements verschoben werden (d.h. left:0; sollte ein r.p. Element über einem vorhergehenden Float platzieren). Im IE 6 beginnt die Verschiebung left: Wert; von der rechten Margin-Kante des Float-Elements aus, was eine horizontale Verschiebung in der Größe der äußeren Gesamtbreite des Float-Elements nach sich zieht (stattdessen margin-left zu verwenden ist eine mögliche Lösung – doch hüten Sie sich vor den seltsamen Fehlern bei Prozentwerten).

Gemäß der Spezifikationen verweben sich Float-Elemente mit nachfolgenden Boxen. Dies kann man nicht mit zweidimensionalen Rechtecken erreichen, die sich nicht überschneiden.

Wenn der Autor der Unzulänglichkeit des IE nachgibt, dann taucht die Frage auf, wie man Boxen in standardkonformen Browsern dazu bringen kann, genauso wie diese Layout-Boxen auszusehen, die sich »zurückziehen« um Platz für das vorhergehende Float zu schaffen. Im Bereich “Ähnlichkeiten mit der CSS-Spezifikation” stellen wir Möglichkeiten vor, einen neuen Block-Formatierungskontext nach dem Float zu schaffen.

Wenn wir (wieder) diese Seite zu Fehlern im IE 6 besuchen

werden wir sehen, dass die Layout-Box, die auf das Float folgt, keine 3px-Verschiebung beim Text zeigt. Die festzementierten 3px, die das Float umgeben, können den Inhalt im Layout-Element nicht mehr beeinflussen, doch sie verschieben das gesamte Layout-Element um 3px. Wie ein Schild hat »Layout« den Inhalt vor dem Einfluss bewahrt, doch die Kraft des Float-Stoßes verschiebt die geschützte Box selbst.

Listen

Listen sind von »Layout« betroffen, das auf die Liste (ol, ul) oder die Listenelemente (li) angewendet wird. Verschiedene IE-Versionen verhalten sich verschieden. Am offensichtlichsten sind die Auswirkungen auf die Marker (komplett durchgestaltete Listen, bei denen die Marker nicht nötig sind, haben diese Probleme nicht). Die Marker werden wahrscheinlich erzeugt, indem intern einige Elemente hinzugefügt werden, die den Listenelementen irgendwie "angehängt" werden (normalerweise hängen sie aus ihnen heraus) und ziemlich instabil scheinen. Weil diese Objekte nur »intern« sind, kann man unglücklicherweise nicht auf sie zugreifen, um Fehlverhalten zu korrigieren.

Die offensichtlichsten Auswirkungen sind:

Manchmal können sie durch Änderung der Randabstände bei den Listenelementen zurückgeholt werden. Das scheint eine Folge der Tatsache zu sein, dass Layout-Elemente dazu neigen, heraushängende innere Elemente abzuschneiden.

Ein weiteres Problem bei geordneten Listen: jedes Listenelement mit »Layout« scheint seinen eigenen Zähler zu haben. Angenommen wir haben eine geordnete Liste mit fünf Elementen; davon hat nur das dritte »Layout«. Wir werden folgendes sehen:

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

Weiterhin: wenn sich ein Listenelement mit »Layout« über mehrere Zeilen erstreckt, so wird der Marker am unteren Rand ausgerichtet (nicht wie erwartet am oberen).

Gegen manche dieser Probleme ist kein Kraut gewachsen; daher ist es besser, »Layout« bei Listen zu vermeiden, wenn Marker gewünscht sind. Wenn es notwendig ist, eine Dimension zu vergeben, dann ist sie besser bei einem anderen Element aufgehoben: zum Beispiel kann eine Breite einem umgebenden Element zugewiesen werden, und eine Höhe dem Inhalt eines jeden Listenpunktes.

Ein weiteres häufiges Problem bei Listen tritt auf, wenn der Inhalt eines li aus einem Anker mit display: block besteht. Unter dieser Voraussetzung wird der Leerraum (white space) zwischen Listenpunkten nicht ignoriert und normalerweise als zusätzliche Zeile für jedes li dargestellt. Eine Methode zur Vermeidung dieses zusätzlichen vertikalen Abstands besteht darin, dem Anker zusätzlich zum display:block auch noch »Layout« zu geben. Das hat zudem den Vorteil, dass dann die gesamte rechteckige Linkfläche klickbar wird.

Tabellen

Eine Tabelle hat immer »Layout«, verhält sich immer wie ein Objekt mit definierter Breite. Im IE 6 ist table-layout: fixed normalerweise gleichbedeutend mit einer Tabelle mit einer Breite von 100%, einschließlich aller Probleme, die das mit sich bringt (fehlerhafte Berechnungen). Nebenbei ein paar Dinge zur Situation in IE 5.5 und IE 6 im »Quirksmodus«.

Relativ positionierte Elemente

Beachten Sie, dass position: relative kein hasLayout auslöst. Das führt zu einigen Darstellungsfehlern, meistens zu verschwindendem oder verschobenem Inhalt. Man begegnet Widersprüchlichkeiten beim Neuladen von Seiten, beim Ändern der Fenstergröße, beim Scrollen und beim Markieren/Auswählen von Inhalt. Bei dieser Eigenschaft verschiebt der IE zwar das Element, aber scheint zu vergessen, seinem Layout-Kindelement ein »Neuzeichnen« zu schicken (was ein Layout-Element korrekterweise in der Signalkette der Neuzeichen-Ereignisse getan hätte).

sind Beschreibungen, die damit in Zusammenhang stehen. Als Faustregel: niemals ein Element relativ positionieren, ohne ihm »Layout« zu geben. Außerdem sollten wir prüfen, ob das Elternelement eines solchen Konstrukts ebenfalls »Layout« und/oder position: relative braucht; das ist unabdingbar, wenn Floats betroffen sind.

Absolut positionierte Elemente:
umschließender Block, welcher umschließende Block?

Es ist wesentlich, das CSS-Konzept des umschließenden Blocks (containing block) zu verstehen. Damit wird bestimmt, worauf ein absolut positioniertes Element Bezug nimmt: wo der Ausgangspunkt der Verschiebung liegt, und worauf sich Längenangaben in Prozent beziehen.

Für ein a.p. Element ist der nächste positionierte Vorfahre der umschließende Block. Wenn es keinen solchen Vorfahren gibt, so wird der umschließende Ausgangsblock (initial containing block) des html-Elements verwendet.

Normalerweise würden wir einen solchen umschließenden Block per position:relative erzeugen. Das bedeutet, dass wir Längen und Ursprünge von a.p. Elementen unabhängig vom Dokumentfluss belassen können. Damit können wir die Bedürfnisse des Zugänglichkeitskonzeptes »Inhalt zuerst« erfüllen oder uns das Leben in komplexen Float-Layouts einfacher machen.

Dieses Design-Konzept wird vom IE in Frage gestellt: Verschiebungen eines a.p. Elements werden nur dann korrekt berechnet, wenn der umschließende Block »Layout« hat, und die Prozentbreite eines a.p. Elements kann sich auf den falschen Vorfahren beziehen. Dabei verhalten sich IE 5 und IE 6 unterschiedlich, aber beide haben Probleme. IE 7b2 ist dabei beständiger, verhält sich aber in einigen Fällen noch immer fehlerhaft. Wenn möglich, halten Sie sich an Fälle, in denen der umschließende Block »Layout« hat und Elternelement des a.p. Elements ist (d.h. dass keine weiteren Vorfahren zwischen dem a.p. Element und dem umschließenden Block liegen).

Angenommen ein Nicht-Layout-Elternelement ist relativ positioniert – wir werden dazu gezwungen, diesem Elternelement »Layout« zu geben, damit die Verschiebung funktioniert:

Angenommen ein nicht-positioniertes Elternelement muss eine Dimension bekommen und das Design beruht auf Prozentwerten – das können wir wegen mangelnder Browserunterstützung vergessen:

Filter

Die MS-proprietäre Filter-Eigenschaft kann nur auf Layout-Elemente angewandt werden. Sie zeigen ihre eigenen speziellen Fehler.

Neuanordnung bereits dargestellter Elemente

Wenn einmal alle Elemente dargestellt sind, so ordnet der IE den umschließenden Block neu an, wenn eine Änderung durch :hover auftritt (d.h., wenn sich der Hintergrund eines Links ändert). Manchmal werden die Elemente neu positioniert, weil im Moment des :hover alle Breiten und Verschiebungen des betreffenden Elements bekannt sind. Das tritt nicht beim ersten Laden auf, weil zu diesem Zeitpunkt die Breite dank des »Mitwachsens« noch unbestimmt ist. Das kann zum Verspringen bei :hover führen.

Diese vom Neuzeichnen abhängigen Beziehungsprobleme verursachen  Schwierigkeiten bei flexiblen Layouts, wo man häufig Prozentwerte für margin und padding einsetzt.

Ursprung des Hintergrunds

Die hasLayout-Eigenschaft beeinflusst die Ausdehnung und die Positionierung des Hintergrunds. Gemäß CSS-Spezifikation sollte sich zum Beispiel ein background-position: 0 0 auf die Padding-Kante eines Elements beziehen. Im IE/Win bezieht es sich auf die Border-Kante, wenn hasLayout = false ist, und auf die Padding-Kante, wenn hasLayout=true ist:

Zusammenfallende Ränder (Collapsing Margins)

Die hasLayout-Eigenschaft beeinflusst das Zusammenfallen der Ränder von einer Box und ihren Nachfahren. Gemäß Spezifikation sollte der obere Margin einer Box, die kein oberes Padding und keinen oberen Border besitzt, mit dem oberen Margin ihres ersten Block-Level-Kindelements zusammenfallen, das sich im normalen Fluss befindet:

Im IE/Win geschieht das nie, wenn eine Box »Layout« hat: Es scheint, dass »Layout« verhindert, dass die Margins der Kindelemente aus der umgebenden Box herausragen. Zudem treten weitere  falsche Margin-Berechnungen auf, wenn entweder beim umgebenden Element oder beim Kindelement hasLayout auf true gesetzt ist:

hasLayout beeinflusst die klickbare/überfahrbare Fläche eines Block-Level-Ankers. Wenn hasLayout = false gesetzt ist, so reagiert normalerweise nur der Textbereich. Mit hasLayout = true ist die gesamte Box ansprechbar. Das Gleiche gilt für jedes Blockelement, dem ein onclick/onmouseover-Ereignis zugeordnet ist.

Seiteninterne Tastatur-Navigation: eine Odyssee

Wenn man sich mit dem Tabulator durch eine Seite bewegt und einen seiteninternen Link benutzt, so wird der nächste Tabulatorschritt nicht bei dem nachfolgenden Anker fortgesetzt:

Der Tabulator wird den Besucher zum ersten Ziel des nächsten Layout-Vorfahren führen – und oft in die Irre führen (sofern dieser Layout-Vorfahre aus einem table, div, span oder bestimmten anderen Elementen besteht).

Schrumpfendes Einschließen (Shrink-wrapping)

Durch einige Eigenschaften, die auf Elemente mit width: auto angewendet werden, wird die Breite mit einem »Schrumpf-Algorithmus« berechnet. Beispiele für diese Eigenschaften sind: float: left|right, position: absolute|fixed, display: table|table-cell|inline-block|inline-table.

Das funktioniert auch im IE/Win, selbsverständlich eingeschränkt auf die unterstützten Eigenschaften. Doch wenn ein Element, das schrumpfen sollte, ein Block-Element mit »Layout« enthält, so dehnt sich in den meisten Fällen dieses Kindelement unabhängig von seinem Inhalt auf die volle verfügbare Breite aus und verhindert so den Schrumpfeffekt des Elternelements.

Beispiel:
Bei einer vertikalen Navigation mit Float scheitert das schrumpfende Einschließen, weil für die Links a {display: block; zoom: 1;} nötig war, um den ungewollten zusätzlichen Leerraum (whitespace bug) der Liste zu beseitigen und den klickbaren Bereich auszudehnen.

Die Schrumpfwirkung bleibt nur dann erhalten, wenn das Layout-Kind eine Breite zugewiesen bekommt, oder wenn es selbst eine Schrumpf-Eigenschaft wie float hat.

Abschneiden außerhalb der Kante

Im Allgemeinen ist häufig »hasLayout« zur Vermeidung von Darstellungsproblemen nötig, wenn eine Box komplexe Strukturen enthält – wie Inhalte, die aus ihr herausragen. Diese Quasi-Notwendigkeit führt zu einem Dilemma an den Rändern, da eine Box, die »Layout« hat, zu einer Art selbstbegrenzten Box wird.

Eingebettete Inhaltsboxen, die nach außerhalb des Elements verschoben werden (zum Beispiel indem man negative Margins einsetzt), werden abgeschnitten.

Der abgeschnittene Teil kann zurückgeholt werden, indem man dieser Inhaltsbox »Layout« gibt; für IE 6 ist zusätzlich position: relative nötig. Das Verhalten im IE 7 scheint ein wenig verbessert dahingehend, dass position: relative nicht mehr nötig ist.

Stapelung, Schichtung und »Layout«

Es scheint im IE/Win zwei Stapel-/Schicht-Reihenfolgen zu geben:

Obwohl unvereinbar, sind beide Stapelmodelle im IE enthalten. Als Faustregel: versäumen Sie es bei der Fehlersuche nicht, beide Verdächtige zu überprüfen. Wir sehen regelmäßig damit zusammenhängende Probleme in Ausklapp- oder ähnlich komplexen Menüs, wo Stapelung, Positionierung und Float zu mannigfachen Katastrophen führen können. Eine Lösung kann mit z-index versehenes, positioniertes »Layout« sein, doch es variiert – also seien Sie gewarnt.

Das Debakel mit editierbarem Inhalt

Das Attribut contenteditable=true bei einem HTML-Tag wie <body contenteditable=true> erlaubt es, das Element und seine Layout-Nachfahren direkt zu Editieren, zu Verschieben und die Größe zu ändern. Jetzt versuchen Sie das bei Floats oder Li-Elementen mit »Layout« in einer geordneten Liste.

Um Elemente zu manipulieren (sie zu editieren), führen »contenteditable« und »hasLayout« eine separate Stapelreihenfolge für diejenigen Elemente ein, die true für hasLayout zurückgeben.

Die Editing Platform (das Dokument wurde aus dem MSDN entfernt2) erbt das »Layout«-Konzept; alles deutet darauf hin, dass contenteditable die Ursache für das Misskonzept des »Layout« ist (mit der Folge, dass Anwendungen, die auf irgendeine Weise die IE-Editing-Engine integrieren, eine Rückwärtskompatibilität zu diesem Layout-Konzept erzwingen).

Ähnlichkeiten mit der CSS-Spezifikation

Scheitern Ihre für MSIE gestalteten Seiten in anderen Browsern? So muss es nicht kommen, wissen Sie! Alle guten Browser können gut mit MSIE-Designs umgehen, wenn Sie sie nett fragen – und ihnen ein wenig valides CSS anbieten.

Wenn wir die leichten Ähnlichkeiten ausnutzen, die zwischen hasLayout und dem Schaffen eines »neuen Block-Formatierungskontextes« bestehen, so haben wir einige Möglichkeiten, die Auswirkungen von hasLayout auf das »Einschließen von Floats« und auf das Verhalten von »Elementen nach Floats« in standardkonformen Browsern zu reproduzieren.

Quirks-Modus

Bitte halten Sie sich an unser Kapitel zum Quirks-Modus für Informationen zu diesem Darstellungsmodus.

Layout — eine Schlussfolgerung

Das »Layout«-Konzept als Ganzes passt nicht zusammen mit einer Zahl von grundlegenden CSS-Konzepten des visuellen Formatierungsmodells, nämlich: Einschließen, der Fluss, Float, Positionierung und Stapelung.

Das führt zu IE/Win-spezifischen Verletzungen der CSS-Spezifikation in Abhängigkeit davon, ob Elemente einer Seite »Layout« haben oder nicht.

hasLayout — Teil einer anderen Engine?

Das Objektmodell im Explorer scheint eine Kreuzung zu sein zwischen einem Dokumentmodell und ihrem traditionellen Anwendungsmodell. Ich erwähne das, weil es wichtig ist, wenn man verstehen will, wie der Explorer Seiten darstellt. Der Schalter, der von einem Dokumentmodell zu einem Anwendungsmodell wechselt, ist das Hinzufügen von »Layout« zu einem Element.

(Dean Edwards)

Manchmal ist es unmöglich, eine Interpretation für ein Verhalten zu geben: Es ist einfach, als würde – in Abhängigkeit vom hasLayout-Status – eine von zwei unterschiedlichen Rendering Engines verwendet, jede mit ihren eigenen Ungereimtheiten und Fehlern.

Die Absurdität von Fehlern

Software-Fehler sind ein Ergebnis menschlicher Fehler und des Mangels an Vollständigkeit und Logik während des Entwicklungsprozesses. Es ist eine grundsätzliche menschliche Unzulänglichkeit, gegen die erst noch ein wirksames Heilmittel gefunden werden muss.
Alle Versuche, fehlerbehaftete Software zu korrigieren, ohne sie von Grund auf neu zu entwickeln, werden unvermeidlich dazu führen, dass noch mehr und noch komplexere Fehler ihren Weg in die Software finden – wegen der immer gleichen menschlichen Unzulänglichkeiten.
Jede Software, die auf anderer Software aufbaut – Betriebssysteme selbstverständlich eingeschlossen – wird auch auf deren Fehlern aufbauen. Daher erhalten wir eine Kaskade von Fehlern von jedem beteiligten Software-Teilchen, was schon den Gedanken an fehlerlose Software völlig absurd erscheinen lässt.

(Molly ‚the cat‛)

Dieser Artikel wurde am 30. Juni 2005 verfasst und zuletzt am 9. Mai 2007 geändert.

Bearbeiter:
Holly Bergevin
Ingo Chao
Bruno Fassino
John Gallant
Georg Sørtun
Philippe Wittenbergh
Besonderer Dank für ihre Unterstützung an:
Dean Edwards, Molly ‚the cat, and David Laakso.
Übersetzungen:
Brasilianisches Portugiesisch von Mauricio Samy Silva
Chinesisch von old9
Deutsch von Corina Rudel
Italienisch von Gabriele Romanato
In Vorbereitung: Hebräisch, Spanisch, Japanisch und Bulgarisch.
Übersetzungen sind willkommen, bitte treten Sie mit uns in Verbindung.
Diskutieren Sie diesen Artikel:
dean.edwards.name/weblog/
Kontaktieren Sie uns:
Anmerkung zum Copyright:
Dieser Artikel wird unter einer Creative Commons license veröffentlicht.

Inhaltsverzeichnis

  1. Einführung
  2. hasLayout — Eine Definition
  3. Nomenklatur
  4. Womit wir es zu tun haben
  5. Woher »Layout« kommt
  6. Elemente, die von vornherein »Layout« haben
  7. Eigenschaften
  8. Anmerkungen zu Elementen auf Inline-Level
  9. hasLayout zurücksetzen
  10. Die Skript-Eigenschaft hasLayout
  11. CSS-Hacks
  12. Der Umgang mit Hacks
  13. Eine kurze Anmerkung zum IE Mac.
  14. Die MSDN-Dokumentation
  15. Interpretation
  16. Eine Übersicht der Auswirkungen
  17. Clear bei Float und Mitwachsen
  18. Elemente nach Floats
  19. Listen
  20. Tabellen
  21. Relativ positionierte Elemente
  22. Absolut positionierte Elemente: umschließender Block, welcher umschließende Block?
  23. Filter
  24. Neuanordnung bereits dargestellter Elemente
  25. Ursprung des Hintergrunds
  26. Zusammenfallende Ränder (Collapsing Margins)
  27. Block–level Links
  28. Seiteninterne Tastatur-Navigation: eine Odyssee
  29. Schrumpfendes Einschließen (Shrink-wrapping)
  30. Abschneiden außerhalb der Kante
  31. Stapelung, Schichtung und »Layout«
  32. Das Debakel mit editierbarem Inhalt
  33. Ähnlichkeiten mit der CSS-Spezifikation
  34. Quirks-Modus
  35. Layout — eine Schlussfolgerung
  36. hasLayout — Teil einer anderen Engine?
  37. Die Absurdität von Fehlern

Permanente Adresse des Original-Artikels: http://www.satzansatz.de/cssd/onhavinglayout.html

  1. Das Originaldokument wurde im MSDN modifiziert. Wir beziehen uns auf eine Version, die im Internetarchiv einsehbar ist (Kontrolle über die Darstellung mit Maßangaben und Positionsangaben (Controlling Presentation with Measurement and Location Properties)).
  2. Das Originaldokument wurde aus dem MSDN entfernt und steht im Internetarchiv zur Verfügung (Die MSHTML Editierplattform im Internet Explorer 5.5 (The MSHTML Editing Platform in Internet Explorer 5.5)).

Deutsche Übersetzung des Artikels »On having layout« (englisch).

Vielen Dank an Ingo Chao für die freundliche Unterstützung!

Corina Rudel