Розгорніть ключ, щоб заповнити залишилася ширину


552

Я хочу мати двоколонний макет, де кожен може мати змінну ширину, наприклад

div {
  float: left;
}

.second {
  background: #ccc;
}
<div>Tree</div>
<div class="second">View</div>

Я хочу, щоб розділ "view" розширився на всю доступну ширину після того, як div "tree" заповнив необхідний простір.

Наразі мій «перегляд» діва змінено на вміст, який він містить. Також буде добре, якщо обидва диви займуть всю висоту.


Не дублювати відмову від відповідальності:



1
Або я не розумію питання, або я не розумію, як ви обираєте прийняту відповідь, оскільки там ширина і висота фіксуються з незручностіoverflow hidden
user10089632

Відповіді:


1013

Вирішення цієї проблеми насправді дуже просто, але не все очевидно. Ви повинні запустити щось, що називається "контекст блокування форматування" (BFC), який взаємодіє з плаваючими певними способами.

Просто візьміть цей другий div, вийміть поплавок і дайте його overflow:hiddenзамість цього. Будь-яке значення переповнення, окрім видимого, робить блок, на який він встановлений, стає BFC. BFCs не дозволяють поплавцям нащадків бігти від них, а також не дозволяють поплавцям побратимів / предків втручатися в них. Чистий ефект тут полягає в тому, що плаваючий div зробить свою справу, тоді другий div буде звичайним блоком, займаючи всю наявну ширину, крім тієї, яку займає поплавок .

Це має працювати у всіх поточних браузерах, хоча, можливо, доведеться запускати hasLayout в IE6 та 7. Я не можу згадати.

Демо:


28
Відмінна відповідь! Але ви помиляєтесь, коли кажете, що "будь-яке значення переповнення, крім авто", зробить це BFC. Що ви маєте на увазі, що будь-яке значення переповнення, окрім типового (видиме), зробить його BFC. Насправді, автоматичне переповнення працює також ідеально - ось що я рекомендую (про всяк випадок, якщо у вас є відносно розташовані елементи, які можуть визивати з цього діла).
BT

52
Ця стаття має гарне пояснення: colinaarts.com/articles/the-magic-of-overflow-hidden
Макс Кантор

1
Що робити, якщо вміст достатньо великий, щоб переповнити div?
giannis christofakis

11
Важливо зазначити, що порядок дітей має значення. Плаваючий елемент з фіксованою шириною повинен бути вище іншого. Займав мене занадто довго, щоб зрозуміти, чому це не працювало для мене з переключеним замовленням.
Riplexus

2
Я написав відповідь, в якій пояснював, чому невидиме переповнення всіх речей викликає BFC на основі відповідей Девіда та Бориса, які можна знайти тут: stackoverflow.com/questions/9943503/… Чи було моє тлумачення правильним?
BoltClock

104

Я щойно відкрив для себе магію флексових коробок (display: flex). Спробуйте це:

<style>
  #box {
    display: flex;
  }
  #b {
    flex-grow: 100;
    border: 1px solid green;
  }
</style>
<div id='box'>
 <div id='a'>Tree</div>
 <div id='b'>View</div>
</div>

Flex коробки дають мені той контроль, якого я хотів, щоб css був протягом 15 років. Нарешті тут! Більше інформації: https://css-tricks.com/snippets/css/a-guide-to-flexbox/


Я не знаю, що ви виявили, але ваш код не працює в останньому Chrome jsfiddle.net/fjb548kw/3
Євгеній Афанасьєв,

@YevgeniyAfanasyev я видалив "float: left;" щоб виправити проблему. Дякую за замітку!
BT

Дякую. Чи можете ви поясніть, чому у вас це flex-grow: 100;замість flex-grow: 1;?
Євген Афанасьєв

2
@ YevgeniyAfanasyev Жодної конкретної причини, окрім того, як я люблю це робити. Це дозволяє мені думати в відсотках, тому якби я міг зробити щось на зразок встановлення #a, flex-grow:10а потім я встановив би flex-grow: 90#b, щоб #a становив 10% від ширини рядка, а #b було б 90% від ширини рядка. Якщо жоден інший елемент не має стилю ширини, то технічно це не має значення, що ви ставите.
BT

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

28

Рішення Flexbox

Це те, для чого flex-growвластивість.

html, body {
  height: 100%;
}
body {
  display: flex;
}
.second {
  flex-grow: 1;
}
<div style="background: #bef;">Tree</div>
<div class="second" style="background: #ff9;">View</div>

Примітка. Додайте префікси flex постачальника, якщо цього вимагають підтримувані браузери .


27

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

