允许一个网格项与固定的页眉和侧边栏一起滚动

19
我有一个由两列和两行组成的网格布局,左侧有一个粘性导航栏,顶部有一个粘性页眉,内容将位于网格的右下角。
我现在几乎已经做到了,但我希望 .content div 在内容超出屏幕时使用滚动条。我以为只需要使用 overflow: auto 就可以了,但这似乎不起作用。我的方法接近正确吗?

body {
  margin: 0;
  overflow: hidden;
}

.page {
  display: grid;
  grid-template-rows: 55px auto;
  grid-template-columns: 20vh auto;
  grid-template-areas: "nav header" "nav content";
}

.nav {
  grid-area: nav;
  background-color: blue;
}

.header {
  grid-area: header;
  background-color: grey;
}

.content {
  grid-area: content;
  height: 1000px; // This is dynamic
  background-color: red;
}
<div class="page">
  <div class="nav">Side nav</div>
  <div class="header">Header</div>
  <div class="content">
    <h1>title</h1>
  </div>
  <div>

JS fiddle

3个回答

25

为了让overflow: auto生效(即呈现滚动条),浏览器需要一个触发器。这个触发器通常是高度/宽度的限制,强制产生溢出情况,从而启动滚动条。

触发条件因浏览器而异。它们还因CSS技术(如flex、grid和block布局)而异。

在这种特定情况下,有几个逻辑上合理的地方可以建立溢出条件,但没有一个有效。

  1. You could target the grid item, as you have tried:

    .content {
       height: 1000px
       overflow: auto;
    }
    

    But it doesn't work. No scrollbar appears on the fluid item.

body {
  margin: 0;
  /* overflow: hidden; */
}

.page {
  display: grid;
  grid-template-rows: 55px auto;
  grid-template-columns: 20vh auto;
  grid-template-areas: "nav header" 
                       "nav content";
}

.nav {
  grid-area: nav;
  background-color: aqua;
}

.header {
  grid-area: header;
  background-color: lightgrey;
}

.content {
  grid-area: content;
  height: 1000px;
  overflow: auto;
  background-color: red;
}
<div class="page">
  <div class="nav">Side nav</div>
  <div class="header">Header</div>
  <div class="content">
    <h1>title</h1>
  </div>
  <div>

  1. You could target the row itself, as I tested:

    .page {
       display: grid;
       grid-template-rows: 55px 1000px;
    }
    
    .content {
       overflow: auto;
    }
    

    But that doesn't work either. Still no scrollbar on the fluid item.

body {
  margin: 0;
  /* overflow: hidden; */
}

.page {
  display: grid;
  grid-template-rows: 55px 1000px;
  grid-template-columns: 20vh auto;
  grid-template-areas:
    "nav header"
    "nav content";
}

.nav {
  grid-area: nav;
  background-color: aqua;
}

.header {
  grid-area: header;
  background-color: lightgrey;
}

.content {
  overflow: auto;
  grid-area: content;
  background-color: red;
}
<div class="page">
  <div class="nav">Side nav</div>
  <div class="header">Header</div>
  <div class="content">
    <h1>title</h1>
  </div>
  <div>

  1. 所以我选择了一个网格项的子元素。叮叮当!这个方法可行。

    不需要固定定位,也不需要粘性定位。这在所有支持Grid Layout的浏览器中都可以使用。

body {
  margin: 0;
}

.page {
  display: grid;
  grid-template-rows: 55px calc(100vh - 55px);  /* height limitation on second row */
  grid-template-columns: 20vh auto;
  grid-template-areas: "nav header" 
                       "nav content";
}

.nav {
  grid-area: nav;
  background-color: aqua;
}

.header {
  grid-area: header;
  background-color: lightgrey;
}

.content {
  grid-area: content;
  background-color: red;
  overflow: auto;                          /* overflow condition on parent */
}

article {
  height: 1000px;                          /* height set on child; triggers scroll */
}
<div class="page">
  <div class="nav">Side nav</div>
  <div class="header">Header</div>
  <div class="content">
    <article><!-- new section for content -->
      <h1>title</h1>
    </article>
  </div>
  <div>

jsFiddle演示


1
这太完美了。正是我想要的。谢谢! - sss
1
非常好的解决方案,解释和实现得很好!谢谢! - Daniel B

5

