Làm thế nào để làm cho một phần tử khối nội tuyến điền vào phần còn lại của dòng?


185

Điều đó có khả thi khi sử dụng CSS và hai thẻ DIV chặn nội tuyến (hoặc bất cứ thứ gì) thay vì sử dụng bảng không?

Phiên bản bảng là cái này (viền được thêm vào để bạn có thể thấy nó):

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

Nó tạo ra một cột bên trái với WIDTH CỐ ĐỊNH (không phải là chiều rộng phần trăm) và một cột bên phải mở rộng để lấp đầy KHÔNG GIAN TUYỆT VỜI trên dòng. Nghe có vẻ khá đơn giản phải không? Hơn nữa, vì không có gì là "nổi", chiều cao của ngăn chứa cha mẹ mở rộng đúng cách để bao gồm chiều cao của nội dung.

--BEGIN RANT--
Tôi đã thấy các triển khai "sửa lỗi rõ ràng" và "chén thánh" cho bố cục nhiều cột với cột bên có chiều rộng cố định, và chúng rất phức tạp. Chúng đảo ngược thứ tự của các phần tử, chúng sử dụng độ rộng phần trăm hoặc chúng sử dụng số float, lề âm và mối quan hệ giữa các thuộc tính "trái", "phải" và "lề" rất phức tạp. Hơn nữa, các bố cục có độ nhạy pixel phụ để việc thêm ngay cả một pixel viền, phần đệm hoặc lề sẽ phá vỡ toàn bộ bố cục và gửi toàn bộ cột cho dòng tiếp theo. Ví dụ, lỗi làm tròn là một vấn đề ngay cả khi bạn cố gắng làm điều gì đó đơn giản, như đặt 4 phần tử trên một dòng, với chiều rộng của mỗi người được đặt thành 25%.
--END RANT--

Tôi đã thử sử dụng "khối nội tuyến" và "khoảng trắng: nowrap;", nhưng vấn đề là tôi không thể lấy phần tử thứ 2 để lấp đầy khoảng trống còn lại trên dòng. Đặt chiều rộng thành một cái gì đó như "width: 100% - (LeftColumWidth) px" sẽ hoạt động trong một số trường hợp, nhưng thực hiện tính toán trong thuộc tính chiều rộng không thực sự được hỗ trợ.


1
Tôi không nghĩ có một cách lành mạnh để làm điều này ngoại trừ việc biến nó thành một display: table-*cấu trúc sẽ hoạt động, nhưng thực sự không "nhiều ngữ nghĩa" hơn (là một trường hợp khủng khiếp của divsúp) và phá vỡ khả năng tương thích IE6. Cá nhân tôi sẽ gắn bó với <table>, trừ khi có ai đó nghĩ ra một ý tưởng đơn giản thiên tài hoạt động mà không có
Pekka

51
Vâng. Tôi tiếp tục chạy vào tất cả các đối số "tránh các bảng" này từ buổi bình minh của thời đại CSS và chúng được phát âm để khiến bạn nghe như một kẻ lười biếng bất tài nếu bạn vẫn sử dụng các bảng để bố trí. Nhanh chóng chuyển tiếp một thập kỷ, và nó vẫn là một giấc mơ lý tưởng. Thực tế là, ngữ nghĩa bố cục dòng Suck cho các bố cục cố định nhưng linh hoạt như giao diện và biểu mẫu người dùng. Sự thật là những người thông minh sẽ sử dụng các bảng khi thuận tiện, vì họ đã dùng hết mọi giải pháp CSS có thể và nhận ra rằng tất cả chúng đều không hoàn hảo và phức tạp hơn đáng kể so với chỉ sử dụng bảng.
Triynko

4
Phao? Chỉ cho tôi mã làm việc, trong đó các phần tử cuối dòng không bao bọc một cách khó lường và các đường viền và lề không phá vỡ bố cục. Đó là những gì sai với họ. Ngoài ra, bộ chứa cha mẹ có kích thước tự động có mở rộng đúng cách để bao gồm các phần tử nổi mà không có các bản hack "sửa lỗi rõ ràng" không? Tôi đã không nghĩ như vậy.
Triynko

Nếu bạn đã có ít nhất một phần tử không nổi trong thùng chứa cha mẹ của mình, thì đó không thực sự là một "hack" để xóa phao, bây giờ phải không? Hãy nhớ rằng CSS có nguồn gốc từ việc in ấn - xem css-tricks.com/containers-dont-clear-floats để thảo luận tốt về lý do tại sao bạn không nhận được tự động xóa.
Chowlett

3
@Triynko: Đây là những gì tôi đã thực hiện trước đó: jsfiddle.net/thundreddot/qx32C - Tôi nghĩ rằng nó đạt được hầu hết các điểm của bạn. Tôi sẽ nghe bài phê bình của bạn về bản demo mà tôi đã làm và cố gắng sửa nó sau đó.
ba mươi

Câu trả lời:


169

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


Tại sao tôi lại thay thế margin-left: 100pxvới overflow: hiddentrên .right?

