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:
According to the HTML spec, browsers must wrap the
elements inside a element if there isn't any:
The height of that will be the height of all rows. However, the height of the
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
now participates in a flex layout, not a table layout. Since the is a table-row-group element whose parent is neither a table nor inline-table (it's a flex), an anonymous table parent is generated.
So now we have a
which is a flex container with a single flex line, and which contains a single flex item (the anonymous table).
The height of the flex line will be the height of the flex container (spec):
If the flex container is single-line and has a definite cross
size, the cross size of the flex line is the flex container’s inner
cross size.
And then you use align-items: center. That will align vertically the anonymous table (together with the ) 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:
Prior to alignment via justify-content and align-self,
any positive free space is distributed to auto margins in that
dimension.
Note the difference: auto margins only distribute positive free space, not negative one.
Therefore, we only have to style the flex item with
margin: auto 0; /* Push to the center (vertically) */
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 . Then, it won't be wrapped in any anonymous table element, so it will be a flex item and the alignment will work.
Note this won't break the table, because the bunch of
s, which are table-rows, will generate an anonymous table parent, but now inside the :
So you can use this code:
tbody {
display: block; /* Disable tabular layout, and make a flex item */
margin: auto 0; /* Push to the center (vertically) */
}
#container {
height: 180px;
display: flex;
flex-flow: row;
align-items: stretch;
border: 1px dashed gray;
}
table {
display: flex;
flex-flow: row;
margin: 10px;
overflow: scroll;
border: 1px dashed blue;
}
tbody {
display: block; /* Disable tabular layout, and make a flex item */
margin: auto 0; /* Push to the center (vertically) */
}
td {
height: 10px;
width: 100px;
border: 1px solid red;
}
#container div {
flex: 1;
margin: 10px;
border: 1px dashed red;
}