3

I was reading How are `display: table-cell` widths calculated? and bootstrap input groups. Consider the following example

https://jsfiddle.net/kb23jLL3/

<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<form class="bs-example bs-example-form" data-example-id="simple-input-groups">
  <div class="input-group">
    <div class="input-group-addon" id="basic-addon1">@</div>
    <div class="form-control" placeholder="Username" aria-describedby="basic-addon1"> </div>
  </div>  
</form>

The .form-control has width 100% but it grows only to take the available width in the congaing table. So far so good. So I expect .form-control to never grow beyond the limits of containing table. But if I give width more than 100% then it grows out of the containing table's boundaries and if I give width less than 100% then it doesn't take the available space. E.g. 100% + case:

https://jsfiddle.net/kb23jLL3/1/

.input-group .form-control {
  width: 110%;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<form class="bs-example bs-example-form" data-example-id="simple-input-groups">
  <div class="input-group">
    <div class="input-group-addon" id="basic-addon1">@</div>
    <div class="form-control" placeholder="Username" aria-describedby="basic-addon1"> </div>
  </div>  
</form>

You can see the horizontal scroll bar now appearing. Similarly consider the following example where I give width less than 100%:

https://jsfiddle.net/kb23jLL3/2/

.input-group .form-control {
  width: 90%;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<form class="bs-example bs-example-form" data-example-id="simple-input-groups">
  <div class="input-group">
    <div class="input-group-addon" id="basic-addon1">@</div>
    <div class="form-control" placeholder="Username" aria-describedby="basic-addon1"> </div>
  </div>  
</form>

Why does 100% width on table-cell mean the available width? Should 100% width mean to take 100% of the containing element?Please provide some reference which mentions this behavior.

Community
  • 1
  • 1
user31782
  • 7,087
  • 14
  • 68
  • 143
  • 1
    http://stackoverflow.com/questions/21130221/how-are-display-table-cell-widths-calculated – Daniel Nov 30 '16 at 16:10
  • @Daniel That is the same question I linked at the beginning of my question. – user31782 Nov 30 '16 at 16:16
  • You should envision a table row. The table cells fill a table row up to 100%. If you have another table-cell within that row an it has a set limited width, then the remainder width is for the second table-cell in your example. Because a `table-cell` has a standard behavior to collapse to its content, you need to force it to stretch to 100% to fill the containing element. – Daniel Nov 30 '16 at 17:03
  • @Daniel Is the table cell with 100% width encompassed by a virtual `tr`? And does the `td` takes 100% of that virtual `tr`'s width? – user31782 Nov 30 '16 at 17:08
  • When you give an element `display: table-cell` the browser creates anonymous objects for the `table` and `tr`, and since there is no actual rule for how those gets their default property values, each browser does its own interpretation, hence very unpredictable render result. W3C: https://www.w3.org/TR/REC-CSS2/tables.html#anonymous-boxes – Asons Nov 30 '16 at 20:39
  • @LGSon But this behavior is consistent across all browsers. And if `table-cell` automatically generates `tr` then the `tr` must encompass both `td`'s Then `tr` must have width same as `table` and width 100% on `td` must mean to make it as wide as the table but in the current scenario 100% on `td` means 100% of the available width. – user31782 Dec 01 '16 at 06:43
  • I have come across an instance where the behavior was odd. IE and early Firefox browser. Had to hack my way around it. But the current latest browsers seem more consistent. – Daniel Dec 01 '16 at 16:28
  • The behavior _can_ be consistent, the interpretation though, is still browser dependent. That being said, the first link in your question has the answer to the very same, and what makes your demo code not behave as a normal cell should, is the float, which breaks a cells normal behavior, hence the different result. – Asons Dec 01 '16 at 17:37

1 Answers1

2

Bootstrap applies a float property to the .input-group .form-control class. This is the second table-cell in the examples.

I have made an example where the first two examples do not have the float property and the next two examples do. The float property takes an element out of the document flow. That is the reason it is able to extend the containing element. The last example is without the float property and a width set to less than 100% on the second table-cell. Part from some other styling that bootstrap applies, the effect can be seen in the snippet.

example1: no float width 100%

example2: no float, width 200%

example3: float left, width 100%

example4: float left, width 200%

example5: no float, width 50%

In example 5 the table-cell follows the rules for a table. This means that the table cells fill the parent container input group to 100%, even when the width of the table cells are set different. The last table-cell will fill the remainder.

note: the parent container of the table cells (input.group) is set to a static value to facilitate the examples. Bootstrap does not add a width to that element, which makes it render to 100% of its parent element.

* {
  box-sizing: border-box;
}
.input-group {
  border-collapse: separate;
  display: table;
  position: relative;
  background: #ccc;
  padding: 5px;
  margin-bottom: 20px;
  /* relative elements render to 100% width when width is not set explicity. For the example the width is limited to 80%. */
  width: 80%;
}
.addon {
  position: relative;
  display: table-cell;
  background: #559;
  padding: 5px 6px;
  white-space: nowrap;
  width: 1%;
}
.cell1 {
  position: relative;
  display: table-cell;
  background: #595;
  padding: 5px;
  width: 100%;
  /* float: left;*/
}
.cell2 {
  position: relative;
  display: table-cell;
  background: #595;
  padding: 5px;
  width: 200%;
  /* float: left;*/
}
.cell3 {
  position: relative;
  display: table-cell;
  background: #955;
  padding: 5px;
  width: 100%;
  float: left;
}
.cell4 {
  position: relative;
  display: table-cell;
  background: #955;
  padding: 5px;
  width: 200%;
  float: left;
}
.cell5 {
  position: relative;
  display: table-cell;
  background: #995;
  padding: 5px;
  width: 50%;
  /* float: left;*/
}
.cell6 {
  position: relative;
  display: table-cell;
  background: #995;
  padding: 5px;
  width: 50%;
  float: left;
}
<!-- example 1 | no float cell 100% -->
<div class='input-group'>
  <div class='addon'>@</div>
  <div class='cell1'>no float, width 100%</div>
</div>

<!-- example 2 | no float cell 200% -->
<div class='input-group'>
  <div class='addon'>@</div>
  <div class='cell2'>no float, width 200%</div>
</div>


<!-- example 3 | float cell 100% -->
<div class='input-group'>
  <div class='addon'>@</div>
  <div class='cell3'>float left, width 100%</div>
</div>

<!-- example 4 | float cell 200% -->
<div class='input-group'>
  <div class='addon'>@</div>
  <div class='cell4'>float left, width 200%</div>
</div>

<!-- example 5 |  cell 50% -->
<div class='input-group'>
  <div class='addon'>@</div>
  <div class='cell5'>no float, width 50% (fills remainder 'table' width)</div>
</div>

<!-- example 6 |  cell 50% -->
<div class='input-group'>
  <div class='addon'>@</div>
  <div class='cell6'>float left, width 50% (sizes to 50% of available space)</div>
</div>
Daniel
  • 4,816
  • 3
  • 27
  • 31
  • I have a lot of confusions. 1. Why does `float` property allow it to go out of it's containing element? A div can go out of it's container even if it is not floated. 2. With `float` applied to `td` not only it can out of it's container but it will shrink too with width less than 100%; shrinking is not possible without `float`, why? – user31782 Dec 01 '16 at 06:39
  • The basic table tag is `input-group`. This is a div with position relative and no width. The standard behavior will make it span to 100%. The table cells within must fill this space. It is standard browser behavior of a table. I added it in the example. – Daniel Dec 01 '16 at 14:46
  • I still don't understand. By assigning `float` to `cell` and width 50% why doesn't it fill the available space? Doesn't it act no more like a `table-cell`? If yes then why does 100% on cell make it span the 100% of available width? If it it isn't a table-cell anymore then 100% width on it should mean to take 100% width of its container. – user31782 Dec 02 '16 at 07:12
  • Well... It is still a `display:table-cell` as property value. Nothing changed other than adding a float property. It still knows that 100% is the remainder space of the parent container, but the float allows you to visually size it smaller or larger. Browser behavior. – Daniel Dec 02 '16 at 23:43
  • It is a browser behavior only (although consistent cross browser)? I thought `float` was _defined_ to make this behavior. Also I think float doesn't take the element completely out of the flow because it still respects text. I also read somewhere that applying float makes `display: block` automatically. – user31782 Dec 03 '16 at 05:06
  • if you're very much interested in the browser behavior on element, I recommend W3org. There is a lot to say about behavior of elements. I just pointed out that the float property is responsible for the change in behavior. The float property collapses to content, unless a specific width is given. As a table cell the value of 100% fills the remainder of the parent element. the different examples OI made show you insight on the behavior. i hope that helps you. – Daniel Dec 03 '16 at 07:12
  • Yes you are right. float property on div collapses the div to contain only it's content when width is auto. – user31782 Dec 03 '16 at 08:08