Bagaimana cara membuat elemen inline-blok mengisi sisa garis?

186

Apakah hal seperti itu mungkin menggunakan CSS dan dua tag DIV inline-block (atau apa pun) alih-alih menggunakan tabel?

Versi tabelnya adalah ini (batas ditambahkan sehingga Anda dapat melihatnya):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
<table style="width:100%;">
<tr>
<td style="border:1px solid black;width:100px;height:10px;"></td>
<td style="border:1px solid black;height:10px;"></td>
</tr>
</table>
</body>
</html>

Ini menghasilkan kolom kiri dengan WIDTH TETAP (bukan lebar persentase), dan kolom kanan yang mengembang untuk mengisi RUANG SISA di baris. Kedengarannya cukup sederhana, bukan? Selain itu, karena tidak ada yang "mengambang", tinggi induk induk dengan benar mengembang untuk mencakup ketinggian konten.

--MULAI RANT -
Saya telah melihat implementasi "perbaikan jelas" dan "grail suci" untuk tata letak multi-kolom dengan kolom sisi lebar-tetap, dan mereka payah dan rumit. Mereka membalik urutan elemen, mereka menggunakan lebar persentase, atau mereka menggunakan float, margin negatif, dan hubungan antara atribut "kiri", "kanan", dan "margin" sangat kompleks. Lebih jauh lagi, tata letak adalah sub-pixel sensitif sehingga menambahkan bahkan satu pixel dari perbatasan, padding, atau margin akan memecah seluruh tata letak, dan mengirim seluruh kolom membungkus ke baris berikutnya. Misalnya, kesalahan pembulatan adalah masalah bahkan jika Anda mencoba melakukan sesuatu yang sederhana, seperti meletakkan 4 elemen pada sebuah garis, dengan lebar masing-masing diatur ke 25%.
--END RANT--

Saya sudah mencoba menggunakan "inline-block" dan "white-space: nowrap;", tetapi masalahnya adalah saya tidak bisa mendapatkan elemen ke-2 untuk mengisi ruang yang tersisa di telepon. Mengatur lebar ke sesuatu seperti "width: 100% - (LeftColumWidth) px" akan berfungsi dalam beberapa kasus, tetapi melakukan penghitungan dalam properti lebar tidak benar-benar didukung.

Triynko
sumber
1
Saya tidak berpikir ada cara yang waras untuk melakukan ini kecuali mengubahnya menjadi sebuah display: table-*konstruksi yang akan bekerja, tetapi tidak benar-benar "lebih semantik" baik (menjadi divsup yang mengerikan ) dan merusak kompatibilitas IE6. Saya pribadi akan tetap dengan <table>, kecuali seseorang berhasil datang dengan ide jenius sederhana yang bekerja tanpa
Pekka
51
Ya. Saya terus menjalankan semua argumen "tabel hindari" ini dari awal zaman CSS, dan mereka dibuat untuk membuat Anda terdengar seperti orang malas yang tidak kompeten jika Anda masih menggunakan tabel untuk tata letak. Maju cepat satu dekade, dan itu masih ideal-mimpi pipa. Faktanya adalah, flow semantik tata letak SUCK untuk tata letak yang tetap namun fleksibel seperti antarmuka dan formulir pengguna. Yang benar adalah bahwa orang pintar akan menggunakan tabel yang nyaman, karena mereka telah menghabiskan semua solusi CSS yang mungkin dan menyadari bahwa mereka semua tidak sempurna dan secara signifikan lebih kompleks daripada hanya menggunakan tabel.
Triynko
4
Mengapung? Tunjukkan pada saya kode yang berfungsi, di mana elemen end-of-line tidak membungkus garis secara tak terduga dan batas dan margin tidak merusak tata letak. Itulah yang salah dengan mereka. Juga, apakah wadah induk berukuran otomatis diperluas dengan benar untuk mencakup elemen apung tanpa peretasan "bersihkan"? Saya kira tidak.
Triynko
Jika Anda memiliki setidaknya satu elemen non-apung di wadah induk Anda, maka itu bukan benar-benar "retas" untuk menghapus mengapung, sekarang bukan? Ingatlah bahwa CSS berakar pada pencetakan - lihat css-tricks.com/containers-dont-clear-floats untuk diskusi yang bagus tentang mengapa Anda tidak mendapatkan pembersihan otomatis.
Chowlett
3
@Triynko: Ini yang saya buat sebelumnya: jsfiddle.net/thirtydot/qx32C - Saya pikir itu menyentuh sebagian besar poin Anda. Saya akan mendengar kritik Anda tentang demo yang saya lakukan, dan mencoba memperbaikinya setelah itu.
tigapuluh tanggal

