Puoi fare questo layout HTML senza usare le tabelle?


102

Ok, ho avuto un semplice problema di layout una o due settimane fa. Vale a dire le sezioni di una pagina richiedevano un'intestazione:

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

Cose abbastanza semplici. Il fatto è che l'odio per le tabelle sembra aver preso il sopravvento nel mondo Web, cosa che mi è stata ricordata quando ho chiesto Perché usare i tag degli elenchi di definizioni (DL, DD, DT) per i moduli HTML invece delle tabelle? Ora l'argomento generale di tabelle vs divs / CSS è stato discusso in precedenza, ad esempio:

Quindi questa non vuole essere una discussione generale su CSS e tabelle per il layout. Questa è semplicemente la soluzione a un problema. Ho provato varie soluzioni a quanto sopra utilizzando CSS, tra cui:

  • Fluttua a destra per il pulsante o un div contenente il pulsante;
  • Posizione relativa per il pulsante; e
  • Posizione relativa + assoluta.

Nessuna di queste soluzioni è stata soddisfacente per motivi diversi. Ad esempio, il posizionamento relativo ha provocato un problema di z-index in cui il mio menu a discesa appariva sotto il contenuto.

Quindi ho finito per tornare a:

<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>

E funziona perfettamente. È semplice, compatibile con le versioni precedenti (probabilmente funzionerà anche su IE5) e funziona. Nessun problema con il posizionamento o i galleggianti.

Quindi chiunque può fare l'equivalente senza tavoli?

I requisiti sono:

  • Retrocompatibile: per FF2 e IE6;
  • Ragionevolmente coerente: attraverso diversi browser;
  • Centrato verticalmente: il pulsante e il titolo hanno altezze diverse; e
  • Flessibile: consente un controllo ragionevolmente preciso sul posizionamento (imbottitura e / o margine) e sullo styling.

Come nota a margine, oggi mi sono imbattuto in un paio di articoli interessanti:

EDIT: Permettetemi di approfondire la questione del galleggiante. Questo tipo di lavori:

<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>

Grazie ad Ant P per la overflow: hiddenparte (ancora non capisco perché). Ecco dove entra in gioco il problema. Diciamo che voglio che il titolo e il pulsante siano centrati verticalmente. Questo è problematico perché gli elementi sono di diversa altezza. Confronta questo con:

<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>

che funziona perfettamente.


11
Ok, ha senso "Che colore devo usare per vim?" viene votato, il mio specifico problema di layout CSS viene svalutato.
cletus


puoi fare quello che vuoi senza tavolo in ogni caso. Inoltre, perché diavolo @SamB ha urtato questa domanda vecchia di 2 anni? DOH +
dinamico

3
@ yes123: beh, l'evidenziazione della sintassi era sbagliata ...
SamB

Risposte:


50

Non c'è niente di sbagliato nell'usare gli strumenti a tua disposizione per svolgere il lavoro in modo rapido e corretto.

In questo caso un tavolo ha funzionato perfettamente.

Personalmente avrei usato un tavolo per questo.

Penso che le tabelle nidificate dovrebbero essere evitate, le cose possono diventare disordinate.


21
Tranne quando stai usando una tabella per il layout di presentazione piuttosto che i dati tabulari solo perché all'inizio è più facile pallido, nel qual caso sei diretto verso un sentiero oscuro e pericoloso.
One Crayon

9
Anche Amazon utilizza le tabelle in alcuni casi. E anche stackoverflow.com. Sono tutto per le soluzioni CSS quando funzionano davvero bene.
Nosredna

11
Né amazon, ora stackoverflow sono i pinnacoli del web design.
Bobby Jack,

31
Potrebbero non esserlo, ma stanno funzionando soluzioni che servono decine di migliaia di utenti.
17 del 26

22
Questo meme anti-tavolo è semplicemente vecchio stupido. L'unico gestore di layout bidimensionale per layout flessibile basato su vincoli è table; e che sia solo uno complicato (con una miriade di colonne / righe) o annidati fa poca differenza. Ma la realtà ei fatti non sono sempre armi sufficienti contro il fanatismo, a quanto pare.
StaxMan

28

Basta fluttuare a sinistra ea destra e impostare per cancellarli entrambi e il gioco è fatto. Non c'è bisogno di tavoli.

Modifica: so di aver ricevuto molti voti positivi per questo, e credevo di aver ragione. Ma ci sono casi in cui devi semplicemente avere delle tabelle. Puoi provare a fare tutto con CSS e funzionerà nei browser moderni, ma se desideri supportare quelli più vecchi ... Per non ripetermi, qui il thread di overflow dello stack correlato e sfogo sul mio blog .

Edit2: Poiché i browser meno recenti non sono più così interessanti, sto usando il bootstrap di Twitter per i nuovi progetti. È ottimo per la maggior parte delle esigenze di layout e utilizza i CSS.


2
Non gestisce il centraggio verticale, quindi -1.
SamB

