จะทำให้องค์ประกอบ inline-block เติมส่วนที่เหลือของบรรทัดได้อย่างไร


186

เป็นไปได้ไหมที่ใช้ CSS และแท็ก DIV แบบอินไลน์บล็อก (หรืออะไรก็ได้) แทนการใช้ตาราง

เวอร์ชันของตารางคือ (เพิ่มเส้นขอบเพื่อให้คุณเห็น):

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

มันสร้างคอลัมน์ด้านซ้ายด้วยความกว้างคงที่ (ไม่ใช่ความกว้างร้อยละ) และคอลัมน์ด้านขวาที่ขยายเพื่อเติมเต็มพื้นที่ที่เหลืออยู่ในบรรทัด ฟังดูง่าย ๆ ใช่มั้ย นอกจากนี้เนื่องจากไม่มีสิ่งใด "ลอยตัว" ความสูงของคอนเทนเนอร์หลักจะขยายอย่างเหมาะสมเพื่อรวมความสูงของเนื้อหา

- เริ่มต้น RANT -
ฉันได้เห็นการใช้งาน "การแก้ไขที่ชัดเจน" และ "จอกศักดิ์สิทธิ์" สำหรับเค้าโครงหลายคอลัมน์พร้อมคอลัมน์ด้านกว้างคงที่และพวกเขาดูดและพวกเขากำลังซับซ้อน พวกเขากลับคำสั่งขององค์ประกอบพวกเขาใช้ความกว้างร้อยละหรือพวกเขาใช้ลอยขอบลบและความสัมพันธ์ระหว่างแอตทริบิวต์ "ซ้าย", "ขวา" และ "ระยะขอบ" มีความซับซ้อน นอกจากนี้เลย์เอาต์มีความละเอียดอ่อนพิกเซลย่อยเพื่อให้เพิ่มแม้แต่หนึ่งพิกเซลของเส้นขอบ, padding หรือระยะขอบจะทำลายรูปแบบทั้งหมดและส่งการตัดคอลัมน์ทั้งหมดไปยังบรรทัดถัดไป ตัวอย่างเช่นข้อผิดพลาดในการปัดเศษเป็นปัญหาแม้ว่าคุณจะพยายามทำสิ่งที่ง่ายเช่นใส่ 4 องค์ประกอบในบรรทัดโดยความกว้างของแต่ละคนตั้งไว้ที่ 25%
--END RANT -

ฉันได้ลองใช้ "inline-block" และ "white-space: nowrap;" แต่ปัญหาคือฉันไม่สามารถรับองค์ประกอบที่ 2 เพื่อเติมช่องว่างที่เหลือในบรรทัด การตั้งค่าความกว้างเป็นบางอย่างเช่น "width: 100% - (LeftColumWidth) px" จะทำงานในบางกรณี แต่การคำนวณในคุณสมบัติความกว้างนั้นไม่ได้รับการสนับสนุนจริงๆ


1
ฉันไม่คิดว่าจะมีวิธีที่มีเหตุผลในการทำเช่นนี้ยกเว้นการเปลี่ยนสิ่งนี้เป็นสิ่งdisplay: table-*ก่อสร้างที่จะใช้งานได้ แต่ก็ไม่ได้หมายถึง "ความหมายมากขึ้น" (เช่นdivซุปที่แย่มาก) และแบ่ง IE6 ฉันเองจะยึดติดกับ<table>ถ้าไม่มีใครจัดการที่จะเกิดขึ้นกับความคิดที่เรียบง่ายอัจฉริยะที่ทำงานได้โดยไม่ต้อง
Pekka

51
ใช่. ฉันยังคงพบข้อโต้แย้ง "หลีกเลี่ยงตาราง" เหล่านี้ทั้งหมดตั้งแต่เช้าตรู่ของยุค CSS และพวกเขากำลังพูดเพื่อให้คุณฟังเหมือนคนขี้เกียจที่ไร้ความสามารถหากคุณยังคงใช้ตารางสำหรับการจัดวาง ก้าวไปข้างหน้าอย่างรวดเร็วนานนับสิบปีและมันก็ยังเป็นความฝันในอุดมคติของท่อ ความจริงก็คือความหมายของผังเค้าโครงของ SUCK สำหรับรูปแบบคงที่ แต่มีความยืดหยุ่นเช่นส่วนต่อประสานผู้ใช้และแบบฟอร์ม ความจริงก็คือคนฉลาดจะใช้ตารางที่สะดวกเพราะพวกเขาได้หมดทุกวิธีการแก้ปัญหา CSS ที่เป็นไปได้และตระหนักว่าพวกเขาทั้งหมดไม่สมบูรณ์และมีความซับซ้อนมากขึ้นกว่าเพียงแค่ใช้ตาราง
Triynko