Якби обидва стовпчики були фіксованої ширини, це було б легко.

Якби одна зі стовпців мала фіксовану ширину, це було б трохи важче, але цілком можливо.

Із змінною шириною обох стовпців IMHO потрібно просто використовувати таблицю з двома стовпцями.


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

1
Є кілька чуйних
Rikki

Зараз я схильний часто розробляти два окремі макети повністю і змінювати їх на мобільних пристроях, використовуючи медіа-запити, і display:none;при цьому максимально на 100% реагувати на розсувну шкалу, іноді приємніше повністю змінити дизайн для мобільного пристрою, використовуючи сенсорний екран і стиль кнопки.
Bysander

22

Перевірте це рішення

.container {
  width: 100%;
  height: 200px;
  background-color: green;
}
.sidebar {
  float: left;
  width: 200px;
  height: 200px;
  background-color: yellow;
}
.content {
  background-color: red;
  height: 200px;
  width: auto;
  margin-left: 200px;
}
.item {
  width: 25%;
  background-color: blue;
  float: left;
  color: white;
}
.clearfix {
  clear: both;
}
<div class="container">
  <div class="clearfix"></div>
  <div class="sidebar">width: 200px</div>

  <div class="content">
    <div class="item">25%</div>
    <div class="item">25%</div>
    <div class="item">25%</div>
    <div class="item">25%</div>
  </div>
</div>


2
Це, як правило, найкраще рішення, оскільки приховування переповнення не завжди бажане.
Джозеф Леннокс

3
За ОП: "Я хочу розкладку з двома стовпцями, де кожен може мати змінну ширину" У своїй відповіді ви повинні знати ширину першого стовпця, тому він не є змінним. Ви можете також встановити фіксовану ширину обох стовпців і просто плавати їх.
Яків Альварес

17

Використання calc:

.leftSide {
  float: left;
  width: 50px;
  background-color: green;
}
.rightSide {
  float: left;
  width: calc(100% - 50px);
  background-color: red;
}
<div style="width:200px">
  <div class="leftSide">a</div>
  <div class="rightSide">b</div>
</div>

Проблема в цьому полягає в тому, що всі ширини повинні бути чітко визначені, або як значення (px і em працюють добре), або як відсоток від чогось явно визначеного себе.


15

Тут це може допомогти ...

<html>

<head>
  <style type="text/css">
    div.box {
      background: #EEE;
      height: 100px;
      width: 500px;
    }
    div.left {
      background: #999;
      float: left;
      height: 100%;
      width: auto;
    }
    div.right {
      background: #666;
      height: 100%;
    }
    div.clear {
      clear: both;
      height: 1px;
      overflow: hidden;
      font-size: 0pt;
      margin-top: -1px;
    }
  </style>
</head>

<body>
  <div class="box">
    <div class="left">Tree</div>
    <div class="right">View</div>
    <div class="clear" />
  </div>
</body>

</html>


+1, тому що ваш приклад, здається, працює, але в моєму реальному сценарії дещо, як вміст з "view" переповзає на "дерево" div, оскільки дерево div не на 100%, може бути, що javascript змушує його бути невеликим і після висоти дерева Я бачу вміст перегляду
Anurag Uniyal

У такому випадку, якщо ви знаєте максимальну ширину лівого стовпця, ви можете або надати йому стиль max-width (не працює в IE), або подумати над полем margin (остерігайтеся помилок подвійної маржі на IE) або підкладка-зліва.
a6hi5h3k

Це було чудово! Я використовую це в <div class="clear" style="clear: both; height: 1px; overflow: hidden; font-size:0pt; margin-top: -1px;"></div>
прямому порядку

5

Я не розумію, чому люди готові настільки наполегливо працювати, щоб знайти чисте CSS рішення для простих стовпчастих макетів, які ТАКІ ЛЕГКІ, використовуючи старий TABLEтег.

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

<table WIDTH=100% border=0 cellspacing=0 cellpadding=2>
  <tr>
    <td WIDTH="1" NOWRAP bgcolor="#E0E0E0">Tree</td>
    <td bgcolor="#F0F0F0">View</td>
  </tr>
</table>

Набагато менш ризиковано і з точки зору сумісності між браузерами.


2
так, але якщо все робиться css, чому б це не зробити, принаймні цікавість, якщо це можливо?
Anurag Uniyal

2
Це тому, що якщо ви хочете media-queriesпоставити обидва стовпчики один над одним на невеликих пристроях, це неможливо зі старим tableтегом. Для цього потрібно застосувати CSSстилі таблиць. Отже, на сьогоднішній день краще вирішити це, CSSякщо ви хочете чуйний макет для будь-якого розміру екрана.
ElChiniNet

