Bisakah Anda melakukan tata letak HTML ini tanpa menggunakan tabel?

102

Oke, saya mengalami masalah tata letak sederhana satu atau dua minggu yang lalu. Yaitu bagian dari halaman membutuhkan header:

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

Hal-hal yang cukup sederhana. Masalahnya adalah kebencian tabel tampaknya telah mengambil alih di dunia Web, yang saya ingat ketika saya bertanya Mengapa menggunakan tag daftar definisi (DL, DD, DT) untuk formulir HTML daripada tabel? Sekarang topik umum tabel vs divs / CSS telah dibahas sebelumnya, misalnya:

Jadi ini tidak dimaksudkan sebagai diskusi umum tentang CSS vs tabel untuk tata letak. Ini hanyalah solusi untuk satu masalah. Saya mencoba berbagai solusi di atas menggunakan CSS termasuk:

  • Mengambang tepat untuk tombol atau div yang berisi tombol;
  • Posisi relatif untuk tombol; dan
  • Posisi relatif + absolut.

Tak satu pun dari solusi ini memuaskan karena alasan yang berbeda. Misalnya pemosisian relatif menghasilkan masalah indeks-z di mana menu tarik-turun saya muncul di bawah konten.

Jadi saya akhirnya kembali ke:

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

Dan itu bekerja dengan sempurna. Ini sederhana, kompatibel dengan versi sebelumnya (yang mungkin akan bekerja bahkan pada IE5) dan berfungsi. Tidak mengotak-atik positioning atau float.

Jadi, adakah yang bisa melakukan hal yang setara tanpa tabel?

Persyaratannya adalah:

  • Kompatibel dengan versi sebelumnya : ke FF2 dan IE6;
  • Cukup konsisten: di berbagai browser;
  • Ditengah vertikal: tombol dan judul memiliki ketinggian yang berbeda; dan
  • Fleksibel: memungkinkan kontrol yang cukup tepat atas pemosisian (padding dan / atau margin) dan gaya.

Di samping catatan, saya menemukan beberapa artikel menarik hari ini:

EDIT: Izinkan saya menguraikan masalah float. Jenis pekerjaan ini:

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

Terima kasih kepada Ant P untuk overflow: hiddenbagiannya (masih belum mengerti mengapa). Di sinilah masalahnya masuk Misalnya saya ingin judul dan tombol berada di tengah secara vertikal. Ini bermasalah karena elemen memiliki ketinggian yang berbeda. Bandingkan ini dengan:

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

yang bekerja dengan sempurna.

cletus
sumber
11
Ok itu masuk akal "Warna apa yang harus saya gunakan untuk vim?" mendapat suara positif, masalah tata letak CSS spesifik saya diturunkan suara.
cletus
Anda dapat melakukan apapun yang Anda inginkan tanpa tabel dalam kasus apapun. Juga kenapa @SamB menemukan pertanyaan 2 tahun ini? DOH +
dinamis
3
@ yes123: baik, penyorotan sintaks salah ...
SamB

Jawaban:

50

Tidak ada salahnya menggunakan alat-alat yang tersedia bagi Anda untuk melakukan pekerjaan dengan cepat dan benar.

Dalam hal ini meja bekerja dengan sempurna.

Saya pribadi akan menggunakan tabel untuk ini.

Saya pikir tabel bersarang harus dihindari, hal-hal bisa menjadi berantakan.

Gregor Brandt
sumber
21
Kecuali jika Anda menggunakan tabel untuk tata letak presentasi daripada data tabel hanya karena lebih mudah pada pucat pertama, dalam hal ini Anda menuju ke jalur yang gelap dan berbahaya.
Satu Krayon
9
Bahkan Amazon menggunakan tabel dalam kasus tertentu. Dan stackoverflow.com juga melakukannya. Saya mendukung solusi css ketika mereka benar-benar bekerja dengan baik.
Nosredna
11
Bukan amazon, sekarang stackoverflow adalah puncak desain web.
Bobby Jack
31
Mungkin tidak, tetapi mereka berfungsi sebagai solusi yang melayani puluhan ribu pengguna.
17 dari 26
22
Meme anti-meja ini benar-benar bodoh. Satu-satunya manajer layout 2-dimensi untuk laout berbasis kendala yang fleksibel adalah tabel; dan apakah itu hanya satu yang rumit (dengan segudang col / rowpans), atau yang bertingkat membuat sedikit perbedaan. Tetapi kenyataan dan fakta tampaknya tidak selalu menjadi senjata yang cukup baik untuk melawan kefanatikan.
StaxMan
28