Jawaban:

169

Lihat: http://jsfiddle.net/qx32C/36/

.lineContainer {
    overflow: hidden; /* clear the float */
    border: 1px solid #000
}
.lineContainer div {
    height: 20px
} 
.left {
    width: 100px;
    float: left;
    border-right: 1px solid #000
}
.right {
    overflow: hidden;
    background: #ccc
}
<div class="lineContainer">
    <div class="left">left</div>
    <div class="right">right</div>
</div>


Kenapa saya ganti margin-left: 100pxdengan overflow: hiddenon .right?

EDIT: Berikut adalah dua mirror untuk tautan di atas (mati):

tigapuluh
sumber
60
Jika Anda menyebut diri Anda seorang pengembang web, Anda harus mengklik tautan itu. Aku melakukannya, dan aku merasa seperti Jasmine yang naik karpet ajaib.
Chris Shouts
2
@ ChrisShouts, itu mungkin cara terbaik untuk menggambarkan ini. Metode ini tidak masuk akal, tapi sekali lagi ... Solusi yang bagus untuk sesuatu yang Anda harus dapat lakukan secara eksplisit.
mjvotaw
14
Overflow tersembunyi bukanlah solusi. Misalkan Anda tidak ingin meluap wadah yang tepat disembunyikan. Ini tidak membuat ukuran wadah yang tepat mengisi ruang yang tersisa di telepon. Ini adalah contoh pertanyaan berusia dua tahun yang belum saya tandai jawabannya, karena masih belum ada jawaban yang memuaskan.
Triynko
3
Triynko: meskipun Anda menggunakan 'overflow: hidden', umumnya tidak ada yang disembunyikan (setidaknya jika Anda hanya memiliki teks di sana). Teks / elemen di dalam div akan diatur sehingga sesuai di dalam div (kecuali Anda memiliki elemen yang lebih besar dari div, tentu saja).
CpnCrunch
1
@RMorrisey: Mungkin hanya perlu beberapa box-sizing: border-boxdi divs. Tebakan saja, karena Anda tidak memberikan demo yang menunjukkan perilaku yang Anda uraikan. Yang makhluk mengatakan, para display: tablesolusi berbasis biasanya lebih baik . Ini adalah pertanyaan yang sangat lama, tapi saya pikir saya mencoba menghindari apa pun yang berhubungan dengan tabel dalam pertanyaan ini karena perilaku OP.
tigapuluhdot
65

Solusi modern menggunakan flexbox:

.container {
    display: flex;
}
.container > div {
    border: 1px solid black;
    height: 10px;
}

.left {
   width: 100px;
}

.right {
    width: 100%;
    background-color:#ddd;
}
<div class="container">
  <div class="left"></div>
  <div class="right"></div>
</div>

http://jsfiddle.net/m5Xz2/100/

