Setting overflow: scroll on a table with display: flex

前端 未结 2 1843
一整个雨季
一整个雨季 2021-01-06 23:54

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:

2条回答
  •  野趣味
    野趣味 (楼主)
    2021-01-07 00:04

    According to the HTML spec, browsers must wrap the elements inside a element if there isn't any:

    <tbody> is inserted inside <table> (http://jsfiddle.net/ed9msnfp/)

    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.

    The <tbody> is wrapped in an anonymous table (http://jsfiddle.net/1wf1hu0d/)

    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 :

    An anonymous table is generated inside <tbody> (http://jsfiddle.net/bvjvd30u/)

    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; }
    A
    B
    C
    D
    E
    F
    G
    H
    I
    J
    K
    L
    M
    N
    O
    P
    Q
    R
    S
    T
    U
    V
    W
    X
    Y
    Z
    A
    B
    C

提交回复
热议问题