Flexbox子级具有“溢出:隐藏”的祖父母边距

Hyb*_*ore 16 html css overflow flexbox

我正在尝试在包装器中嵌套两个子元素,该包装器指定侧边距,以便当显示狭窄时在其内容和屏幕侧面之间有一个空间,max-width而当显示较宽时则用于一个。

第二个孩子会有一些溢出,这应该是可见的,而第一个孩子应该严格位于包装器的内容框中。在删除第一个孩子的情况下,第二个孩子的行为符合预期。但是,当我添加第一个孩子时,它似乎完全忽略了包装器的边距,拉伸了包装器的内容框,并破坏了第二个孩子。

应用于overflow: hidden包装程序可以解决页边距问题,但可以裁剪第二个孩子。将边距应用于第一个孩子并不会使其与父对象一起折叠,因为它处于新的块格式上下文中。

到目前为止,我发现的唯一解决方法是:

.wrapper {
    > * {
        margin-left: 1.5rem;
        margin-right: 1.5rem;
    }
}
Run Code Online (Sandbox Code Playgroud)

并将包装器的最大宽度增加3rem,但我希望有一些解决方案不需要我将包装器的边距转移到其子级。

https://codepen.io/HybridCore/pen/jjoWmd

.wrapper {
    > * {
        margin-left: 1.5rem;
        margin-right: 1.5rem;
    }
}
Run Code Online (Sandbox Code Playgroud)
body {
  background-color: #000;
  color: #FFF;
  display: flex;
  justify-content: center;
}

.wrapper {
  margin: 0 1.5rem;
  max-width: 40rem;
  width: 100%;
}

.fit_content_box {
  display: flex;
  align-items: center;
}

.L {
  min-width: 0;
  flex: 1 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.R {
  margin-left: 1rem;
  height: 1rem;
  width: 1rem;
  background-color: #FFF;
}

.overflow {
  display: flex;
  justify-content: space-between;
}

.overflow>div {
  width: 0;
  display: flex;
  justify-content: center;
}
Run Code Online (Sandbox Code Playgroud)

Tem*_*fif 6

You mainly have two issues:

  1. You are setting width:100% to the wrapper and this doesn't account for margin so you will logically have overflow and since the body is a flex container with justify-content:center the margin will overflow equally from both sides that's why you think it's not applied.
  2. You are facing the min-width constraint of flexbox which is forcing you to set width:100% thinking it's the good solution. This same constraint is also preventing the element from shrinking lower than the 100% you specified (related: Why is a flex item limited to parent size?)

To fix this you need to remove width:100% from wrapper and consider min-width:0 instead. You can also remove the min-width applied to .L and you need to consider flex-shrink:0 on .R (or replace its width by min-width)

body {
  background-color: #000;
  color: #FFF;
  display: flex;
  justify-content: center;
}

.wrapper {
  margin: 0 1.5rem;
  max-width: 40rem;
  min-width:0;
}

.fit_content_box {
  display: flex;
  align-items: center;
}

.L {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.R {
  margin-left: 1rem;
  flex-shrink:0;
  height: 1rem;
  width: 1rem;
  background-color: #FFF;
}

.overflow {
  display: flex;
  justify-content: space-between;
}

.overflow>div {
  width: 0;
  display: flex;
  justify-content: center;
}
Run Code Online (Sandbox Code Playgroud)
<body>
  <div class="wrapper">
    <div class="fit_content_box">
      <p class="L">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
        dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

      <div class="R"></div>
    </div>

    <div class="overflow">
      <div>
        <p>0</p>
      </div>
      <div>
        <p>12</p>
      </div>
      <div>
        <p>24</p>
      </div>
    </div>
  </div>
</body>
Run Code Online (Sandbox Code Playgroud)

If you want the element to remain at least equal to max-width when there is a small amount of text add flex-grow:1:

body {
  background-color: #000;
  color: #FFF;
  display: flex;
  justify-content: center;
}

.wrapper {
  margin: 0 1.5rem;
  max-width: 40rem;
  min-width:0;
  flex-grow:1;
}

.fit_content_box {
  display: flex;
  align-items: center;
}

.L {
  flex-grow:1;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.R {
  margin-left: 1rem;
  flex-shrink:0;
  height: 1rem;
  width: 1rem;
  background-color: #FFF;
}

.overflow {
  display: flex;
  justify-content: space-between;
}

.overflow>div {
  width: 0;
  display: flex;
  justify-content: center;
}
Run Code Online (Sandbox Code Playgroud)
<body>
  <div class="wrapper">
    <div class="fit_content_box">
      <p class="L">Lorem ipsum dolor sit e dolor sit e</p>

      <div class="R"></div>
    </div>

    <div class="overflow">
      <div>
        <p>0</p>
      </div>
      <div>
        <p>12</p>
      </div>
      <div>
        <p>24</p>
      </div>
    </div>
  </div>
</body>
Run Code Online (Sandbox Code Playgroud)


To better illustrate the (1) here is another example with overflowing margin that you can hardly notice:

.container {
  width:200px;
  margin:auto;
  display:flex;
  justify-content:center;
}
.box {
  height:50px;
  width:100%;
  background:red;
}
Run Code Online (Sandbox Code Playgroud)
<div class="container">
  <div class="box" style="margin:0 5966px">a_long_text_to_avoid_the_shrink</div>
</div>

<div class="container">
  <div class="box">a_long_text_to_avoid_the_shrink</div>
</div>
Run Code Online (Sandbox Code Playgroud)

You can see that we have a long text forcing our element to not shrink (the min-width constraint), the element is taking full width and we are centring the content. This will make the margin overflowing like if there is no margin.

If you break one rule then you will see the effect of the margin.

Remove the long text:

.container {
  width:200px;
  margin:auto;
  display:flex;
  justify-content:center;
}
.box {
  width:100%;
  height:50px;
  background:red;
}
Run Code Online (Sandbox Code Playgroud)
<div class="container">
  <div class="box" style="margin:0 5966px">a long text to avoid the shrink</div>
</div>

<div class="container">
  <div class="box">a long text to avoid the shrink</div>
</div>
Run Code Online (Sandbox Code Playgroud)

Remove the centring:

.container {
  width:200px;
  margin:auto;
  display:flex;
}
.box {
  width:100%;
  height:50px;
  background:red;
}
Run Code Online (Sandbox Code Playgroud)
<div class="container">
  <div class="box" style="margin:0 5966px">a_long_text_to_avoid_the_shrink</div>
</div>

<div class="container">
  <div class="box">a_long_text_to_avoid_the_shrink</div>
</div>
Run Code Online (Sandbox Code Playgroud)

Make a different margin on each side

.container {
  width:200px;
  margin:auto;
  display:flex;
  justify-content:center;
}
.box {
  width:100%;
  height:50px;
  background:red;
}
Run Code Online (Sandbox Code Playgroud)
<div class="container">
  <div class="box" style="margin:0 500px 0 400px">a_long_text_to_avoid_the_shrink</div>
</div>

<div class="container">
  <div class="box">a_long_text_to_avoid_the_shrink</div>
</div>
Run Code Online (Sandbox Code Playgroud)


(2) The white-space is creating the min-width contraint preventing the element from shrinking.

Here is an exmaple to illustrate:

.body {
  display: flex;
  justify-content: center;
  margin: 10px 100px;
  border: 2px solid red;
}

.wrapper {
  border: 1px solid;
  margin: 0 20px;
}
.box {
 display:flex;
}
Run Code Online (Sandbox Code Playgroud)
The below is a logical behavior where the text will wrap and the margin are respected
<div class="body">
  <div class="wrapper">
    <div class="box">
      <div>some long text here some long text here some long text here some long text here</div>
    </div>
  </div>
</div>
Let's add white-space:nowrap. We add a min-width contraint since we said to the text to never wrap thus our flex element will not shrink and overflow.
<div class="body">
  <div class="wrapper">
    <div class="box">
      <div style="white-space:nowrap">some long text here some long text here some long text here some long text here</div>
    </div>
  </div>
</div>
If we add width:100% we force its width to be the same as the container BUT the margin aren't included and are kept outside (the text will logically overflow)
<div class="body">
  <div class="wrapper" style="width:100%">
    <div class="box">
      <div style="white-space:nowrap">some long text here some long text here some long text here some long text here</div>
    </div>
  </div>
</div>
Now if we add min-width:0 we remove the constaint of minimum sizing and we can see the margin again even if we keep width:100% because the element will shrink by default
<div class="body">
  <div class="wrapper" style="width:100%;min-width:0">
    <div class="box">
      <div style="white-space:nowrap">some long text here some long text here some long text here some long text here</div>
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

The trick is that we are centring the element and applying the same margin on both side which will create the illusion of a collapsing margin but it's a simple overflow of the margin from both sides equally.

Let's change the margin slightly on one side to see a little offset to the other side:

.body {
  display: flex;
  justify-content: center;
  margin: 10px 100px;
  border: 2px solid red;
}

.wrapper {
  border: 1px solid;
  margin: 0 20px 0 40px;
}
.box {
 display:flex;
}
Run Code Online (Sandbox Code Playgroud)
The below is a logical behavior where the text will wrap and the margin are respected
<div class="body">
  <div class="wrapper">
    <div class="box">
      <div>some long text here some long text here some long text here some long text here</div>
    </div>
  </div>
</div>
Let's add white-space:nowrap. We add a min-width contraint since we said to the text to never wrap thus our flex element will not shrink and overflow.
<div class="body">
  <div class="wrapper">
    <div class="box">
      <div style="white-space:nowrap">some long text here some long text here some long text here some long text here</div>
    </div>
  </div>
</div>
If we add width:100% we force its width to be the same as the container BUT the margin aren't included and are kept outside (the text will logically overflow)
<div class="body">
  <div class="wrapper" style="width:100%">
    <div class="box">
      <div style="white-space:nowrap">some long text here some long text here some long text here some long text here</div>
    </div>
  </div>
</div>
Now if we add min-width:0 we remove the constaint of minimum sizing and we can see the margin again even if we keep width:100% because the element will shrink by default
<div class="body">
  <div class="wrapper" style="width:100%;min-width:0">
    <div class="box">
      <div style="white-space:nowrap">some long text here some long text here some long text here some long text here</div>
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)