具有两个等高子项的 Flexbox 布局,其中一个包含带有滚动内容的嵌套 Flexbox [英] Flexbox layout with two equal height children, one containing nested flexbox with scrolling content

查看:13
本文介绍了具有两个等高子项的 Flexbox 布局,其中一个包含带有滚动内容的嵌套 Flexbox的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 <img>,它的右侧有一个面板,其中包含一个控件标题和一长串项目.所以我有一个嵌套的 flexbox 情况:

.container (flex)->.child img->.child 控制面板 (flex)->.controls->.content-wrapper 滚动列表

在非常基本的层面上,两个并排的面板很容易,使用 align-items:stretch 成为一个简单的 flex .. https://codepen.io/neekfenwick/pen/MOxYxz

在那个基本层面,这是一个重复的问题 如何让两个并排的 div 保持相同的高度?.

一旦右侧的面板因垂直滚动列表而变得更加复杂,我无法看到如何使其父级的高度,即第二个 .child 的高度与第一个 的高度匹配>.child.https://codepen.io/neekfenwick/pen/XzGJGw

+-------------+---------------+||控制 ||左子 |||+--------------+||A|||垂直 |+||滚动 ||||项目 |||||+||V|+--------------+--------------+

我已阅读具有可滚动内容的 Flexbox 项目,但这解决了水平滚动问题,不是这样的垂直布局.另外 带滚动区域的嵌套 flexbox 处理垂直堆叠的嵌套 flexbox,我认为这种组合rowcolumn 方向混淆了我的情况.

作为代码片段:

.container {显示:弹性;对齐项目:拉伸;}.孩子 {边框:1px 纯灰色;背景颜色:浅灰色;弹性:1 1 自动;}.控制面板{显示:弹性;弹性方向:列;}.controls {弹性:0 0 自动;}.content-wrapper {弹性:1 1 自动;宽度:400px;溢出-y:自动;}.content-item {显示:内联块;宽度:100px;高度:100px;背景颜色:红色;}

<div class="child"><p>在现实生活中,我是一个内嵌的 img.</p><p>我有点内容呲牙咧嘴.</p><p>我有点内容呲牙咧嘴.</p><p>我有点内容呲牙咧嘴.</p><p>我希望我的兄弟姐妹和我一样高.</p>

<div class="子控件面板"><div class="控件"><p>小控制区域.下面的面板应垂直滚动.</p>

<div class="content-wrapper"><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div>

我不想在这里固定任何元素的高度.碰巧,我知道 img 的高度,所以我可以使用 CSS 来强制右侧元素的高度,但我想知道是否有一种真正的"flexbox 方法可以解决这个问题.

解决方案

一般来说,对于 overflow: scroll(或 autohidden) 工作,需要以一种或另一种方式进行高度约束,否则元素通常会根据需要增长以适应其内容.

主要有 3 种方式,其中一种是设置实际高度,如在第一个示例中,我将其添加到 container.

堆栈片段 1

.container {显示:弹性;高度:100vh;}.孩子 {边框:1px 纯灰色;背景颜色:浅灰色;弹性:1 1 自动;}.控制面板{显示:弹性;弹性方向:列;}.controls {弹性:0 0 自动;}.content-wrapper {弹性:1 1 自动;宽度:400px;溢出-y:自动;}.content-item {显示:内联块;宽度:100px;高度:100px;背景颜色:红色;}

<div class="child"><p>在现实生活中,我是一个内嵌的 img.</p><p>我有点内容呲牙咧嘴.</p><p>我有点内容呲牙咧嘴.</p><p>我有点内容呲牙咧嘴.</p><p>我希望我的兄弟姐妹和我一样高.</p>

<div class="子控件面板"><div class="控件"><p>小控制区域.下面的面板应垂直滚动.</p>

<div class="content-wrapper"><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div>

<小时>

或者使用绝对定位来创建高度约束,这是绝对元素所做的.

它只是通过一个额外的包装器实现,content-scroll,并将保持结构的其余部分完全动态.

堆栈片段 2

.container {显示:弹性;}.孩子 {边框:1px 纯灰色;背景颜色:浅灰色;弹性:1 1 自动;}.控制面板{显示:弹性;弹性方向:列;}.controls {弹性:0 0 自动;}.content-wrapper {位置:相对;弹性:1 1 自动;宽度:400px;}.内容滚动{位置:绝对;顶部:0;左:0;右:0;底部:0;溢出-y:自动;}.content-item {显示:内联块;宽度:100px;高度:100px;背景颜色:红色;}

