Reputation: 7323
I'm using flexbox to display a text label along with a numeric value in a narrow column, so that the text is truncated with ellipsis if it doesn't fit.
It worked fine, until I had the need to place the entire column in a table-cell - at which point the browser (Chrome) just ignored the column width and made the table wide enough to fit all the text.
Here's the label layout:
<div class="line">
<span>Very long label text</span>
<span>12345</span>
</div>
.line {
display: flex;
width: 100%;
}
.line span:first-child {
white-space: nowrap;
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.line span:last-child {
flex-shrink: 0;
margin-left: 5px;
}
Placing it in a regular div with a fixed width works as expected. Placing it in a table-cell doesn't:
Fiddle: http://jsfiddle.net/98o7m7am/
.wrapper {
width: 150px;
}
.table {
display: table;
}
.table > div {
display: table-cell;
}
.line {
display: flex;
width: 100%;
}
.line span:first-child {
white-space: nowrap;
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.line span:last-child {
flex-shrink: 0;
margin-left: 5px;
}
<div class="wrapper">
<div class="line">
<span>Very long label text</span>
<span>12345</span>
</div>
</div>
<div class="table wrapper">
<div>
<div class="line">
<span>Very long label text</span>
<span>12345</span>
</div>
</div>
</div>
Update: I ended up 'solving' this by using more flexboxes instead of tables, but I would still like to know why the original example doesn't work.
Upvotes: 6
Views: 11849
Reputation: 288480
That's because, by default, tables use the automatic table layout:
The CSS 2.1 spec doesn't define that layout mode, but suggests a (non-normative) algorithm, which reflects the behavior of several popular HTML user agents.
According to that algorithm, the table's width
will only be treated like a minimum width, and the real width will be enough so that the content does not overflow:
Calculate the minimum content width (MCW) of each cell: the formatted content may span any number of lines but may not overflow the cell box.
Since you have white-space: nowrap
, the MCW will be the width of the full text.
To avoid that, you can set the initial width of your first span to 0:
.line span:first-child {
width: 0;
}
.wrapper {
width: 150px;
}
.table {
display: table;
}
.table > div {
display: table-cell;
}
.line {
display: flex;
width: 100%;
}
.line span:first-child {
width: 0;
white-space: nowrap;
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.line span:last-child {
flex-shrink: 0;
margin-left: 5px;
}
<div class="wrapper">
<div class="line">
<span>Very long label text</span>
<span>12345</span>
</div>
</div>
<div class="table wrapper">
<div>
<div class="line">
<span>Very long label text</span>
<span>12345</span>
</div>
</div>
</div>
Alternatively, you may want to try the fixed table mode, which is properly defined in the spec (and thus more reliable), is usually faster, and solves the problem too.
table-layout: fixed;
.wrapper {
width: 150px;
}
.table {
display: table;
table-layout: fixed;
}
.table > div {
display: table-cell;
}
.line {
display: flex;
width: 100%;
}
.line span:first-child {
white-space: nowrap;
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
}
.line span:last-child {
flex-shrink: 0;
margin-left: 5px;
}
<div class="wrapper">
<div class="line">
<span>Very long label text</span>
<span>12345</span>
</div>
</div>
<div class="table wrapper">
<div>
<div class="line">
<span>Very long label text</span>
<span>12345</span>
</div>
</div>
</div>
Upvotes: 18