Flex items overlapping in Chrome and IE11

被刻印的时光 ゝ 提交于 2020-01-11 05:25:21

问题


I'm trying to create a flexbox layout of fixed height which scrolls the inner content when the inner content is too large.

Additionally if the content doesn't cause scrolling I want to fix a div with buttons to the bottom of the container.

I have a layout which works perfectly in Firefox but in Chrome it causes the bottom button div to clip on top of the content when it's large enough to cause scrolling.

This is the layout rendering properly in Firefox:

This is how it renders improperly in Chrome:

Additionally, this is how it should behave if there's not enough inner content to cause scrolling:

.container {
  height: 150px;
  width: 300px;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  border: 1px solid #000;
  padding: 4px;
}

.options {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

.spacer {
  flex: 1 1 auto;
}

.buttons {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
}
<div class="container">

  <div class="options">
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
  </div>

  <div class="spacer"></div>

  <div class="buttons">
    <input type="button" value="Cancel">
    <input type="button" value="Save">
  </div>

</div>

https://jsfiddle.net/tdghqyuu/1/


回答1:


Solution

Add this to your code:

.container > * {
  flex-shrink: 0; 
}

Explanation

An initial setting on flex items, according to the flexbox specification, should be flex-shrink: 1. This means that flex items are permitted to shrink in order to avoid overflowing the container.

Chrome and IE11 appear to be adhering to this guideline.

Other browsers, such as Firefox, Edge and Safari, seem to have flex-shrink set to 0 by default.

On the other hand, this may have little or nothing to do with flex-shrink. The problem may relate to the default min-height and min-width settings on flex items. (See here: Why don't flex items shrink past content size?)

Or maybe it's a combination of both. It really depends on the browser.

The fact is, browser implementations vary. That's why you have to test.

Spec initial settings are not entirely reliable because

  1. browsers represent independent entities that can do whatever they want, and
  2. the use of "interventions".

Interventions

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

In other words, a browser takes it upon itself to provide settings that it feels are best for its users, regardless of spec guidelines.

Chrome seems to do this a lot. Here are some examples:

  • Why don't flex items shrink past content size? (see browser rendering notes)
  • pseudo element not aligning at top left corner
  • Google Chrome viewport-anchored expand direction with flexbox
  • How to make images stay within the rows of a css grid container?
  • Why are percentage heights working on children when the parent has no height defined?

One thing appears certain: If you disable flex-shrink, your layout then works across all browsers. Add this to your code:

.container > * {
  flex-shrink: 0; 
}

.container>* {
  flex-shrink: 0;
}

.container {
  height: 150px;
  width: 300px;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  border: 1px solid #000;
  padding: 4px;
}

.options {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

.buttons {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  margin-top: 10px;
  /* new; for demo only */
}
<div class="container">

  <div class="options">
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
  </div>

  <div class="buttons">
    <input type="button" value="Cancel">
    <input type="button" value="Save">
  </div>

</div>

You may also want to consider moving the scrollbar to the options box only, then you've truly fixed the buttons to the bottom of the screen. Make this adjustment to your code:

.container {
  height: 150px;
  width: 300px;
  display: flex;
  flex-direction: column;
  /* overflow-y: auto; */
  border: 1px solid #000;
  padding: 4px;
}

.options {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  overflow-y: auto; /* NEW */
  flex: 1;          /* NEW; may be necessary for overflow to work in some browsers */

}

.container > * {
  flex-shrink: 0;
}

.container {
  height: 150px;
  width: 300px;
  display: flex;
  flex-direction: column;
  /* overflow-y: auto; */
  border: 1px solid #000;
  padding: 4px;
}

.options {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  overflow-y: auto; /* NEW */
  flex: 1;          /* NEW; may be necessary for overflow to work in some browsers */
}

.buttons {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  margin-top: 10px; /* new; for demo only */
}
<div class="container">

  <div class="options">
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
    <div class="option">
      <input type="checkbox"> Option
    </div>
  </div>

  <div class="buttons">
    <input type="button" value="Cancel">
    <input type="button" value="Save">
  </div>

</div>

Also, I removed the spacer element you had. It doesn't seem necessary when there are a multitude of clean ways to create space between items in a flex container.




回答2:


.container doesn't need to be "flex", a min-height property for .options may be enough:

        .container {
            height: 150px;
            width: 300px;
            /*display: flex;*/
            flex-direction: column;
            overflow-y: auto;
            border: 1px solid #000;
            padding: 4px;
        }

        .options {
            display: flex;
            flex-direction: row;
            flex-wrap: wrap;
            min-height: 125px;
        }

        .options > div
        {
            display: inline-block;
        }

        .spacer {
            flex: 1 1 auto;
        }

        .buttons {
            display: flex;
            flex-direction: row;
            justify-content: space-between;
        }
<div class="container">

        <div class="options">
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
            <div class="option">
                <input type="checkbox"> Option
            </div>
        </div>

        <div class="spacer"></div>

        <div class="buttons">
            <input type="button" value="Cancel">
            <input type="button" value="Save">
        </div>

    </div>



回答3:


This has actually nothing to do with flex. What you see is the options overflowing it's container (the <div class="options"> element). The element itself has the correct size, but the container itself is fixed height. If you add overflow: hidden or overflow: scroll to .options, it will render as you expect (although you might not want the scrollbar there).



来源:https://stackoverflow.com/questions/48294014/flex-items-overlapping-in-chrome-and-ie11

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!