<div class="child"><p>在现实生活中,我是一个内嵌的 img.</p><p>我有点内容呲牙咧嘴.</p><p>我有点内容呲牙咧嘴.</p><p>我有点内容呲牙咧嘴.</p><p>我希望我的兄弟姐妹和我一样高.</p>

<div class="子控件面板"><div class="控件"><p>小控制区域.下面的面板应垂直滚动.</p>

<div class="content-wrapper"><div class="content-scroll"><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div>

<小时>

单独使用 Flexbox,认为它可能无法完全跨浏览器工作,尤其是旧版本,仍然支持它,但有很多错误.

原始代码中的简单修复是将 .content-wrapper 中的 flex: 1 1 auto; 更改为 flex: 1 1 0px;(我的 IE 版本需要 0px,Chrome/Firefox/Edge 可以使用 0)

堆栈片段 3

.container {显示:弹性;}.孩子 {边框:1px 纯灰色;背景颜色:浅灰色;弹性:1 1 自动;}.控制面板{显示:弹性;弹性方向:列;}.controls {弹性:0 0 自动;}.content-wrapper {弹性:1 1 0px;宽度:400px;溢出-y:自动;}.content-item {显示:内联块;宽度:100px;高度:100px;背景颜色:红色;}

<div class="child"><p>在现实生活中,我是一个内嵌的 img.</p><p>我有点内容呲牙咧嘴.</p><p>我有点内容呲牙咧嘴.</p><p>我有点内容呲牙咧嘴.</p><p>我希望我的兄弟姐妹和我一样高.</p>

<div class="子控件面板"><div class="控件"><p>小控制区域.下面的面板应垂直滚动.</p>

<div class="content-wrapper"><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div><div class="content-item"></div>

<小时>

代码段 2 和 3 也回答了您的问题

<块引用>

...使用垂直滚动列表,我看不到如何制作其父级的高度,即第二个 .child,与第一个 .child.

注意,如果右列的顶部元素可以比左列更大,则底部元素需要一个最小高度,以防止其折叠为0,例如

.content-wrapper {...最小高度:200px;/* 例如像这样  */}

I have an <img> with a panel to its right containing a controls header and a long list of items. So I have a nested flexbox situation:

.container (flex)
 -> .child img
 -> .child controls panel (flex)
  -> .controls
  -> .content-wrapper scrolling list

At a very basic level, the two side by side panels are easy, being a simple flex with align-items: stretch .. https://codepen.io/neekfenwick/pen/MOxYxz

At that basic level it's a duplicate question to How do I keep two divs that are side by side the same height?.

Once the panel on the right becomes more complex with a vertically scrolling list, I cannot see how to make the height of its parent, the second .child, match the height of the first .child. https://codepen.io/neekfenwick/pen/XzGJGw

+-------------+---------------+
|             |  Controls     |
| Left child  |               |
|             +---------------+
|             |              A|
|             | Vertically   |+
|             | scrolling    ||
|             | items        ||
|             |              |+
|             |              V|
+-------------+---------------+

I have read Flexbox item with scrollable content but that solves a horizontal scrolling problem, not a vertical layout like this. Also Nested flexbox with scrolling area deals with vertically stacked nested flexboxes, I think this combination of row and column directions confuses my situation.

As a code snippet:

.container {
  display: flex;
  align-items: stretch;
}

.child {
  border: 1px solid grey;
  background-color: lightgrey;
  flex: 1 1 auto;
}

.controls-panel {
  display: flex;
  flex-direction: column;
}

.controls {
  flex: 0 0 auto;
}

.content-wrapper {
  flex: 1 1 auto;
  width: 400px;
  overflow-y: auto;
}
.content-item {
  display: inline-block;
  width: 100px;
  height: 100px;
  background-color: red;
}

<div class="container">
  <div class="child">
    <p>In real life I am an inline img.</p>
    <p>I am some content whoop de doo.</p>
    <p>I am some content whoop de doo.</p>
    <p>I am some content whoop de doo.</p>
    <p>I want my sibling to equal my height.</p>
  </div>
  <div class="child controls-panel">
    <div class="controls">
      <p>Small controls area. Panel below should scroll vertically.</p>
    </div>
    <div class="content-wrapper">
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
    </div>
  </div>
</div>

I do not want to fix the height of any elements here. As it happens, I know the height of the img, and so I could use CSS to force the height of the elements on the right, but I wondered if there is a 'true' flexbox way of solving this problem.

解决方案

In general, for overflow: scroll (or auto and hidden) to work, a height constraint is needed in one way or the other, or else element's normally grow as much as needed to fit their content.

There is mainly 3 ways, where either an actual height is set, as in this first sample, where I added it to the container.

Stack snippet 1

.container {
  display: flex;
  height: 100vh;
}

.child {
  border: 1px solid grey;
  background-color: lightgrey;
  flex: 1 1 auto;
}

.controls-panel {
  display: flex;
  flex-direction: column;
}

.controls {
  flex: 0 0 auto;
}

.content-wrapper {
  flex: 1 1 auto;
  width: 400px;
  overflow-y: auto;
}
.content-item {
  display: inline-block;
  width: 100px;
  height: 100px;
  background-color: red;
}

<div class="container">
  <div class="child">
    <p>In real life I am an inline img.</p>
    <p>I am some content whoop de doo.</p>
    <p>I am some content whoop de doo.</p>
    <p>I am some content whoop de doo.</p>
    <p>I want my sibling to equal my height.</p>
  </div>
  <div class="child controls-panel">
    <div class="controls">
      <p>Small controls area. Panel below should scroll vertically.</p>
    </div>
    <div class="content-wrapper">
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
      <div class="content-item"></div>
    </div>
  </div>
</div>


Or to use absolute positioning to create that height constraint, which an absolute element does.

It is simply accomplished with an extra wrapper, content-scroll, and will keep the rest of the structure fully dynamic.

Stack snippet 2

.container {
  display: flex;
}

.child {
  border: 1px solid grey;
  background-color: lightgrey;
  flex: 1 1 auto;
}

.controls-panel {
  display: flex;
  flex-direction: column;
}

.controls {
  flex: 0 0 auto;
}

.content-wrapper {
  position: relative;
  flex: 1 1 auto;
  width: 400px;
}
.content-scroll {
  position: absolute;
  top: 0; left: 0;
  right: 0; bottom: 0;
  overflow-y: auto;
}
.content-item {
  display: inline-block;
  width: 100px;
  height: 100px;
  background-color: red;
}

<div class="container">
  <div class="child">
    <p>In real life I am an inline img.</p>
    <p>I am some content whoop de doo.</p>
    <p>I am some content whoop de doo.</p>
    <p>I am some content whoop de doo.</p>
    <p>I want my sibling to equal my height.</p>
  </div>
  <div class="child controls-panel">
    <div class="controls">
      <p>Small controls area. Panel below should scroll vertically.</p>
    </div>
    <div class="content-wrapper">
      <div class="content-scroll">
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
      </div>
    </div>
  </div>
</div>


Use Flexbox alone, thought it might not work fully cross browsers, especially with older versions, that still support it but is a lot buggier.

The simple fix in your original code is to change the flex: 1 1 auto; in .content-wrapper to flex: 1 1 0px; (0px were needed for my IE version, for Chrome/Firefox/Edge one can use 0)

Stack snippet 3

.container {
  display: flex;
}

.child {
  border: 1px solid grey;
  background-color: lightgrey;
  flex: 1 1 auto;
}

.controls-panel {
  display: flex;
  flex-direction: column;
}

.controls {
  flex: 0 0 auto;
}

.content-wrapper {
  flex: 1 1 0px;
  width: 400px;
  overflow-y: auto;
}
.content-item {
  display: inline-block;
  width: 100px;
  height: 100px;
  background-color: red;
}

<div class="container">
  <div class="child">
    <p>In real life I am an inline img.</p>
    <p>I am some content whoop de doo.</p>
    <p>I am some content whoop de doo.</p>
    <p>I am some content whoop de doo.</p>
    <p>I want my sibling to equal my height.</p>
  </div>
  <div class="child controls-panel">
    <div class="controls">
      <p>Small controls area. Panel below should scroll vertically.</p>
    </div>
    <div class="content-wrapper">
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
        <div class="content-item"></div>
    </div>
  </div>
</div>


Snippet 2 and 3 also answers your question

...with a vertically scrolling list, I cannot see how to make the height of its parent, the second .child, match the height of the first .child.

Note, if the top element in the right column can grow bigger than the left column, a minimum height will be needed on the bottom element, to prevent it from collapse into 0, e.g.

.content-wrapper {
  ...
  min-height: 200px;           /*  e.g. like this  */
}

这篇关于具有两个等高子项的 Flexbox 布局,其中一个包含带有滚动内容的嵌套 Flexbox的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