4
ลอยตัว? แสดงโค้ดที่ใช้งานได้ซึ่งองค์ประกอบที่อยู่ท้ายบรรทัดไม่สามารถตัดบรรทัดได้อย่างไม่คาดคิดและเส้นขอบและระยะขอบจะไม่ทำลายเค้าโครง นั่นคือสิ่งที่ผิดปกติกับพวกเขา นอกจากนี้คอนเทนเนอร์พาเรนต์ขนาดอัตโนมัติจะถูกขยายอย่างเหมาะสมเพื่อรวมองค์ประกอบลอยที่ไม่มีแฮ็ก "clear fix" หรือไม่ ฉันไม่คิดอย่างนั้น
Triynko

หากคุณมีองค์ประกอบที่ไม่ลอยอย่างน้อยหนึ่งองค์ประกอบในคอนเทนเนอร์หลักของคุณนั่นไม่ใช่ "แฮ็ค" สำหรับการล้างข้อมูลลอยตอนนี้ใช่ไหม โปรดจำไว้ว่า CSS มีรากฐานในการพิมพ์ - ดูcss-tricks.com/containers-dont-clear-floatsสำหรับการอภิปรายที่ดีว่าทำไมคุณถึงไม่ได้รับการล้างอัตโนมัติ
Chowlett

3
@Triynko: นี่คือสิ่งที่ฉันทำไว้ก่อนหน้านี้: jsfiddle.net/thirtydot/qx32C - ฉันคิดว่ามันได้คะแนนมากที่สุด ฉันจะได้ยินคำวิจารณ์ของคุณเกี่ยวกับการสาธิตที่ฉันทำและพยายามแก้ไขในภายหลัง
สามสิบ

คำตอบ:


169

ดู: 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>


ผมไม่เปลี่ยนทำไมmargin-left: 100pxกับoverflow: hiddenบน.right?

แก้ไข: ต่อไปนี้เป็นกระจกสองหน้าสำหรับลิงก์ด้านบน (ตาย):


60
หากคุณเรียกตัวเองว่าเป็นนักพัฒนาเว็บคุณจะต้องคลิกลิงก์นั้น ฉันทำและฉันรู้สึกเหมือนจัสมีนบนพรมวิเศษ
Chris Shouts

2
@ChrisShouts นั่นอาจเป็นวิธีที่ดีที่สุดในการอธิบายเรื่องนี้ วิธีนี้ไม่สมเหตุสมผล แต่แล้วอีกครั้ง ... วิธีแก้ปัญหาที่ยอดเยี่ยมสำหรับสิ่งที่คุณควรจะทำอย่างชัดเจน
mjvotaw

14
การโอเวอร์โฟลที่ซ่อนอยู่ไม่ใช่วิธีแก้ปัญหา สมมติว่าคุณไม่ต้องการให้มีการล้นของคอนเทนเนอร์ที่ถูกต้อง สิ่งนี้ไม่ทำให้ขนาดของคอนเทนเนอร์ที่เหมาะสมเติมพื้นที่ว่างที่เหลืออยู่บนบรรทัด นี่เป็นตัวอย่างของคำถามสองปีที่ฉันยังไม่ได้ทำเครื่องหมายคำตอบเพราะยังไม่มีคำตอบที่น่าพอใจ
Triynko

3
Triynko: ถึงแม้ว่าคุณกำลังใช้ 'ล้น': ซ่อนอยู่ 'โดยทั่วไปจะไม่มีอะไรซ่อนอยู่ (อย่างน้อยถ้าคุณมีข้อความอยู่ในนั้น) ข้อความ / องค์ประกอบภายใน div จะถูกจัดเรียงเพื่อให้พอดีกับ div (เว้นแต่คุณจะมีองค์ประกอบที่มีขนาดใหญ่กว่า div แน่นอน)
CpnCrunch

