I have a table with the display: flex
property, whose cells will be centered vertically. When there are more cells than the table can show, the overflow: scroll
property doesn't take the top ones into account.
In the sample code below, the scroll stops at the letter K when it should go all the way up to the letter A. What is causing this?
#container {
height: 180px;
display: flex;
flex-flow: row;
align-items: stretch;
border: 1px dashed gray;
}
table {
display: flex;
flex-flow: row;
align-items: center;
margin: 10px;
overflow: scroll;
border: 1px dashed blue;
}
td {
height: 10px;
width: 100px;
border: 1px solid red;
}
#container div {
flex: 1;
margin: 10px;
border: 1px dashed red;
}
<div id="container">
<table>
<tr><td>A</td></tr>
<tr><td>B</td></tr>
<tr><td>C</td></tr>
<tr><td>D</td></tr>
<tr><td>E</td></tr>
<tr><td>F</td></tr>
<tr><td>G</td></tr>
<tr><td>H</td></tr>
<tr><td>I</td></tr>
<tr><td>J</td></tr>
<tr><td>K</td></tr>
<tr><td>L</td></tr>
<tr><td>M</td></tr>
<tr><td>N</td></tr>
<tr><td>O</td></tr>
<tr><td>P</td></tr>
<tr><td>Q</td></tr>
<tr><td>R</td></tr>
<tr><td>S</td></tr>
<tr><td>T</td></tr>
<tr><td>U</td></tr>
<tr><td>V</td></tr>
<tr><td>W</td></tr>
<tr><td>X</td></tr>
<tr><td>Y</td></tr>
<tr><td>Z</td></tr>
</table>
<table>
<tr><td>A</td></tr>
<tr><td>B</td></tr>
<tr><td>C</td></tr>
</table>
<div></div>
</div>
According to the HTML spec, browsers must wrap the
<tr>
elements inside a<tbody>
element if there isn't any:The height of that
<tbody>
will be the height of all rows. However, the height of the<table>
can be smaller. That wouldn't be a problem in a table layout, because the height of the table would be treated as a minimum height.However, the
<table>
now participates in a flex layout, not a table layout. Since the<tbody>
is atable-row-group
element whose parent is neither atable
norinline-table
(it's aflex
), an anonymoustable
parent is generated.So now we have a
<table>
which is a flex container with a single flex line, and which contains a single flex item (the anonymoustable
).The height of the flex line will be the height of the flex container (spec):
And then you use
align-items: center
. That will align vertically the anonymoustable
(together with the<tbody>
) at the middle of the flex line, even if it overflows above or below.The problem is that scrollbars allow scrolling to see the content that overflows below, but not the content that overflows above.
Therefore, instead of
align-items: center
, I suggest aligning with auto margins:Note the difference: auto margins only distribute positive free space, not negative one.
Therefore, we only have to style the flex item with
But there is a problem: as explained above, the flex item is an anonymous generated element, so we can't select it with CSS selectors.
To solve that, we can add
display: block
to the<tbody>
. Then, it won't be wrapped in any anonymoustable
element, so it will be a flex item and the alignment will work.Note this won't break the table, because the bunch of
<tr>
s, which aretable-row
s, will generate an anonymoustable
parent, but now inside the<tbody>
:So you can use this code: