Können Sie dieses HTML-Layout ohne Verwendung von Tabellen erstellen?

102

Ok, ich hatte vor ein oder zwei Wochen ein einfaches Layoutproblem. Abschnitte einer Seite benötigten nämlich eine Überschrift:

+---------------------------------------------------------+
| Title                                            Button |
+---------------------------------------------------------+

Ziemlich einfaches Zeug. Der Hass auf Tabellen scheint in der Web-Welt Einzug gehalten zu haben, woran ich erinnert wurde, als ich fragte, warum anstelle von Tabellen Tags für Definitionslisten (DL, DD, DT) für HTML-Formulare verwendet werden sollen. Nun wurde das allgemeine Thema Tabellen gegen Divs / CSS bereits erörtert, zum Beispiel:

Dies ist also keine allgemeine Diskussion über CSS im Vergleich zu Tabellen für das Layout. Dies ist einfach die Lösung für ein Problem. Ich habe verschiedene Lösungen für das oben Gesagte mit CSS ausprobiert, darunter:

  • Schweben Sie nach rechts für die Schaltfläche oder ein Div, das die Schaltfläche enthält.
  • Position relativ für die Schaltfläche; und
  • Position relativ + absolut.

Keine dieser Lösungen war aus verschiedenen Gründen zufriedenstellend. Zum Beispiel führte die relative Positionierung zu einem Z-Index-Problem, bei dem mein Dropdown-Menü unter dem Inhalt angezeigt wurde.

Also ging ich zurück zu:

<style type="text/css">
.group-header { background-color: yellow; width: 100%; }
.group-header td { padding: 8px; }
.group-title { text-align: left; font-weight: bold; }
.group-buttons { text-align: right; }
</style>
<table class="group-header">
<tr>
  <td class="group-title">Title</td>
  <td class="group-buttons"><input type="button" name="Button"></td>
</tr>
</table>

Und es funktioniert perfekt. Es ist einfach, so abwärtskompatibel wie es nur geht (das wird wahrscheinlich sogar unter IE5 funktionieren) und es funktioniert einfach. Kein Herumspielen mit Positionieren oder Schweben.

Kann jemand das Äquivalent ohne Tabellen tun?

Die Anforderungen sind:

  • Abwärtskompatibel: zu FF2 und IE6;
  • Ziemlich konsistent: über verschiedene Browser hinweg;
  • Vertikal zentriert: Die Schaltfläche und der Titel sind unterschiedlich hoch. und
  • Flexibel: Ermöglichen eine einigermaßen präzise Kontrolle über Positionierung (Polsterung und / oder Rand) und Styling.

Nebenbei bemerkt bin ich heute auf einige interessante Artikel gestoßen:

EDIT: Lassen Sie mich auf das Float-Problem näher eingehen. Diese Art von Arbeiten:

<html>
  <head>
    <title>Layout</title>
    <style type="text/css">
      .group-header, .group-content { width: 500px; margin: 0 auto; }
      .group-header { border: 1px solid red; background: yellow; overflow: hidden; }
      .group-content { border: 1px solid black; background: #DDD; }
      .group-title { float: left; padding: 8px; }
      .group-buttons { float: right; padding: 8px; }
    </style>
  </head>
  <body>
    <div class="group-header">
      <div class="group-title">This is my title</div>
      <div class="group-buttons"><input type="button" value="Collapse"></div>
    </div>
    <div class="group-content">
      <p>And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.</p>
      <p>So can anyone do the equivalent without tables that is backwards compatible to at least FF2 and IE6?</p>
      <p>On a side note, I came across a couple of interesting articles today:</p>
    </div>
  </body>
</html>

Vielen Dank an Ant P für den overflow: hiddenTeil (verstehe immer noch nicht warum). Hier kommt das Problem ins Spiel. Angenommen, Titel und Schaltfläche sollen vertikal zentriert sein. Dies ist problematisch, da die Elemente unterschiedlich hoch sind. Vergleichen Sie dies mit:

<html>
  <head>
    <title>Layout</title>
    <style type="text/css">
      .group-header, .group-content { width: 500px; margin: 0 auto; }
      .group-header { border: 1px solid red; background: yellow; overflow: hidden; }
      .group-content { border: 1px solid black; background: #DDD; }
      .group-header td { vertical-align: middle; }
      .group-title { padding: 8px; }
      .group-buttons { text-align: right; }
    </style>
  </head>
  <body>
    <table class="group-header">
    <tr>
      <td class="group-title">This is my title</td>
      <td class="group-buttons"><input type="button" value="Collapse"></td>
    </tr>
    </table>
    <div class="group-content">
      <p>And it works perfectly. It's simple, as backward compatibile as it gets (that'll work probably even on IE5) and it just works. No messing about with positioning or floats.</p>
      <p>So can anyone do the equivalent without tables that is backwards compatible to at least FF2 and IE6?</p>
      <p>On a side note, I came across a couple of interesting articles today:</p>
    </div>
  </body>
</html>

das funktioniert perfekt.

Cletus
quelle
11
Ok, das macht Sinn. "Welche Farbe soll ich für vim verwenden?" wird positiv bewertet, mein spezifisches CSS-Layout-Problem wird abgelehnt.
Cletus
Sie können in jedem Fall ohne Tabelle tun, was Sie wollen. Auch warum zum Teufel hat @SamB diese 2 Jahre alte Frage gestoßen? DOH +
dynamisch
3
@ yes123: Nun, die Syntaxhervorhebung war falsch ...
SamB

Antworten:

50

Es ist nichts Falsches daran, die Tools zu verwenden, die Ihnen zur Verfügung stehen, um die Arbeit schnell und korrekt zu erledigen.

In diesem Fall funktionierte ein Tisch perfekt.

Ich persönlich hätte dafür einen Tisch benutzt.

Ich denke, verschachtelte Tabellen sollten vermieden werden, Dinge können chaotisch werden.

Gregor Brandt
quelle
21
Außer wenn Sie eine Tabelle für das Präsentationslayout anstelle von Tabellendaten verwenden, nur weil es auf den ersten Blick einfacher ist, blass zu werden. In diesem Fall befinden Sie sich auf einem dunklen und gefährlichen Pfad.
Ein Wachsmalstift
9
In bestimmten Fällen verwendet sogar Amazon Tabellen. Und stackoverflow.com auch. Ich bin alles für CSS-Lösungen, wenn sie tatsächlich gut funktionieren.
Nosredna
11
Weder Amazon noch Stackoverflow sind die Höhepunkte des Webdesigns.
Bobby Jack
31
Sie mögen es nicht sein, aber sie arbeiten an Lösungen, die Zehntausende von Benutzern bedienen.
17 von 26
22
Dieses Anti-Tisch-Mem ist einfach nur alt und dumm. Der einzige zweidimensionale Layout-Manager für flexibles, auf Einschränkungen basierendes Laout ist die Tabelle. und ob es nur eine komplizierte (mit unzähligen col / rowspans) oder verschachtelte ist, macht wenig Unterschied. Aber Realität und Fakten sind anscheinend nicht immer gut genug Waffen gegen Eifer.
StaxMan
28

Schweben Sie einfach nach links und rechts und stellen Sie beide ein, und Sie sind fertig. Keine Notwendigkeit für Tabellen.

Edit: Ich weiß, dass ich dafür viele positive Stimmen bekommen habe und ich glaubte, dass ich Recht hatte. Es gibt jedoch Fälle, in denen Sie lediglich Tabellen benötigen. Sie können versuchen, alles mit CSS zu tun, und es wird in modernen Browsern funktionieren, aber wenn Sie ältere unterstützen möchten ... Um mich nicht zu wiederholen, hier der zugehörige Stapelüberlauf-Thread und Rant in meinem Blog .

Edit2: Da ältere Browser nicht mehr so ​​interessant sind, verwende ich Twitter Bootstrap für neue Projekte. Es eignet sich hervorragend für die meisten Layoutanforderungen und verwendet CSS.

Milan Babuškov
quelle
2
Behandelt die vertikale Zentrierung nicht, also -1.
SamB
1
Ich hatte ein ähnliches Problem, bei dem ich links ein Logo und rechts einige Textmenüs hatte. Die Menüs mussten an der Grundlinie des Logos ausgerichtet werden. Verwenden von float: rechts für die Menüs hat nicht funktioniert. Es schickte sie in die obere rechte Ecke und sie waren nicht mehr vertikal an der Grundlinie des Logos ausgerichtet.
Jean-François Beauchamp
1
Ich denke, Sie können die vertikale Zentrierung lösen, indem Sie die Zeilenhöhe des Titels so einstellen, dass sie der Höhe der Schaltfläche entspricht.
igors
1
@igors, +1, du hast recht.
Beachten Sie,
17

Dies ist eine Art Trickfrage: Es sieht furchtbar einfach aus, bis Sie dazu kommen

Angenommen, Titel und Schaltfläche sollen vertikal zentriert sein.

Ich möchte für die Aufzeichnung festhalten, dass die vertikale Zentrierung in CSS schwierig ist. Wenn Leute posten und es auf SO endlos erscheint, "kannst du X in CSS machen", lautet die Antwort fast immer "Ja" und ihr Schimpfen scheint ungerechtfertigt. In diesem Fall ist diese eine Sache schwierig.

Jemand sollte einfach die gesamte Frage bis auf "Ist die vertikale Zentrierung in CSS problematisch?" Bearbeiten.

AmbroseChapel
quelle
11
Das ist ein Problem mit dem Argument "Tabellenhasser": CSS kann alles, was Tabellen können ... mit Ausnahme einiger ziemlich einfacher, häufiger und vernünftiger Fälle (wie vertikaler Zentrierung). CSS scheint nur ein schlechtes Wahlversprechen zu sein.
Cletus
4
Mein Punkt war, dass vertikale Zentrierung nur das EINZIGE ist, was wirklich schwierig ist.
AmbroseChapel
3
CSS soll keine Tabellen ersetzen. Es soll Ihnen nur ermöglichen, die meisten gängigen Layoutprobleme ohne Tabellen zu lösen. Wenn ein Tisch funktioniert, verwenden Sie einen Tisch, so als würden Sie anstelle eines Vorschlaghammers einen Stift zum Zeichnen verwenden.
Aaron Digulla
16

Float-Titel links, Float-Button rechts und (hier ist der Teil, den ich bis vor kurzem nicht kannte) - machen Sie den Container aus beiden {overflow:hidden}.

Das sollte das Z-Index-Problem sowieso vermeiden. Wenn es nicht funktioniert und Sie die IE5-Unterstützung wirklich benötigen, verwenden Sie die Tabelle.


quelle
+1 Whoa, was ist mit dem Überlauf versteckt? Es macht einen Unterschied. Keine Ahnung warum.
Cletus
Um ehrlich zu sein, verstehe ich es auch nicht und konnte es in der Spezifikation nicht erwähnen. Jemand sagte mir, dass dies der "richtige" Weg sei, nachdem ich eine andere Frage beantwortet hatte, die vorschlug, dass sie ein gelöschtes Element verwenden, um dies zu tun. Scheint mir eine gute Idee zu sein.
Die schwebenden Elemente müssen noch gelöscht werden, damit der darauf folgende Inhalt ordnungsgemäß fließt. Überlauf versteckt; Adressiert nur die Höhe des Containers.
Zack The Human
2
"overflow: hidden" ist ein Hack, um BEIDE Höhen "Expansion" und Clearing zu erreichen. Die folgenden Elemente löschen dieses Feld (zumindest in Browsern, die diesen Teil der Spezifikation korrekt implementieren).
Bobby Jack
1
-1 für nicht vertikale Zentrierung, aber +2 für overflow:hidden.
SamB
7

In reinem CSS wird eine funktionierende Antwort eines Tages darin bestehen, nur zu verwenden "display:table-cell". Leider funktioniert das in aktuellen Browsern der Klasse A nicht. Sie können also genauso gut eine Tabelle verwenden, wenn Sie trotzdem nur das gleiche Ergebnis erzielen möchten. Zumindest werden Sie sicher sein, dass es weit genug in der Vergangenheit funktioniert.

Ehrlich gesagt, benutzen Sie einfach einen Tisch, wenn es einfacher ist. Es wird nicht weh tun.

Wenn Ihnen die Semantik und Zugänglichkeit des Tabellenelements wirklich wichtig ist, gibt es einen Arbeitsentwurf, mit dem Sie Ihre Tabelle nicht semantisch machen können:

http://www.w3.org/TR/wai-aria/#presentation

Ich denke, dies erfordert eine spezielle DTD über XHTML 1.1 hinaus, die nur die gesamte Debatte text/htmlgegen die Aufregung anregen würde. application/xmlGehen wir also nicht dorthin.

Also weiter zu Ihrem ungelösten CSS-Problem ...

Um zwei Elemente vertikal in ihrer Mitte auszurichten: Dies kann auf verschiedene Arten geschehen, mit etwas stumpfem CSS-Hackery.

Wenn Sie die folgenden Einschränkungen erfüllen können, gibt es einen relativ einfachen Weg:

  • Die Höhe der beiden Elemente ist festgelegt.
  • Die Höhe des Containers ist festgelegt.
  • Die Elemente sind schmal genug, um sich nicht zu überlappen (oder können auf eine feste Breite eingestellt werden).

Dann können Sie die absolute Positionierung mit negativen Rändern verwenden:

.group-header { height: 50px; position: relative; }
.group-title, .group-buttons { position: absolute; top: 50%; }
# Assuming the height of .group-title is a known 34px
.group-title { left: 0; margin-top: -17px; }
# Assuming the height of .group-buttons is a known 38px
.group-buttons { right: 0; margin-top: -19px; }

Dies ist jedoch in den meisten Situationen sinnlos. Wenn Sie die Höhe der Elemente bereits kennen, können Sie einfach Floats verwenden und genügend Rand hinzufügen, um sie nach Bedarf zu positionieren.

Hier ist eine andere Methode, die die Textgrundlinie verwendet, um die beiden Spalten als Inline-Blöcke vertikal auszurichten. Der Nachteil hierbei ist, dass Sie feste Breiten für die Spalten festlegen müssen, um die Breite vom linken Rand auszufüllen. Da wir die Elemente an eine Textgrundlinie gebunden halten müssen, können wir nicht einfach float: right für die zweite Spalte verwenden. (Stattdessen müssen wir die erste Spalte breit genug machen, um sie zu verschieben.)

<html>
  <head>
    <title>Layout</title>
    <style type="text/css">
      .group-header, .group-content { width: 500px; margin: 0 auto; }
      .group-header { border: 1px solid red; background: yellow; }
      .valign { display: inline-block; vertical-align: middle; }
      .group-content { border: 1px solid black; background: #DDD; }
      .group-title { padding: 8px; width: 384px; }
      .group-buttons { padding: 8px; width: 84px; text-align: right; }
    </style>
    <!--[if lt IE 8]>
    <style type="text/css">
      .valign { display: inline; margin-top: -2px; padding-top: 1px; }
    </style>
    <![endif]-->
  </head>
  <body>
    <div class="group-header">
      <div class="valign">
        <div class="group-title">This is my title.</div>
      </div><!-- avoid whitespace between these! --><div class="valign">
        <div class="group-buttons"><input type="button" value="Collapse"></div>
      </div>
    </div>
    <div class="group-content">
      <p>And it works perfectly, but mind the hacks.</p>
    </div>
  </body>
</html>

Der HTML- Code : Wir fügen jeder Spalte .valign-Wrapper hinzu. (Geben Sie ihnen einen "semantischeren" Namen, wenn Sie dadurch glücklicher werden.) Diese müssen ohne Leerzeichen dazwischen aufbewahrt werden, da sie sonst durch Textbereiche auseinandergedrückt werden. (Ich weiß, dass es scheiße ist, aber das ist es, was man bekommt, wenn man mit dem Markup "rein" ist und es von der Präsentationsschicht trennt ... Ha!)

Das CSS: Wir verwenden vertical-align:middle, um die Blöcke an der Textgrundlinie des Gruppenkopfelementes auszurichten. Die unterschiedlichen Höhen jedes Blocks bleiben vertikal zentriert und drücken die Höhe ihres Behälters heraus. Die Breiten der Elemente müssen entsprechend der Breite berechnet werden. Hier sind sie 400 und 100, abzüglich ihrer horizontalen Polsterung.

Der IE behebt: Internet Explorer zeigt nur Inline-Block für nativ-Inline-Elemente an (z. B. span, nicht div). Wenn wir dem div hasLayout geben und es dann inline anzeigen, verhält es sich wie ein Inline-Block. Die Randanpassung dient dazu, eine Lücke von 1 Pixel oben zu beheben (versuchen Sie, dem Gruppentitel Hintergrundfarben hinzuzufügen, um sie anzuzeigen).

Andrew Vit
quelle
1
Hmm die Anzeige: table-X-Tags scheinen den Zweck zu haben, das Layout mit Tabellen zu erstellen, nur ohne Tabellen-Tags?
Danubian Sailor
3

Ich würde empfehlen, in diesem Fall keine Tabelle zu verwenden, da dies keine tabellarischen Daten sind. Es ist rein präsentativ, wenn sich der Knopf ganz rechts befindet. Dies würde ich tun, um Ihre Tabellenstruktur zu duplizieren (wechseln Sie zu einem anderen H #, je nachdem, wo Sie sich in der Hierarchie Ihrer Site befinden):

<style>
  .group-header { background: yellow; zoom: 1; padding: 8px; }
  .group-header:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
  /* set width appropriately to allow room for button */
  .group-header h3 { float: left; width: 300px; }
  /* set line-height or margins to align with h3 baseline or middle */
  .group-header input { float: right; }
</style>

<div class="group-header">
  <h3>This is my title</h3>
  <input type="button" value="Collapse"/>
</div>

Wenn Sie eine echte vertikale Ausrichtung in der Mitte wünschen (dh wenn der Text umbrochen wird, ist die Schaltfläche in Bezug auf beide Textzeilen immer noch mittig ausgerichtet), müssen Sie entweder eine Tabelle erstellen oder etwas mit position: absoluteund Rändern bearbeiten . Sie können position: relativeIhrem Dropdown-Menü (oder wahrscheinlich dem übergeordneten Menü) hinzufügen , um es in die gleiche Reihenfolge wie die Schaltflächen zu bringen, sodass Sie es mit dem Z-Index darüber streichen können, wenn es dazu kommt.

Beachten Sie, dass Sie width: 100%das div nicht benötigen, da es sich um ein Element auf Blockebene handelt und zoom: 1das div sich so verhält, als hätte es einen Clearfix im IE (andere Browser übernehmen den eigentlichen Clearfix). Sie benötigen auch nicht alle diese Fremdklassen, wenn Sie etwas spezifischer auf Dinge abzielen, obwohl Sie möglicherweise ein Wrapper-Div oder eine Spanne auf der Schaltfläche benötigen, um die Positionierung zu vereinfachen.

Ein Wachsmalstift
quelle
Ihre Lösung funktioniert jedoch nicht mit IE6, da: nach der Pseudoklasse.
Sebastian Hoitz
1
Es funktioniert in IE 6 dank des zoom: 1in .group-header, das hasLayout auslöst und bewirkt, dass sich IE 6 genauso verhält, als ob das Element: after aktiv wäre.
Ein Wachsmalstift
2

Machen Sie einen Double Float in einem Div und verwenden Sie den Clearfix. http://www.webtoolkit.info/css-clearfix.html Haben Sie Einschränkungen hinsichtlich Polsterung / Rand?

<div class="clearfix">
   <div style="float:left">Title</div>
   <input type="button" value="Button" style="float:right" />
</div>
Bendewey
quelle
Ich habe eine vertikale Zentrierungsanforderung (und ein wenig zusätzliche Polsterung). Ich glaube, ich habe das klargestellt, nachdem du es gepostet hast.
Cletus
2
<div class="group-header">
    <input type="button" name="Button" value="Button" style="float:right" />
    <span>Title</span>
</div>
Omer Bokhari
quelle
1

Ich habe mich für Flexbox entschieden, weil es die Dinge so viel einfacher gemacht hat.

Grundsätzlich müssen Sie zu den Eltern der Kinder gehen, die Sie ausrichten und hinzufügen möchten display:box(natürlich mit Präfix). Verwenden Sie den Rechtfertigungsinhalt, damit sie in den Seiten sitzen . Der Abstand dazwischen ist das Richtige, wenn Sie Elemente haben, die wie in diesem Fall am Ende ausgerichtet werden müssen (siehe Link) ...

Dann das Problem der vertikalen Ausrichtung. Da ich das übergeordnete Element der beiden Elemente erstellt habe, möchten Sie eine Flexbox ausrichten. Es ist jetzt einfach zu bedienen align-items: center.

Dann habe ich die gewünschten Stile hinzugefügt, den Float aus dem Titel und der Schaltfläche in der Kopfzeile entfernt und eine Auffüllung hinzugefügt:

.group-header, .group-content {
    width: 500px;
    margin: 0 auto;
}
.group-header{
    border: 1px solid red;
    background: yellow;
    overflow: hidden;
    display: -webkit-box;
    display: -moz-box;
    display: box;
    display: -webkit-flex;
    display: -moz-flex;
    display: -ms-flexbox;
    display: flex;
    -webkit-justify-content: space-between;
    -moz-justify-content: space-between;
    -ms-justify-content: space-between;
    -o-justify-content: space-between;
    justify-content: space-between;
    webkit-align-items: center;
    -moz-align-items: center;
    -ms-align-items: center;
    -o-align-items: center;
    align-items: center;
    padding: 8px 0;
}
.group-content{
    border: 1px solid black;
    background: #DDD;
}
.group-title {
    padding-left: 8px;
}
.group-buttons {
    padding-right: 8px
}

Siehe Demo

user3522940
quelle
1

Ich bin damit einverstanden, dass man wirklich nur Tabellen für tabellarische Daten verwenden sollte, aus dem einfachen Grund, dass Tabellen erst angezeigt werden, wenn sie vollständig geladen sind (egal wie schnell das ist; es ist langsamer als die CSS-Methode). Ich bin jedoch der Meinung, dass dies die einfachste und eleganteste Lösung ist:

<html>
    <head>
        <title>stack header</title>
        <style type="text/css">
            #stackheader {
                background-color: #666;
                color: #FFF;
                width: 410px;
                height: 50px;
            }
            #title {
                color: #FFF;
                float: left;
                padding: 15px 0 0 15px;
            }
            #button {
                color: #FFF;
                float: right;
                padding: 15px 15px 0 0;
            }
        </style>
    </head>

    <body>
        <div id="stackheader">
        <div id="title">Title</div>
        <div id="button">Button</div>
        </div>
    </body>
</html>

Die Tastenfunktion und jedes zusätzliche Detail können aus dieser Grundform heraus gestaltet werden. Entschuldigung für die schlechten Tags.

Galen777
quelle