Prevent flex item from exceeding parent height and make scroll bar work

后端 未结 2 478
梦谈多话
梦谈多话 2020-11-28 14:47

How can I prevent a child div with scrollbars and flex:1 from exceeding the height of its parent flexbox in Firefox? It works correctly in Chrome.

CodeP

相关标签:
2条回答
  • 2020-11-28 15:24

    I am marking Michael_B's answer as the correct one, since it is a valid solution along with an explanation. In addition here is another solution I came up with, which does not require modifying the flex-basis:

    #messagescontainerrow {
            flex: 1;
    
            min-height: 0;   /* ADDED THIS. */
    
            border: 5px double black;
        }
    
    #leftdiv {
            display:flex;
            flex-direction:column;
    
            max-height: 100%; /* ADDED THIS */
    
            border: 1px solid green;
        }
    
    #rightdiv {
            display:flex;
            flex-direction:column;
    
            max-height: 100%; /* ADDED THIS */
    
            border: 1px solid blue;
        }
    

    Explanation:

    As per the current Flexbox specification https://www.w3.org/TR/css-flexbox-1/#min-size-auto

    In general, the automatic minimum size of a flex item is the smaller of its content size and its specified size. However, if the box has an aspect ratio and no specified size, its automatic minimum size is the smaller of its content size and its transferred size. If the box has neither a specified size nor an aspect ratio, its automatic minimum size is the content size.

    So, by default #messagescontainerrow was taking on a minimum height based on its contents, rather than respecting the height of its parent flexbox. This behavior can be overridden by setting min-height:0.

    By making this change one sees what is displayed in the following image; note that @messagescontainerrow - the one with the double line border - is now the same height as its parent - the one with the purple dashed border.

    (Note that the more recent draft specification, found here - https://drafts.csswg.org/css-flexbox/#min-size-auto - says "for scroll containers the automatic minimum size is zero". So in future we might not need to do this).

    What remains now is the issue of its children, #leftdiv and #rightdiv, overflowing its borders. As Michael_B pointed out, overflow requires a height or max-height property to be present. So the next step is to add max-height: 100% to both #leftdiv and #rightdiv, so that the overflow-y:scroll property of their children gets triggered.

    Here is the result:

    0 讨论(0)
  • 2020-11-28 15:25

    Short Answer

    Instead of flex: 1, use flex: 1 1 1px.

    Make these two adjustments in your code:

    #messagelist {
            /* flex:1; */
            flex: 1 1 1px; /* new */
        }
    
    #messagecontents {
            /* flex:1; */
            flex: 1 1 1px; /* new */
        }
    

    revised codepen


    Explanation

    In most cases, as you have noted, adding min-height: 0 to flex items in a column-direction container is enough to correct the problem.

    In this case, however, there's an additional obstacle: flex-basis.

    You're applying the following rule to flex items #messagelist and #messagecontents: flex: 1.

    This is a shorthand rule that breaks down to:

    • flex-grow: 1
    • flex-shrink: 1
    • flex-basis: 0

    (source: https://www.w3.org/TR/css-flexbox-1/#flex-common)


    2019 UPDATE: Since the posting of this answer in 2018, it appears that Chrome's behavior has changed and is now uniform with Firefox and Edge. Please keep that in mind as you read the rest of this answer.


    In Chrome, flex-basis: 0 is enough to trigger an overflow, which generates the scrollbars. (2019 update: This may no longer be the case.)

    In Firefox and Edge, however, a zero flex-basis is insufficient. This is probably the more correct behavior in terms of standards compliance as MDN states:

    In order for overflow to have an effect, the block-level container must have either a set height (height or max-height) or white-space set to nowrap.

    Well, flex-basis: 0 meets none of those conditions, so an overflow condition should not occur. Chrome has probably engaged in an intervention (as they often do).

    An intervention is when a user agent decides to deviate slightly from a standardized behavior in order to provide a greatly enhanced user experience.

    To meet the "standardized behavior", which would enable an overflow to occur in Firefox and Edge, give flex-basis a fixed height (even if it's just 1px).

    0 讨论(0)
提交回复
热议问题