5

Якщо ширина іншого стовпця фіксована, як щодо використання функції calcCSS, яка працює для всіх звичайних браузерів :

width: calc(100% - 20px) /* 20px being the first column's width */

Таким чином буде обчислена ширина другого ряду (тобто ширина, що залишилася) та застосована відповідним чином.


Це найкраща відповідь, наскільки використовувати що - небудь інше , ніж Flexbox, як, наприклад, css-grid. Також працює, завдяки position: fixedчому все навколо ідеальний вибір! Дякую!
Bartekus

3

<html>

<head>
  <style type="text/css">
    div.box {
      background: #EEE;
      height: 100px;
      width: 500px;
    }
    div.left {
      background: #999;
      float: left;
      height: 100%;
      width: auto;
    }
    div.right {
      background: #666;
      height: 100%;
    }
    div.clear {
      clear: both;
      height: 1px;
      overflow: hidden;
      font-size: 0pt;
      margin-top: -1px;
    }
  </style>
</head>

<body>
  <div class="box">
    <div class="left">Tree</div>
    <div class="right">View</div>
    <div class="right">View</div>
    <div style="width: <=100% getTreeWidth()100 %>">Tree</div>
    <div class="clear" />
  </div>
  <div class="ColumnWrapper">
    <div class="Colum­nOne­Half">Tree</div>
    <div class="Colum­nOne­Half">View</div>
  </div>

</body>

</html>


Я хочу щось подібне до рядка стану з фіксованими елементами зліва, фіксованими елементами праворуч та одним рядком повідомлення, який використовує весь лівий пробіл. Я почав з цієї відповіді і додав своє повідомлення div ПІСЛЯ пливе з: висота: 20px; пробіл: nowrap; переповнення: приховано; переповнення тексту: кліп
englebart

3

Ви можете спробувати макет CSS Grid .

dl {
  display: grid;
  grid-template-columns: max-content auto;
}

dt {
  grid-column: 1;
}

dd {
  grid-column: 2;
  margin: 0;
  background-color: #ccc;
}
<dl>
  <dt>lorem ipsum</dt>
  <dd>dolor sit amet</dd>
  <dt>carpe</dt>
  <dd>diem</dd>
</dl>


2

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

Якщо для всіх елементів функція flex-нарахування встановлена ​​на 1, решта місця в контейнері буде розподілена однаково для всіх дітей. Якщо один з дітей має значення 2, решта місця займає вдвічі більше місця, ніж інші (або намагатиметься, принаймні). Детальніше дивіться тут

.parent {
  display: flex;
}

.child {
  flex-grow: 1; // It accepts a unitless value that serves as a proportion
}

.left {
  background: red;
}

.right {
  background: green;
}
<div class="parent"> 
  <div class="child left">
      Left 50%
  </div>
   <div class="child right">
      Right 50%
  </div>
</div>


1

Трохи інша реалізація,

Дві панелі розділення (вміст + додаткові), поруч, content panelрозширюються, якщо extra panelїх немає.

jsfiddle: http://jsfiddle.net/qLTMf/1722/


1

Пет - Ви праві. Ось чому це рішення задовольнило б і «динозаврів», і сучасників. :)

.btnCont {
  display: table-layout;
  width: 500px;
}

.txtCont {
  display: table-cell;
  width: 70%;
  max-width: 80%;
  min-width: 20%;
}

.subCont {
  display: table-cell;
  width: 30%;
  max-width: 80%;
  min-width: 20%;
}
<div class="btnCont">
  <div class="txtCont">
    Long text that will auto adjust as it grows. The best part is that the width of the container would not go beyond 500px!
  </div>
  <div class="subCont">
    This column as well as the entire container works like a table. Isn't Amazing!!!
  </div>
</div>


2
Немає HTML-посилання для класу css .ip, і воно не працює в IE7
Keith K

1

Ви можете використовувати CSS-бібліотеку W3, яка містить клас, який називається, restщо робить саме це:

<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

<div class="w3-row">
  <div class="w3-col " style="width:150px">
    <p>150px</p>
  </div>
  <div class="w3-rest w3-green">
    <p>w3-rest</p>
  </div>
</div>

Не забудьте прив’язати бібліотеку CSS до сторінки header:

<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

Ось офіційний демонстратор: W3 School Tryit Editor


Схоже, що це просто додає "переповнення: приховано", що робить гіршу версію вже відповіді
vpzomtrrfrt

0

Я не впевнений, що це відповідь, яку ви очікуєте, але чому б вам не встановити ширину дерева на "авто", а ширину "Перегляду" на 100%?


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