1
@Rorrisey: อาจต้องการเพียงบางอย่างbox-sizing: border-boxในdivs เป็นเพียงการคาดเดาเนื่องจากคุณไม่ได้ให้การสาธิตที่แสดงพฤติกรรมที่คุณอธิบาย ที่ถูกกล่าวว่า, แก้ปัญหาชั่นมักจะดีกว่า นี่เป็นคำถามที่เก่ามาก แต่ฉันคิดว่าฉันพยายามหลีกเลี่ยงสิ่งใดที่เกี่ยวข้องกับตารางในคำถามนี้เนื่องจากพฤติกรรมของ OP display: table
สามสิบ

65

โซลูชันที่ทันสมัยโดยใช้ 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/


4
แสดงความยืดหยุ่นและความกว้าง 100% .. ต้องจำไว้
Dreamerkumar

10
เมื่อใช้ดิ้นทำไมไม่ใช้flex: 1แทนwidth: 100%?
Itai Bar-Haim

สำหรับผู้ที่ใหม่กับflexbox : คือชวเลขflex: 1 flex-grow: 1มันเป็นคุณสมบัติการรวมกัน: flex: <grow> <shrink> <basis>.
tanius

1
เพียงแค่ทราบอย่างรวดเร็วว่า display: flex ไม่ได้รับการสนับสนุนใน IE <11 และ buggy มากใน 11
Eric Shields

1
@EricShields สิ่งนี้ไม่ควรป้องกันไม่ให้ใครใช้ Flexbox ทุกวันนี้เราflexbugsรู้แล้ว
สารสื่อประสาท

47

เข้ากันได้กับเบราว์เซอร์สมัยใหม่ทั่วไป (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>


9
การโต้เถียงกับการใช้ตารางไม่มีอะไรเกี่ยวข้องกับลักษณะการนำเสนอ มันเกี่ยวข้องกับมาร์กอัปที่ไม่สามารถจัดการรูปแบบ / เอกสารที่ยุ่งเหยิงและความหมายที่ไม่เหมาะสม ไม่มีข้อโต้แย้งdisplay:tableใดที่เกี่ยวข้องกับ
Rich Remer

สิ่งนี้ไม่ตอบวิธีinline-blockเติมส่วนที่เหลือของบรรทัด
สารสื่อประสาท

1
@TranslucentCloud ฉันยอมรับว่าคำตอบของฉันไม่ได้ตอบชื่อคำถามทุกประการ แต่ให้วิธีการเติมความกว้างที่มีโดยใช้ div ตามที่ถามในเนื้อหาของคำถาม
Frosty Z

1
ฉันชอบวิธีนี้มาก คุณไม่ได้บังคับให้ใช้สไตล์แปลก ๆ ที่เกิดจากตรรกะ CSS ที่ซ่อนอยู่ (เช่นการซ่อนล้น)
Chaoste

4

คุณสามารถใช้ Calc (100% - 100px) บนองค์ประกอบของของเหลวพร้อมกับจอแสดงผล: inline-block สำหรับองค์ประกอบทั้งสอง

โปรดทราบว่าไม่ควรมีช่องว่างระหว่างแท็กมิฉะนั้นคุณจะต้องพิจารณาช่องว่างนั้นในการคำนวณด้วย

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


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

ตัวอย่างด่วน: http://jsfiddle.net/dw689mt4/1/


1

ฉันใช้flex-growคุณสมบัติเพื่อให้บรรลุเป้าหมายนี้ คุณจะต้องตั้งค่าdisplay: flexสำหรับคอนเทนเนอร์หลักแล้วคุณจะต้องตั้งflex-grow: 1สำหรับบล็อกที่คุณต้องการที่จะเติมช่องว่างที่เหลืออยู่หรือเพียงแค่flex: 1เป็นtaniusกล่าวถึงในการแสดงความคิดเห็น


0

หากคุณไม่สามารถใช้overflow: hidden(เพราะคุณไม่ต้องการoverflow: hidden) หรือถ้าคุณไม่ชอบ CSS hacks / วิธีแก้ไขคุณสามารถใช้ JavaScript แทน โปรดทราบว่าอาจใช้งานไม่ได้เช่นกันเนื่องจากเป็น 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/


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.