EDIT: Đây là hai gương cho liên kết (đã chết) ở trên:


60
Nếu bạn gọi cho mình một nhà phát triển web, bạn cần nhấp vào liên kết đó. Tôi đã làm, và tôi cảm thấy giống như Jasmine trên một chuyến đi thảm thần kỳ.
Chris hét lên

2
@ChrisShouts, đó có lẽ là cách tốt nhất để mô tả điều này. Phương pháp này chỉ vô nghĩa, nhưng sau đó một lần nữa ... Một cách giải quyết tuyệt vời cho một cái gì đó mà bạn sẽ có thể làm rõ ràng.
mjvotaw

14
Tràn ẩn không phải là một giải pháp. Giả sử bạn không muốn tràn bộ chứa bên phải. Điều này không làm cho kích thước của container bên phải lấp đầy khoảng trống còn lại trên dòng. Đây là một ví dụ về câu hỏi hai năm tuổi mà tôi vẫn chưa đánh dấu câu trả lời, vì vẫn chưa có câu trả lời thỏa đáng.
Triynko

3
Triynko: ngay cả khi bạn đang sử dụng 'tràn: ẩn', nhìn chung sẽ không có gì bị ẩn (ít nhất là nếu bạn chỉ có văn bản trong đó). Văn bản / thành phần bên trong div sẽ được sắp xếp sao cho chúng khớp với bên trong div (trừ khi bạn có một phần tử lớn hơn div, tất nhiên).
CpnCrunch

1
@RMorrisey: Có lẽ chỉ cần một số box-sizing: border-boxtrên divs. Chỉ là một phỏng đoán, vì bạn đã không cung cấp bản demo cho thấy hành vi bạn mô tả. Nói như vậy, các display: tablegiải pháp dựa trên thường tốt hơn là . Đây là một câu hỏi rất cũ, nhưng tôi nghĩ rằng tôi đã cố tránh mọi thứ liên quan đến các bảng trong câu hỏi này do hành vi của OP.
ba mươi

63

Một giải pháp hiện đại sử dụng 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
hiển thị flex và chiều rộng 100% .. phải nhớ
dreamerkumar

9
Khi sử dụng flex, tại sao không sử dụng flex: 1thay vì width: 100%?
Itai Bar-Haim

Đối với những người mới sử dụng flexbox : flex: 1là viết tắt cho flex-grow: 1. Đây là một thuộc tính kết hợp : flex: <grow> <shrink> <basis>.
tanius

1
Chỉ cần lưu ý nhanh rằng hiển thị: flex không được hỗ trợ trong IE <11 và rất có lỗi trong 11.
Eric Shields

1
@EricShields không nên ngăn bất kỳ ai sử dụng Flexbox. Ngày nay chúng tôi có flexbugsbạn biết.
Chất dẫn truyền thần kinh

47

Tương thích với các trình duyệt hiện đại phổ biến (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
Đối số chống lại việc sử dụng các bảng không liên quan gì đến các đặc điểm trình bày của nó. Nó phải được thực hiện với đánh dấu không thể quản lý, nhầm lẫn phong cách / tài liệu và ngữ nghĩa không phù hợp. Không có đối số nào trong số này áp dụng cho display:table.
Rich Remer

Điều này không trả lời làm thế nào để inline-blockđiền vào phần còn lại của dòng.
Chất dẫn truyền thần kinh

1
@TranslucentCloud Tôi đồng ý rằng câu trả lời của tôi không trả lời chính xác tiêu đề câu hỏi, nhưng nó cung cấp một cách để lấp đầy chiều rộng có sẵn bằng cách sử dụng div, như được hỏi trong phần thân câu hỏi.
Frosty Z

1
Tôi thích giải pháp này rất nhiều. Bạn không bị buộc phải sử dụng một số kiểu dáng kỳ lạ phát sinh từ logic CSS bị ẩn (như bị ẩn tràn).
Chaoste

4

Bạn có thể sử dụng calc (100% - 100px) trên phần tử chất lỏng, cùng với display: inline-block cho cả hai phần tử.

Xin lưu ý rằng không nên có bất kỳ khoảng trống nào giữa các thẻ, nếu không bạn cũng sẽ phải xem xét khoảng trống đó trong calc của mình.

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


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

Ví dụ nhanh: http://jsfiddle.net/dw689mt4/1/


1

Tôi đã sử dụng flex-growtài sản để đạt được mục tiêu này. Bạn sẽ phải đặt display: flexcho bộ chứa cha mẹ, sau đó bạn cần đặt flex-grow: 1cho khối bạn muốn lấp đầy không gian còn lại, hoặc giống flex: 1như tanius đã đề cập trong các nhận xét.


0

Nếu bạn không thể sử dụng overflow: hidden(vì bạn không muốn overflow: hidden) hoặc nếu bạn không thích hack / giải pháp thay thế CSS, bạn có thể sử dụng JavaScript thay thế. Lưu ý rằng nó có thể không hoạt động tốt vì đó là 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/


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.