Як змусити елемент вкладеного блоку заповнити залишок рядка?


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>

Він створює лівий стовпець із ЗАМИСЛЕНОЮ ШІРНОЮ (а не відсотковою шириною) та правий стовпець, який розширюється, щоб заповнити ЗАЛИШНИЙ ПРОСТОР на рядку. Звучить досить просто, правда? Крім того, оскільки нічого не "плаває", висота батьківського контейнера належним чином збільшується, щоб охопити висоту вмісту.

- BEGIN RANT--
Я бачив реалізацію "чіткого виправлення" та "святого грааля" для багатошарових макетів із стовпчиком фіксованої ширини, і вони смокчуть і вони складні. Вони змінюють порядок елементів, вони використовують процентну ширину, або вони використовують поплавці, негативні поля, а відносини між атрибутами "ліворуч", "праворуч" та "маржа" є складними. Крім того, макети чутливі до пікселів, так що додавання навіть одного пікселя меж, прокладки або поля порушить весь макет, а цілі стовпці перегортають у наступний рядок. Наприклад, помилки округлення є проблемою, навіть якщо ви намагаєтеся зробити щось просте, наприклад, поставити 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 і зрозуміли, що всі вони недосконалі та значно складніші, ніж просто використання таблиці.
Трайнко

4
Поплавці? Покажіть мені робочий код, коли елементи кінцевих рядків не обертаються непередбачувано, а межі та поля не порушують макет. Ось що з ними не так. Крім того, чи належним чином розширюється батьківський контейнер розміром з автоматичним розміром, щоб охоплювати плаваючі елементи з вимиканнями "чіткого виправлення"? Я так не думав.
Трайнко

Якщо у вас є принаймні один неплаваючий елемент у батьківському контейнері, то очистити поплавці насправді це не "хак", тепер це так? Пам'ятайте, що 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?

EDIT: Ось два дзеркала для вищезазначеного (мертвого) посилання:


60
Якщо ви називаєте себе веб-розробником, вам потрібно натиснути це посилання. Я це зробив, і я відчував себе так само, як Жасмін на чарівної їзді на килимах.
Кріс Криків

2
@ChrisShouts, це, мабуть, найкращий спосіб описати це. Цей метод просто не має сенсу, але знову ж таки ... Чудовий спосіб вирішення того, що ви повинні мати можливість явно робити.
mjvotaw

14
Переповнений прихований не є рішенням. Припустимо, ви не хочете, щоб переповнення потрібного контейнера було прихованим. Це не робить розмір правого контейнера заповнювати решту місця на рядку. Це приклад дворічного запитання, на яке я досі не зазначив відповіді, тому що досі немає задовільної відповіді.
Трайнко

3
Трієнко: навіть якщо ви використовуєте 'overflow: hidden', загалом нічого не буде приховано (принаймні, якщо у вас просто текст там). Текст / елементи всередині div будуть розташовані таким чином, щоб вони вміщувалися всередині div (якщо, звичайно, у вас є елемент, який більше, ніж div).
CpnCrunch

1
@RMorrisey: Напевно, просто потрібні деякі box-sizing: border-boxна divs. Лише здогадка, оскільки ви не надали демонстраційну демонстрацію поведінки, яку описуєте. Це , так би мовити, засноване рішення, як правило , краще . Це дуже давнє запитання, але я думаю, що я намагався уникати нічого спільного з таблицями в цьому питанні через поведінку ОП. display: table
тридцятьдот

65

Сучасне рішення за допомогою флексокса:

.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, чому б не використовувати flex: 1замість width: 100%?
Itai Bar-Haim

Для тих, хто є новим у flexbox : flex: 1це стенограма для flex-grow: 1. Це атрибут поєднання: flex: <grow> <shrink> <basis>.
таніум

1
Лише швидка примітка, що дисплей: flex не підтримується в IE <11, а дуже баггі в 11.
Ерік Шилдс

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.
Річ Ремер

Це не відповідає як inline-blockзаповнити залишок рядка.
Нейромедіатор

1
@TranslucentCloud Я погоджуюся, що моя відповідь не відповідає точно назвою запитання, але це забезпечує спосіб заповнити наявну ширину за допомогою divs, про що запитують в тілі питань.
Морозний Z

1
Мені це рішення дуже подобається. Ви не змушені використовувати якісь дивні стилі, які відрізняються від прихованої логіки CSS (наприклад, для переповнення прихованих).
Chaoste

4

Ви можете використовувати calc (100% - 100px) на текучому елементі разом з дисплеєм: вбудований блок для обох елементів.

Майте на увазі, що між тегами не повинно бути місця, інакше вам доведеться враховувати цей простір і в вашому обчисленні.

.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як таніус згадується в коментарях.


0

Якщо ви не можете використовувати overflow: hidden(тому що ви не хочете overflow: hidden) або якщо вам не подобаються CSS-хаки / обхідні шляхи, ви можете використовувати 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/


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.