浏览器支持并不是100%,但实际上使用sticky而不是fixed定位怎么样?(现在在Chrome中测试)你不必处理硬编码边距。

你仍然需要处理的问题之一是,当侧边栏(.nav > div)中的内容高于您的视口时该怎么办。

body {
  margin: 0;
}

.page {
  display: grid;
  grid-template-rows: 55px auto;
  grid-template-columns: 3.5rem auto;
  grid-template-areas: "nav header" "nav content";
}

.nav {
  grid-area: nav;
  background-color: blue;
}

.nav > div {
  position: sticky;
  top: 0;
}

.header {
  grid-area: header;
  background-color: grey;
  position: sticky;
  top: 0;
  min-height: 3.5rem;
}

.content {
  grid-area: content;
  min-height: 1000px;
  background-color: red;
}
<div class="page">
  <div class="nav">
    <div>Side nav</div>
  </div>
  <div class="header">Header</div>
  <div class="content">
    <h1>title</h1>
  </div>
<div>


我喜欢它,并且有polyfill来模拟position:sticky;。 https://github.com/filamentgroup/fixed-sticky - Sascha
运行良好。谢谢! - sss
不需要固定或粘性定位。通过对CSS和HTML进行一些调整,布局可以按预期工作。 - Michael Benjamin
@Michael_B 根据 Lakindu 的写作,改进了一个答案。我甚至不知道实际要求是什么。我宁愿把你的答案作为备选,因为在我看来,在整个窗口上拥有滚动条通常是可取的(在你的示例中,只有当我的指针在红色区域时,滚动才起作用)。在某些浏览器中,这也可能会显得有点丑。 - René
我认为意图是让滚动条仅存在于流体网格区域,其他区域应该是固定的。布局已经在整个窗口上有一个滚动条(只需在 body 元素上删除 overflow: hidden 即可)。 - Michael Benjamin
是的。这个解决方案可行,但我更希望滚动条从可滚动内容下面的标题开始。@Michael_B的答案正是我想要的。 - sss

3
我已经包含了变更日志,以便查看需要更改代码的位置,以便理解。完整的代码片段也在下面提供。希望这符合您的预期。
变更日志:
* 删除 body { overflow: hidden; } * 更改 .page { grid-template-columns: 3.5rem auto; } * 添加
.nav { position: fixed;
      top: 0;
      bottom:0;}

*新增

.header {  position: fixed;
      margin-left: 3.5rem;
      width: 100%;
      height: 3.5rem; }

完整代码

body {
  margin: 0;
}

.page {
  display: grid;
  grid-template-rows: 55px auto;
  grid-template-columns: 3.5rem auto;
  grid-template-areas:
    "nav header"
    "nav content";
}

.nav {
  position: fixed;
  top: 0;
  bottom:0;
  grid-area: nav;
  background-color: blue;

}

.header {
  grid-area: header;
  background-color: grey;
  position: fixed;
  margin-left: 3.5rem;
  width: 100%;
  height: 3.5rem;
}

.content {
  grid-area: content;
  height: 1000px;
  background-color: red;
}
<div class="page">
  <div class="nav">Side nav</div>
  <div class="header">Header</div>
  <div class="content">
    <h1>title</h1>
  </div>
<div>


不完全正确。我想要页眉和侧边导航栏固定在页面上方,只滚动右下角的.content div。 - sss
"position: fixed" 对于侧边导航和页头应该可以。让我检查一下。 - Lakindu Gunasekara
立即查看 @seanyesmunt - Lakindu Gunasekara
嗯,这已经更接近了。我觉得在使用CSS网格时不应该需要调整边距?我想扩展内容div的样式,并保持导航/标题栏的基本网格样式(如果可能的话)。我会继续尝试你提供的方法。另外,我想避免的另一件事是滚动条延伸到屏幕顶部。理想情况下,它应该从内容div的顶部开始。 - sss
滚动条因为在.content中提供了固定高度而被扩展。我认为"rem"单位也是响应式的。我不得不改变grid-template-columns,因为它与给定的单位不兼容。您需要更多支持吗? - Lakindu Gunasekara
我必须调整边距,因为侧边栏和标题栏都应该是固定的。它们会重叠,为了避免这种情况,我使用了“rem”单位,这在任何地方都是响应式的。也许有更好的解决方案。 - Lakindu Gunasekara

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