1
Ho avuto un problema simile in cui avevo un logo a sinistra e alcuni menu di testo a destra. I menu dovevano essere allineati sulla linea di base del logo. Utilizzando float: giusto per i menu non ha funzionato. Li ha inviati all'angolo in alto a destra e non erano più allineati verticalmente con la linea di base del logo.
Jean-François Beauchamp

1
Penso che tu possa risolvere il centraggio verticale impostando l'altezza della linea del titolo in modo che sia uguale all'altezza del pulsante.
igors

1
@igors, +1, hai ragione. Tieni conto che questa domanda è del 2009.;)
Milan Babuškov

17

Questa è una specie di domanda trabocchetto: sembra terribilmente semplice finché non ci arrivi

Diciamo che voglio che il titolo e il pulsante siano centrati verticalmente.

Voglio affermare per la cronaca che sì, il centraggio verticale è difficile nei CSS. Quando le persone postano, e sembra infinito su SO, "puoi fare X in CSS" la risposta è quasi sempre "sì" e le loro lamentele sembrano ingiustificate. In questo caso, sì, quella cosa in particolare è difficile.

Qualcuno dovrebbe modificare l'intera domanda in "il centraggio verticale è problematico nei CSS?".


11
Questo è un po 'il mio problema con l'argomento "table haters": i CSS possono fare tutto ciò che le tabelle possono fare ... tranne alcuni casi piuttosto semplici, comuni e ragionevoli (come il centraggio verticale). I CSS sembrano solo una promessa elettorale andata male.
cletus

4
Il punto era che il centraggio verticale è l'UNICA cosa veramente difficile.
AmbroseChapel,

3
CSS non è pensato per sostituire le tabelle; ha solo lo scopo di consentire di risolvere la maggior parte dei problemi di layout comuni senza tabelle. Se un tavolo funziona, usa un tavolo, proprio come useresti una penna per disegnare invece di una mazza.
Aaron Digulla

16

Fluttua il titolo a sinistra, il pulsante fluttua a destra e (ecco la parte che non conoscevo fino a poco tempo fa) - crea il contenitore di entrambi {overflow:hidden}.

Questo dovrebbe comunque evitare il problema dello z-index. Se non funziona e hai davvero bisogno del supporto IE5, vai avanti e usa la tabella.


+1 Whoa, cosa c'è con l'overflow nascosto? Fa la differenza. Non ho idea del perché però.
cletus

Ad essere onesti, nemmeno io lo capisco e non sono riuscito a trovarne alcuna menzione nelle specifiche. Qualcuno mi ha detto che è il modo "giusto", però, dopo che ho risposto a un'altra domanda suggerendo di usare un elemento cancellato per farlo. Mi sembra una buona idea.

Gli elementi flottati devono ancora essere cancellati affinché il contenuto che li segue fluisca correttamente. overflow: hidden; affronta solo l'altezza del contenitore.
Zack The Human,

2
"overflow: hidden" è un trucco per ottenere SIA 'espansione' di altezza e pulizia. I seguenti elementi cancelleranno quella casella (almeno nei browser che implementano quella parte della specifica correttamente).
Bobby Jack,

1
-1 per non gestire il centraggio verticale, ma +2 per overflow:hidden.
SamB

7

In puro CSS, una risposta funzionante un giorno sarà semplicemente usare "display:table-cell". Sfortunatamente questo non funziona con gli attuali browser di livello A, quindi per tutto ciò potresti anche usare una tabella se vuoi comunque ottenere lo stesso risultato. Almeno sarai sicuro che funzioni abbastanza lontano nel passato.

Onestamente, usa un tavolo se è più facile. Non farà male.

Se la semantica e l'accessibilità dell'elemento table sono davvero importanti per te, c'è una bozza di lavoro per rendere la tua tabella non semantica:

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

Penso che questo richieda un DTD speciale oltre XHTML 1.1, che susciterebbe solo l'intero dibattito text/htmlvs application/xml, quindi non andiamo lì.

Quindi, passiamo al tuo problema CSS irrisolto ...

Per allineare verticalmente due elementi al centro: può essere fatto in diversi modi, con qualche ottuso hacker CSS.

Se puoi rientrare nei seguenti vincoli, esiste un modo relativamente semplice:

  • L'altezza dei due elementi è fissa.
  • L'altezza del contenitore è fissa.
  • Gli elementi saranno abbastanza stretti da non sovrapporsi (o possono essere impostati su una larghezza fissa).

Quindi puoi utilizzare il posizionamento assoluto con margini negativi:

.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; }

Ma questo è inutile nella maggior parte delle situazioni ... Se conosci già l'altezza degli elementi, puoi semplicemente usare i float e aggiungere abbastanza margine per posizionarli come necessario.

Ecco un altro metodo che utilizza la linea di base del testo per allineare verticalmente le due colonne come blocchi in linea. Lo svantaggio qui è che è necessario impostare larghezze fisse per le colonne per riempire la larghezza dal bordo sinistro. Poiché abbiamo bisogno di mantenere gli elementi bloccati su una linea di base del testo, non possiamo semplicemente usare float: right per la seconda colonna. (Invece, dobbiamo rendere la prima colonna abbastanza larga da spingerla oltre.)

