在flexbox项内获取100%高度的div

5

我正在尝试使用 flexbox 制作以下布局。

enter image description here

顶部黑色条、中间部分和底部黑色条都是弹性项目,它们都是主体标签内的包装 div 的子元素。该标签如下所示。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic' rel='stylesheet' type='text/css'>
    <link href="~/Styles/bootstrap.min.css" rel="stylesheet" />
    <link href="~/Styles/font-awesome.min.css" rel="stylesheet" />
    <link href="~/Styles/ppt_site.css" rel="stylesheet" />
</head>
<body>
    <div class="wrapper">

        <div id="topRow">
        </div>

        <div id="centralRow">

            <div id="sidebarColumn">
            </div>

            <div id="contentColumn">
            </div>

        </div>

        <div id="bottomRow">
        </div>

    </div>

    @Section['customScripts']
    <script src="~/Scripts/siteGlobals.js"></script>

    <script src="~/requireconfig"></script>
    <script data-main="~/scripts/NewTemplatesAppLoader.js" src="~/requirejs"></script>

</body>
</html>

控制所有这些的样式表如下:
.wrapper, html, body {
    height: 100%;
    margin: 0;
}

.wrapper {
    display: flex;
    -ms-flex-direction: column;
    -webkit-flex-direction: column;
    flex-direction: column;
}

#topRow {
    background-color: black;
    color: white;
}

#centralRow {
    -ms-flex: 1;
    -webkit-flex: 1;
    flex: 1;
    display: flex;
    -ms-flex-direction: row;
    -webkit-flex-direction: row;
    flex-direction: row;
}

#bottomRow {
    background-color: #333333;
    color: white;
}

#sidebarColumn {
    background-color: #B83B1D;
    color: white;
}

#contentColumn {
    -ms-flex: 1;
    -webkit-flex: 1;
    flex: 1;
    background-color: #F7F7F7;
    color: black;
    padding: 10px;
    overflow-y: auto;
}

就主要布局而言,一切都很完美,但是如果您查看图片,您会注意到红色侧边栏顶部有一个黄色边框的区域。
那个区域注定是一个div,它将延伸到上面CSS中红色区域(侧边栏列)的整个高度,但无论我如何尝试,都无法使其达到预期效果。
理想情况下,我希望它是一个flex容器的div,然后我可以将4个flex项放入其中,并让每个项目占用可用空间的四分之一,但由于具有黄色边框的div似乎无法看到父容器的高度(红色侧边栏本身也是flex项),因此它只占据其内容周围的空间高度。
我尝试了将其包装在更多的div中并定位这些div,我将进一步的flex盒子包裹在更多的div中,我尝试了块、行内、表格单元格和几乎我能想到的所有其他东西。
无论我尝试什么,我似乎都无法使黄色边框的容器与其父容器具有相同的高度。
大家有什么想法吗?
更新(第二天)
这两种方案确实能够正常工作,它们本身就是我所期望的。
然而,在我的特定情况下,它们不起作用。
我正在使用 NancyFX 和其超级简单的视图引擎,并且我正在使用 KnockoutJS 来组合“Web 组件”,以便我可以保持我的部件可重用。
如果我编辑我的“主模板”,并将 div 直接插入标记中,嵌套在 #sidebarColumn 下面,我会得到所需的 4 个相等大小的 div。
然而,实际上需要发生的是,我的模板如下所示:
<div class="wrapper">

    <div id="topRow">
        @Section['topbarContent']
    </div>

    <div id="centralRow">

        <div id="sidebarColumn">
            @Section['sidebarContent']
        </div>

        <div id="contentColumn">
            @Section['bodyContent']
        </div>

    </div>

    <div id="bottomRow">
        @Section['bottombarContent']
    </div>

</div>

如果我移除"@Section['sidebarContent']",并直接放置div,则它们可以正常工作。
如果我将div直接放入使用以下模板的"Page"中:
@Master['shared/ppt_layout.html']

@Section['topbarContent']
    <toptoolbar></toptoolbar>
@EndSection

@Section['sidebarContent']
    <div>aaa</div>
    <div>aaa</div>
    <div>aaa</div>
    <div>aaa</div>
@EndSection

@Section['bodyContent']
    <h1>Body Content</h1>
    <p class="lead">I am the test page that uses a wide sidebar component</p>
    <p>If you notice however, I also have a top toolbar with title added to me, and a footer bar.</p>
    <p>We all use the same template however....</p>
@EndSection

@Section['bottombarContent']
    <footerbar></footerbar>
@EndSection

