启用换行的 Flex 列中的元素在包含基于嵌套宽高比的元素时不会保留内容高度

问题描述 投票:0回答:1

今天,我必须构建一个相当复杂的布局,需要垂直堆叠弯曲的项目,并在其中包含

aspect-ratio
绑定图像。在开发过程中,我发现当弹性容器设置为
flex-wrap: wrap;
时,其中的元素使用
aspect-ratio
甚至伪元素方法(即
&::before { padding-bottom: 56.25%; }
)会导致弯曲项目脱离其容器。

设置

flex-wrap: none;
对于我今天的目的来说是一个很好的解决方案,但我很困惑为什么会发生这种情况,甚至跨多个浏览器(在 Firefox、Chrome 和 Edge 中测试)。这是故意行为吗?如果是这样,为什么会这样?

https://codepen.io/JacobDB/pen/bGZajOX

/**
 * Button for testing
 */
const BUTTON = document.querySelector("button");
const ROW    = document.querySelector(".row");

BUTTON.addEventListener("click", (e) => {
    e.preventDefault();
    
    if (ROW.classList.contains("flex-wrap")) {
        ROW.classList.remove("flex-wrap");
        BUTTON.innerHTML = "flex-wrap: none;";
    } else {
        ROW.classList.add("flex-wrap");
        BUTTON.innerHTML = "flex-wrap: wrap;";
    }

}, { passive: false });
.row {
    display: flex;
    flex-direction: column;
}

.flex-wrap {
    flex-wrap: wrap;
}

figure {
    aspect-ratio: 16 / 9;
}

figure.pseudo-element {
    aspect-ratio: auto;
}

figure.pseudo-element::after {
    content: "";
    display: block;
    padding-bottom: 56.25%;
}

/**
 * Pretty it up a bit
 */
:root { font-family: sans-serif; }
button { margin-bottom: 1em; }
.row { border: 2px dotted blue; padding: 1em; }
.col { border: 2px dotted red; padding: 1em; }
.col:not(:first-child) { border-top: 0; }
article { border: 2px dotted green; }
figure { position: relative; }
<button>
    flex-wrap: wrap;
</button>

<div class="row flex-wrap">
    <div class="col">
        <article>
            <figure>
                Figure 1
            </figure>
        </article>
    </div>
    <div class="col">
        <article>
            <figure class="pseudo-element">
                Figure 2 (Pseudo Element)
            </figure>
        </article>
    </div>
    <div class="col">
        <article>
            <figure>
                Figure 3
            </figure>
        </article>
    </div>
</div>

css flexbox
1个回答
0
投票

首先,更新

align-items
以使用与
stretch
(默认值)不同的内容,两者的行为相同

/**
 * Button for testing
 */
const BUTTON = document.querySelector("button");
const ROW    = document.querySelector(".row");

BUTTON.addEventListener("click", (e) => {
    e.preventDefault();
    
    if (ROW.classList.contains("flex-wrap")) {
        ROW.classList.remove("flex-wrap");
        BUTTON.innerHTML = "flex-wrap: none;";
    } else {
        ROW.classList.add("flex-wrap");
        BUTTON.innerHTML = "flex-wrap: wrap;";
    }

}, { passive: false });
.row {
    display: flex;
    flex-direction: column;
    align-items: start;
}

.flex-wrap {
    flex-wrap: wrap;
}

figure {
    aspect-ratio: 16 / 9;
}

figure.pseudo-element {
    aspect-ratio: auto;
}

figure.pseudo-element::after {
    content: "";
    display: block;
    padding-bottom: 56.25%;
}

/**
 * Pretty it up a bit
 */
:root { font-family: sans-serif; }
button { margin-bottom: 1em; }
.row { border: 2px dotted blue; padding: 1em; }
.col { border: 2px dotted red; padding: 1em; }
.col:not(:first-child) { border-top: 0; }
article { border: 2px dotted green; }
figure { position: relative; }
<button>
    flex-wrap: wrap;
</button>

<div class="row flex-wrap">
    <div class="col">
        <article>
            <figure>
                Figure 1
            </figure>
        </article>
    </div>
    <div class="col">
        <article>
            <figure class="pseudo-element">
                Figure 2 (Pseudo Element)
            </figure>
        </article>
    </div>
    <div class="col">
        <article>
            <figure>
                Figure 3
            </figure>
        </article>
    </div>
</div>

现在采取相同的示例,保留

flex-wrap: wrap
,然后切换
align-items
。您会注意到,当子项溢出时,容器的高度将保持不变。


flex-wrap
的使用定义了容器的性质,它是“单行”还是“多行”

Flex 容器可以是单行或多行,具体取决于 flex-wrap 属性:ref

即使您有一行(在您的情况下为一列),如果

flex-wrap
设置为
wrap
并且这会影响行和项目的大小调整算法,您的容器仍然被视为“多行”容器。

使用“单线”配置时,计算尺寸很容易。

在单行 Flex 容器中,线的交叉尺寸就是 Flex 容器的交叉尺寸

该行将具有容器的大小(内容在这里不起作用),然后每个容器将拉伸以填充该行(在您的情况下为全宽),然后内部元素的大小将根据其比例进行调整,并逻辑上扩展高度他们的容器。

当使用“多行”配置时,这是另一回事,因为每行的大小现在取决于内容。我不会详细介绍所有算法,但其想法是浏览器需要首先找到线条的大小(基于内容),然后元素将适合该大小并计算它们的高度。然后拉伸对齐将扩大线条的尺寸。这将在逻辑上扩展其中元素的大小,但我们不会再次计算容器的高度,因为它已经在上一步中完成了。

它可能看起来有点奇怪并且不直观,因为您可能认为在您的特定情况下,我们应该扩展高度(这是事实),但在某些情况下,更改高度将导致无限循环,这就是为什么它不会得到更新,子项目将会溢出。


您应该记住的重要一点是

flex-wrap
做的比您想象的要多。它不仅可以实现换行,还可以更改用于调整元素大小的算法,并且正如您所注意到的,它可以产生影响。

类似情况的一些相关问题:

弹性包裹会使孩子身高增加一倍

为什么我的容器的弹性包装导致我的自动填充网格添加额外的空轨道行?

© www.soinside.com 2019 - 2024. All rights reserved.