Cukup melayang ke kiri dan kanan dan atur untuk menghapus keduanya dan Anda selesai. Tidak perlu tabel.

Sunting: Saya tahu bahwa saya mendapat banyak suara positif untuk ini, dan saya yakin saya benar. Tetapi ada kasus di mana Anda hanya perlu memiliki tabel. Anda dapat mencoba melakukan semuanya dengan CSS dan itu akan berfungsi di browser modern, tetapi jika Anda ingin mendukung yang lebih tua ... Jangan terulang lagi, di sini utas stack overflow terkait dan kata - kata kasar di blog saya .

Sunting2: Karena browser lama tidak lagi menarik, saya menggunakan bootstrap Twitter untuk proyek baru. Ini bagus untuk sebagian besar kebutuhan tata letak dan tidak menggunakan CSS.

Milan Babuškov
sumber
2
Tidak menangani pemusatan vertikal, jadi -1.
SamB
1
Saya mengalami masalah serupa di mana saya memiliki logo di sebelah kiri dan beberapa menu teks di sebelah kanan. Menu harus sejajar dengan garis dasar logo. Menggunakan float: tepat untuk menu tidak berfungsi. Itu mengirim mereka ke sudut kanan atas, dan mereka tidak lagi disejajarkan secara vertikal dengan garis dasar logo.
Jean-François Beauchamp
1
Saya pikir Anda dapat menyelesaikan pemusatan vertikal dengan mengatur tinggi baris Judul menjadi sama dengan tinggi Tombol.
igors
1
@igors, +1, Anda benar. Ingatlah bahwa pertanyaan ini dari 2009.;)
Milan Babuškov
17

Ini semacam pertanyaan jebakan: kelihatannya sangat sederhana sampai Anda melakukannya

Katakanlah saya ingin judul dan tombol berada di tengah secara vertikal.

Saya ingin menyatakan sebagai catatan bahwa ya, pemusatan vertikal sulit di CSS. Ketika orang memposting, dan sepertinya tidak ada habisnya di SO, "dapatkah Anda melakukan X di CSS" jawabannya hampir selalu "ya" dan keluhan mereka tampaknya tidak dapat dibenarkan. Dalam hal ini, ya, satu hal itu sulit.

Seseorang sebaiknya mengedit seluruh pertanyaan menjadi "apakah pemusatan vertikal bermasalah di CSS?".

AmbroseChapel
sumber
11
Itulah jenis masalah saya dengan argumen "pembenci tabel": CSS dapat melakukan semua yang dapat dilakukan tabel ... kecuali untuk beberapa kasus yang cukup sederhana, umum, dan masuk akal (seperti pemusatan vertikal). CSS sepertinya janji pemilu menjadi buruk.
cletus
4
Maksud saya adalah bahwa pemusatan vertikal hanya tentang SATU-SATUNYA hal yang benar-benar sulit.
AmbroseChapel
3
CSS tidak dimaksudkan untuk menggantikan tabel; ini hanya dimaksudkan untuk memungkinkan Anda menyelesaikan sebagian besar masalah tata letak umum tanpa tabel. Jika meja berfungsi, gunakan meja, seperti Anda menggunakan pena untuk menggambar, bukan palu luncur.
Aaron Digulla
16

Judul float kiri, tombol float kanan, dan (inilah bagian yang tidak pernah saya ketahui sampai saat ini) - buat wadah dari keduanya {overflow:hidden} .

Itu seharusnya menghindari masalah indeks-z. Jika tidak berhasil, dan Anda benar - benar membutuhkan dukungan IE5, lanjutkan dan gunakan tabel.