@Section['customScripts']
@EndSection

那也可以,但如果我把标记放在一个knockout组件中,即使只是像页面上一样的普通div,那么我就会得到我最初注意到的效果。因此,由于某种原因,使用knockout组件添加内容正是导致问题的根源。即使我尝试在组件内构建新的flex布局,垂直方向上什么都不起作用,但水平方向上一切都完美运行。例如,页脚栏被分成左右两个部分,没有任何问题,但垂直对齐却被压缩了。
3个回答

2

经过看似数天的煎熬,我最终找到了问题所在。

我的项目中使用了 knockout.js,具体来说就是 knockout 组件,而它们之间的障碍导致了问题。

对于那些没有使用过 KO 组件的人来说,这是一个非常简单的过程。你需要构建一个 JS 视图模型和一小段 HTML 代码来提供组件的显示表面。

接下来你需要使用:

ko.components.register("myComponent", {
    viewModel: "Components/myComponent.js",
    template: "Components/myComponent.html"
});

ko.applyBindings();

注册您的组件。

一旦组件被注册,您只需将其放置在需要使用的地方即可。

<myComponent></myComponent>

无论您希望在网页的哪个位置添加它。

现在这一切都很好,但是... 当KO实例化组件时,它会保留自定义标记。

因此,如果您想象一下您的组件如下所示

<div>
    <div>Item...</div>
    <div>Item...</div>
    <div>Item...</div>
    <div>Item...</div>
</div>

你的页面看起来像这样:
<body>
    <div>
        <myComponent></myComponent>
    </div>
</body>

最终输出结果将会是这样的:
<body>
    <div>
        <myComponent>
            <div>
                <div>Item...</div>
                <div>Item...</div>
                <div>Item...</div>
                <div>Item...</div>
            </div>
        </myComponent>
    </div>
</body>

考虑到上述CSS中的规则,我的和两个响应者的规则都是针对包装器div的,因此规则从未匹配目标div以启用其弹性。

关键是(我通过试错发现),要使用自定义标签名称,例如:

#sidebarColumn > narrowsidebar {
     width: 70px;
     flex: 1;
     display: flex;
     flex-direction: column;
}

然后,从父级进一步降低弹性操作。

然而,仍然无法解释的是,如果在组件内从头开始进行完整的 flexbox 布局(即没有在主网页和/或模板中进行任何弹性操作),为什么它仍然存在垂直对齐方面的问题,就我所看到的内容,KO 没有对 dom 进行任何操作,应该不会导致这种行为。

然而,通过自定义标签进行定位解决了我的初始问题。

Shawty


1

您可以使用嵌套的Flexbox:

<div id="sidebarColumn">
  <div>...</div>
  <div>...</div>
  <div>...</div>
  <div>...</div>
</div>

#sidebarColumn {
  display: flex;
  flex-direction: column;
}
#sidebarColumn > div {
  flex: 1;
}

jsFiddle


好的,所以你提出的解决方案独立运行得很好,正如我预期的那样,但它在我的项目中不起作用,不过现在我知道原因了。 - shawty
很高兴看到你解决了这个问题,否则其他人可能会很难理解那里发生了什么。 - Stickers

1
使用flex: 1来使弹性子元素占据尽可能多的空间。

.wrapper, html, body {
    height: 100%;
    margin: 0;
    padding:0;
}

/* header */
#topRow {
    background-color: black;
    color: white;
    height:20%;
}

/* footer */
#bottomRow {
    background-color: #333333;
    color: white;
    height:10%;
}

/* main */
#centralRow {
  height:70%;
  display: flex;
}

/* sidebar */
#sidebarColumn {
    background-color: #B83B1D;
    color: white;
    width:20%;
    display: flex;
    flex-direction: column;
}

#sidebarColumn nav {
  padding:1em;
  border:1px solid yellow;
  flex:1;
}

/* content */
#contentColumn {
  overflow: auto;
  flex:1;
}

.big {
  border:1px solid red;
  margin:1em;
  height:400px;
}
<div class="wrapper">

  <div id="topRow">
    header
  </div>

  <div id="centralRow">
    <div id="sidebarColumn">
      sidebar
      <nav>
        nav links
      </nav>
    </div>
    <div id="contentColumn">
      body content
      <div class="big">some big content</div>
    </div>
  </div>

  <div id="bottomRow">
    footer
  </div>
</div>

https://jsfiddle.net/azizn/y4hag5o3/


与其他解决方案一样,这个可以独立工作,但是在我的项目中却无法运行。 - shawty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接