Panu Horsmalahti
sumber
4
tampilan fleksibel dan lebar 100% .. harus diingat
dreamerkumar
10
ketika menggunakan flex, mengapa tidak menggunakan flex: 1bukan width: 100%?
Itai Bar-Haim
Bagi mereka yang baru menggunakan flexbox : flex: 1adalah singkatan flex-grow: 1. Ini atribut kombinasi: flex: <grow> <shrink> <basis>.
tanius
1
Hanya catatan singkat yang menampilkan: flex tidak didukung di IE <11, dan sangat buggy di 11.
Eric Shields
1
@EricShields ini seharusnya tidak mencegah siapa pun menggunakan Flexbox. Saat ini kami sudah flexbugstahu.
Neurotransmitter
47

Kompatibel dengan peramban modern umum (IE 8+): http://jsfiddle.net/m5Xz2/3/

.lineContainer {
    display:table;
    border-collapse:collapse;
    width:100%;
}
.lineContainer div {
    display:table-cell;
    border:1px solid black;
    height:10px;
}
.left {
    width:100px;
}
 <div class="lineContainer">
    <div class="left">left</div>
    <div class="right">right</div>
</div>

Frosty Z
sumber
9
Argumen menentang penggunaan tabel tidak ada hubungannya dengan karakteristik penyajiannya. Ini ada hubungannya dengan markup yang tidak terkelola, gaya / kerumitan dokumen, dan semantik yang tidak tepat. Tidak satu pun dari argumen ini berlaku untuk display:table.
Rich Remer
Ini tidak menjawab bagaimana cara inline-blockmengisi sisa baris.
Neurotransmitter
1
@TranslucentCloud Saya setuju bahwa jawaban saya tidak benar-benar menjawab judul pertanyaan, tetapi ia menyediakan cara untuk mengisi lebar yang tersedia menggunakan divs, seperti yang ditanyakan dalam badan pertanyaan.
Frosty Z
1
Saya suka solusi ini. Anda tidak dipaksa untuk menggunakan beberapa stylings aneh yang hilang dari logika CSS tersembunyi (seperti untuk overflow tersembunyi).
Chaoste
4

Anda dapat menggunakan calc (100% - 100px) pada elemen fluida, bersama dengan tampilan: inline-block untuk kedua elemen.

Ketahuilah bahwa tidak boleh ada spasi di antara tag, jika tidak, Anda juga harus mempertimbangkan ruang itu di kalk.

.left{
    display:inline-block;
    width:100px;
}
.right{
    display:inline-block;
    width:calc(100% - 100px);
}


<div class=“left”></div><div class=“right”></div>

Contoh cepat: http://jsfiddle.net/dw689mt4/1/

SuperIRis
sumber
1

Saya telah menggunakan flex-growproperti untuk mencapai tujuan ini. Anda harus mengatur display: flexuntuk wadah induk, maka Anda perlu mengatur flex-grow: 1untuk blok yang Anda ingin mengisi ruang yang tersisa, atau sama flex: 1seperti tanius yang disebutkan dalam komentar.

Vladislav Kovechenkov
sumber
0

Jika Anda tidak dapat menggunakan overflow: hidden(karena Anda tidak mau overflow: hidden) atau jika Anda tidak menyukai peretasan / penyelesaian CSS, Anda bisa menggunakan JavaScript. Perhatikan bahwa ini mungkin tidak berfungsi dengan baik karena ini JavaScript.

var parent = document.getElementsByClassName("lineContainer")[0];
var left = document.getElementsByClassName("left")[0];
var right = document.getElementsByClassName("right")[0];
right.style.width = (parent.offsetWidth - left.offsetWidth) + "px";
window.onresize = function() {
  right.style.width = (parent.offsetWidth - left.offsetWidth) + "px";
}
.lineContainer {
  width: 100% border: 1px solid #000;
  font-size: 0px;
  /* You need to do this because inline block puts an invisible space between them and they won't fit on the same line */
}

.lineContainer div {
  height: 10px;
  display: inline-block;
}

.left {
  width: 100px;
  background: red
}

.right {
  background: blue
}
<div class="lineContainer">
  <div class="left"></div>
  <div class="right"></div>
</div>

http://jsfiddle.net/ys2eogxm/

Nick Manning
sumber