sumber
+1 Wah, ada apa dengan luapan yang disembunyikan? Itu memang membuat perbedaan. Tidak tahu kenapa.
cletus
Sejujurnya, saya juga tidak mengerti, dan tidak dapat menemukan apa pun yang menyebutkannya di spesifikasi. Seseorang mengatakan kepada saya bahwa itu adalah cara yang "benar", setelah saya menjawab pertanyaan lain yang menyarankan mereka menggunakan elemen yang sudah dibersihkan untuk melakukannya. Sepertinya ide yang bagus bagiku.
Elemen mengambang masih perlu dibersihkan agar konten yang mengikutinya dapat mengalir dengan baik. overflow: hidden; hanya membahas ketinggian wadah.
Zack The Human
2
"overflow: hidden" adalah hack untuk mencapai 'ekspansi' dan pembersihan KEDUA ketinggian. Elemen berikut AKAN mengosongkan kotak itu (setidaknya di browser yang menerapkan bagian spesifikasi itu dengan benar).
Bobby Jack
1
-1 untuk tidak menangani pemusatan vertikal, tetapi +2 untuk overflow:hidden.
SamB
7

Dalam CSS murni, jawaban yang berhasil suatu hari akan digunakan "display:table-cell". Sayangnya itu tidak berfungsi di browser kelas A saat ini, jadi untuk semua itu Anda mungkin juga menggunakan tabel jika Anda hanya ingin mencapai hasil yang sama. Setidaknya Anda akan yakin bahwa ini bekerja cukup jauh di masa lalu.

Jujur, gunakan saja meja jika lebih mudah. Tidak akan sakit.

Jika semantik dan aksesibilitas elemen tabel benar-benar penting bagi Anda, ada draf yang berfungsi untuk menjadikan tabel Anda non-semantik:

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

Saya pikir ini memerlukan DTD khusus di luar XHTML 1.1, yang hanya akan memicu perdebatan text/htmlvs keseluruhan application/xml, jadi jangan pergi ke sana.

Jadi, ke masalah CSS yang belum terselesaikan ...

Untuk menyelaraskan dua elemen secara vertikal di tengahnya: itu dapat dilakukan dengan beberapa cara berbeda, dengan beberapa peretasan CSS yang tumpul.

Jika Anda dapat menyesuaikan dengan batasan berikut, maka ada cara yang relatif sederhana:

  • Ketinggian kedua elemen itu tetap.
  • Ketinggian wadah sudah diperbaiki.
  • Elemen akan cukup sempit agar tidak tumpang tindih (atau dapat disetel ke lebar tetap).

Kemudian Anda dapat menggunakan pemosisian absolut dengan margin negatif:

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

Tapi ini tidak ada gunanya dalam kebanyakan situasi ... Jika Anda sudah mengetahui ketinggian elemen, maka Anda bisa menggunakan float dan menambahkan margin yang cukup untuk memposisikannya sesuai kebutuhan.

Berikut adalah metode lain yang menggunakan garis dasar teks untuk meratakan dua kolom secara vertikal sebagai blok sebaris. Kekurangannya di sini adalah Anda perlu mengatur lebar tetap untuk kolom mengisi lebar dari tepi kiri. Karena kita perlu menjaga elemen terkunci pada garis dasar teks, kita tidak bisa hanya menggunakan float: tepat untuk kolom kedua. (Sebaliknya, kita harus membuat kolom pertama cukup lebar untuk mendorongnya.)

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

HTML: Kami menambahkan pembungkus .valign di sekitar setiap kolom. (Beri mereka nama yang lebih "semantik" jika itu membuat Anda lebih bahagia.) Ini perlu disimpan tanpa spasi di antaranya atau spasi teks akan memisahkan mereka. (Saya tahu itu menyebalkan, tapi itulah yang Anda dapatkan karena "murni" dengan markup dan memisahkannya dari lapisan presentasi ... Ha!)

CSS: Kami menggunakan vertical-align:middleuntuk menyejajarkan blok ke garis dasar teks dari elemen header grup. Ketinggian yang berbeda dari setiap blok akan tetap berada di tengah secara vertikal dan mendorong tinggi wadah mereka. Lebar elemen perlu dihitung agar sesuai dengan lebarnya. Di sini, angka 400 dan 100, dikurangi bantalan horizontal.

Perbaikan IE: Internet Explorer hanya menampilkan blok-sebaris untuk elemen sebaris asli (mis. Span, bukan div). Tapi, jika kita memberikan hasLayout div dan kemudian menampilkannya secara inline, itu akan berperilaku seperti blok-inline. Penyesuaian margin adalah untuk memperbaiki celah 1px di bagian atas (coba tambahkan warna latar belakang ke .group-title untuk melihatnya).