0

Погляньте на доступні рамки компонування CSS. Я б порекомендував Simpl або, трохи складніший, план Blueprint.

Якщо ви використовуєте Simpl (що включає імпорт лише одного файлу simpl.css ), ви можете зробити це:

<div class="Colum­nOne­Half">Tree</div>
<div class="Colum­nOne­Half">View</div>

, для макета 50-50, або:

<div class="Colum­nOne­Quarter">Tree</div>
<div class="Colum­nThreeQuarters">View</div>

, для 25-75.

Це так просто.


чи будуть обидва стовпчики змінної ширини?
Anurag Uniyal

0

Дякуємо за плагін Simpl.css!

не забудьте обернути всі свої стовпці ColumnWrapperтак.

<div class="ColumnWrapper">
    <div class="Colum­nOne­Half">Tree</div>
    <div class="Colum­nOne­Half">View</div>
</div>

Я збираюся випустити версію 1.0 Simpl.css, тому допоможіть поширити слово!


0

Я написав функцію javascript, яку дзвоню з jQuery $ (document) .ready (). Це дозволить проаналізувати всіх дітей батьківського діва та оновить лише найбільшу дитину.

html

...
<div class="stretch">
<div style="padding-left: 5px; padding-right: 5px; display: inline-block;">Some text
</div>
<div class="underline" style="display: inline-block;">Some other text
</div>
</div>
....

javascript

$(document).ready(function(){
    stretchDivs();
});

function stretchDivs() {
    // loop thru each <div> that has class='stretch'
    $("div.stretch").each(function(){
        // get the inner width of this <div> that has class='stretch'
        var totalW = parseInt($(this).css("width"));
        // loop thru each child node
        $(this).children().each(function(){
            // subtract the margins, borders and padding
            totalW -= (parseInt($(this).css("margin-left")) 
                     + parseInt($(this).css("border-left-width")) 
                     + parseInt($(this).css("padding-left"))
                     + parseInt($(this).css("margin-right")) 
                     + parseInt($(this).css("border-right-width")) 
                     + parseInt($(this).css("padding-right")));
            // if this is the last child, we can set its width
            if ($(this).is(":last-child")) {
                $(this).css("width","" + (totalW - 1 /* fudge factor */) + "px");
            } else {
                // this is not the last child, so subtract its width too
                totalW -= parseInt($(this).css("width"));
            }
        });
    });
}

0

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

Я розробив безкоштовний інструмент для розуміння та розробки макетів за допомогою флекси. Перевірте це тут: http://algid.com/Flex-Designer

.container{
    height:180px;
    border:3px solid #00f;
    display:flex;
    align-items:stretch;
}
div {
    display:flex;
    border:3px solid #0f0;
}
.second {
    display:flex;
    flex-grow:1;
    border:3px solid #f00;
}
<div class="container">
    <div>Tree</div>
    <div class="second">View</div>
</div>


Ви читали ВСІ попередні відповіді, перш ніж додавати свої? здається, ні ...
Темані Афіф

як бічну зауваження, вам не потрібно додавати, stretchтому що це значення за замовчуванням і не потрібно робити дочірній елемент flex контейнером, так що display:flexмарно для внутрішніх елементів
Temani Afif

Цікаво, чому голосування без жодних коментарів. Чи не ця відповідь відповідає на запитання? Чому? Якщо намагаюся допомогти іншим, буде покарано, я подумаю двічі до наступної відповіді,
Маріо Васкес,

1
Ви отримали два коментарі після голосування, це недостатньо?
Темані Афіф

Темарі, ти перевірив мій інструмент? Ви не вважаєте, що це корисно і може допомогти іншим? Як ви думаєте, це не пов’язано з питанням? Де ваша відповідь на це питання? Я не бачу цього. Яка тут ваша роль?
Маріо Васкес

-3

Якщо обидві ширини мають різну довжину, чому б ви не обчислили ширину за допомогою якогось сценарію чи стороні сервера?

<div style="width: <=% getTreeWidth() %>">Tree</div>

<div style="width: <=% getViewWidth() %>">View</div>

3
Як сервер знає, як працює механізм компонування клієнта?
Кев

Просто: розробіть його для 90% веб-переглядачів :) IE 7+, FF3 + та Safari підтримують CSS 3. Ви також можете включити стандартний елемент IE6 <! - [if lte IE 6]>. До речі, який браузер не підтримує style = "width:%" ??
amischiefr

Я не знаю, як це можна зробити на стороні сервера, але так, якийсь javscript може це зробити, але я хочу його уникнути, якщо css / html не зможе цього зробити
Anurag Uniyal,

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