<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>

L'HTML: aggiungiamo wrapper .valign attorno a ogni colonna. (Dai loro un nome più "semantico" se ti rende più felice.) Questi devono essere tenuti senza spazi vuoti in mezzo, altrimenti gli spazi di testo li separeranno. (So ​​che fa schifo, ma è quello che ottieni per essere "puro" con il markup e separarlo dal livello di presentazione ... Ha!)

Il CSS: usiamo vertical-align:middleper allineare i blocchi alla linea di base del testo dell'elemento di intestazione del gruppo. Le diverse altezze di ogni blocco rimarranno centrate verticalmente e spingeranno fuori l'altezza del loro contenitore. Le larghezze degli elementi devono essere calcolate per adattarsi alla larghezza. Qui sono 400 e 100, meno il loro riempimento orizzontale.

Le correzioni di IE: Internet Explorer visualizza solo inline-block per elementi nativamente inline (ad esempio span, non div). Ma, se diamo al div hasLayout e poi lo visualizziamo inline, si comporterà proprio come inline-block. La regolazione del margine serve a correggere uno spazio di 1 pixel nella parte superiore (prova ad aggiungere i colori di sfondo al titolo .group per vedere).


1
Hmm il display: i tag table-X sembrano avere lo scopo di fare il layout usando le tabelle, solo senza usare i tag di tabella?
Danubian Sailor

3

Consiglierei di non utilizzare una tabella in questo caso, perché non si tratta di dati tabulari; è puramente presentativo avere il pulsante situato all'estrema destra. Questo è quello che farei per duplicare la struttura della tabella (cambia in un diverso H # per adattarlo a dove ti trovi nella gerarchia del tuo sito):

<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>

Se vuoi un allineamento verticale vero nel mezzo (cioè, se il testo avvolge il pulsante è ancora allineato al centro rispetto a entrambe le righe di testo), allora devi fare una tabella o lavorare qualcosa con position: absolutee margini. Puoi aggiungere position: relativeal tuo menu a discesa (o più probabilmente al suo genitore) per portarlo allo stesso livello di ordinamento dei pulsanti, permettendoti di spostarlo sopra di loro con z-index, se si tratta di quello.

Nota che non hai bisogno width: 100%del div perché è un elemento a livello di blocco e zoom: 1fa sì che il div si comporti come se avesse un clearfix in IE (altri browser raccolgono l'effettivo clearfix). Inoltre, non hai bisogno di tutte quelle classi estranee se stai prendendo di mira le cose in modo un po 'più specifico, anche se potresti aver bisogno di un div wrapper o di un intervallo sul pulsante per facilitare il posizionamento.


La tua soluzione non funziona su IE6 a causa della pseudo-classe: after.
Sebastian Hoitz,

1
Funziona in IE 6, grazie a zoom: 1in .group-header, che attiva hasLayout e fa sì che IE 6 si comporti come se avesse l'elemento: after attivo.
One Crayon

2

Fai un doppio float in un div e usa il clearfix. http://www.webtoolkit.info/css-clearfix.html Hai limitazioni di riempimento / margine?

<div class="clearfix">
   <div style="float:left">Title</div>
   <input type="button" value="Button" style="float:right" />
</div>

Ho un requisito di centraggio verticale (e un po 'di imbottitura extra). Penso di averlo chiarito dopo che hai postato però.
cletus

2
<div class="group-header">
    <input type="button" name="Button" value="Button" style="float:right" />
    <span>Title</span>
</div>

1

Ho scelto di utilizzare Flexbox, perché ha reso le cose molto più semplici.

Fondamentalmente devi andare dal genitore dei bambini che vuoi allineare e aggiungere display:box(con prefisso ovviamente). Per farli sedere ai lati, usa il contenuto giustificato . Lo spazio tra è la cosa giusta quando hai elementi che devono essere allineati alla fine, come in questo caso (vedi link) ...

Quindi il problema dell'allineamento verticale. Poiché ho creato il genitore dei due elementi, vuoi allineare un Flexbox. Ora è facile da usare align-items: center.

Quindi ho aggiunto gli stili che volevi prima, ho rimosso il float dal titolo e il pulsante nell'intestazione e ho aggiunto un riempimento:

.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
}

Vedi Demo


1

Sono d'accordo sul fatto che si dovrebbero davvero usare le tabelle solo per i dati tabulari, per il semplice motivo che le tabelle non vengono visualizzate fino al termine del caricamento (non importa quanto sia veloce; è più lento del metodo CSS). Tuttavia, sento che questa è la soluzione più semplice ed elegante:

<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>

La funzione del pulsante e qualsiasi dettaglio aggiuntivo possono essere stilizzati da questo modulo di base. Mi scuso per i tag difettosi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.