Andrew Vit
sumber
1
Hmm tampilan: tag table-X sepertinya bertujuan untuk melakukan layout menggunakan tabel, hanya saja tanpa menggunakan tag tabel?
Danubian Sailor
3

Saya akan merekomendasikan untuk tidak menggunakan tabel dalam hal ini, karena itu bukan data tabel; Ini murni presentasi untuk memiliki tombol yang terletak di paling kanan. Inilah yang akan saya lakukan untuk menduplikasi struktur tabel Anda (ubah ke H # yang berbeda agar sesuai dengan posisi Anda di hierarki situs Anda):

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

Jika Anda ingin perataan vertikal yang sebenarnya di tengah (yaitu, jika teks membungkus tombol masih rata tengah sehubungan dengan kedua baris teks), maka Anda perlu membuat tabel atau mengerjakan sesuatu dengan position: absolutedan margin. Anda dapat menambahkanposition: relative ke menu tarik-turun (atau lebih mungkin induknya) untuk menariknya ke tingkat urutan yang sama dengan tombol, memungkinkan Anda untuk menabraknya di atasnya dengan indeks-z, jika itu yang terjadi.

Perhatikan bahwa Anda tidak memerlukan width: 100%div karena ini adalah elemen level blok, dan zoom: 1membuat div berperilaku seperti memiliki clearfix di IE (browser lain mengambil clearfix yang sebenarnya). Anda juga tidak memerlukan semua kelas asing tersebut jika Anda menargetkan sesuatu secara lebih spesifik, meskipun Anda mungkin memerlukan div pembungkus atau span pada tombol untuk mempermudah pemosisian.

Satu Krayon
sumber
Solusi Anda tidak berfungsi pada IE6 karena: setelah pseudo-class.
Sebastian Hoitz
1
Ia bekerja di IE 6, berkat zoom: 1in .group-header, yang memicu hasLayout dan menyebabkan IE 6 berperilaku sama seperti jika ia memiliki elemen: after yang aktif.
Satu Krayon
2

Lakukan double float di div dan gunakan clearfix. http://www.webtoolkit.info/css-clearfix.html Apakah Anda memiliki batasan padding / margin?

<div class="clearfix">
   <div style="float:left">Title</div>
   <input type="button" value="Button" style="float:right" />
</div>
bendewey
sumber
Saya memiliki persyaratan pemusatan vertikal (dan sedikit bantalan ekstra). Saya rasa saya mengklarifikasi itu setelah Anda memposting.
cletus
2
<div class="group-header">
    <input type="button" name="Button" value="Button" style="float:right" />
    <span>Title</span>
</div>
Omer Bokhari
sumber
1

Saya memilih untuk menggunakan Flexbox, karena itu membuat segalanya menjadi lebih mudah.

Pada dasarnya Anda harus pergi ke induk dari anak-anak yang ingin Anda ratakan dan tambahkan display:box(tentu saja diawali). Untuk membuatnya duduk di samping, gunakan justify-content . Spasi di antara adalah hal yang tepat ketika Anda memiliki elemen yang perlu disejajarkan sampai akhir, seperti dalam kasus ini (lihat tautan) ...

Kemudian masalah perataan vertikal. Karena saya membuat induk dari dua elemen, Anda ingin menyelaraskan Flexbox. Sekarang mudah digunakanalign-items: center .

Kemudian saya menambahkan gaya yang Anda inginkan sebelumnya, menghapus float dari judul dan tombol di header dan menambahkan padding:

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

Lihat Demo

pengguna3522940
sumber
1

Saya setuju bahwa seseorang seharusnya hanya menggunakan tabel untuk data tabular, karena alasan sederhana bahwa tabel tidak muncul sampai mereka selesai memuat (tidak peduli seberapa cepatnya; metode CSS lebih lambat). Namun, saya merasa ini adalah solusi paling sederhana dan paling elegan:

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

Fungsi tombol dan detail tambahan lainnya dapat ditata dari bentuk dasar ini. Maaf atas tag yang buruk.

Galen777
sumber