具有可滚动单元格的响应式 CSS 网格溢出其父容器

Responsive CSS grid with scrollable cell overflows its parent container

我有一个经典的“顶部导航栏 - 侧边栏 - 主要内容”CSS 网格布局,它也是响应式的,在较小的屏幕上,这些部分垂直重新排列。网格的样式可以延伸到整个视口。如果内容长于视口,主区域可以垂直滚动,而顶部和侧面导航栏被“固定”到它们的位置,并且在任何方向上都不能小于它们的内容。

为了实现主区域的垂直滚动,我将网格容器的max-height 属性设置为100vh,并设置overflow-y 属性 的 main 元素到 auto。然而,这个 max-height 属性 似乎对网格有不利的副作用:一旦视口的高度小于 space 所需的最小高度,内容可能会垂直溢出网格容器显示顶部导航栏和侧边栏(不能缩小到其内容下方)。

这就是它的样子,例如,在较小的屏幕上,网格单元彼此堆叠:

上图黄色部分是滚动出来的部分,在浏览器中看不到window。主要区域位于底部,高度为零(加上边框),但这没关系,因为 main 元素可垂直滚动,并且网格行设置为 1fr 高度。黑色边框用于整个网格容器。如示例所示,侧边栏和主要区域位于容器外部。

同样的事情在更大的屏幕上,边栏向左移动,看起来像这样:

然而,我想要的是网格单元不与网格容器重叠但它们被完全包含。也就是说,在具有垂直堆叠单元格的较小屏幕上,这:

在较大的屏幕上,左侧边栏:

是否可以使用网格结构的一些修改版本和下面代码段中给出的 CSS 来实现?所以基本上我想要一个可滚动的主区域,其中顶部导航栏和侧边栏不能垂直收缩到低于其最低要求的高度,以及一个不与其内容重叠的网格容器。我想避免任何明确大小为特定值的东西(即我不想使用 height: 120px.

之类的东西

请注意,这是关于我的 的后续问题,但它不一样,因为我现在需要一个可滚动的主区域。

* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}

.bordered {
  border-style: solid;
  border-width: 5px;
}

/* grid layout */

.grid {
  display: grid;
  /* Default (small screen) layout. */
  /* Single column with 3 rows, the last one filling out the remaining space. */
  grid-template-rows: min-content min-content 1fr;
  max-height: 100vh;
  min-height: 100vh;
  min-width: min-content;
}

@media (min-width: 640px) {
  .grid {
    /* Larger screen layout. */
    /* 2 columns with 2 rows, the bottom right cell filling out the remaining space. */
    grid-template-columns: max-content 1fr;
    grid-template-rows: min-content 1fr;
  }

  nav {
    grid-column: span 2 / span 2;
  }
}

aside, nav {
  white-space: nowrap;
}

main {
  overflow-y: auto;
}
<html>

<body>
  <div class="grid bordered" style="border-color: black;">
    <nav class="bordered" style="border-color: green;">Top nav</nav>
    <aside class="bordered" style="border-color: red;">
      <ul>
        <li>Some example sidebar item #1</li>
        <li>Some example sidebar item #2</li>
        <li>Some example sidebar item #3</li>
        <li>Some example sidebar item #4</li>
        <li>Some example sidebar item #5</li>
      </ul>
    </aside>
    <main class="bordered" style="border-color: cyan;">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
      <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
      <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
      <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </main>
  </div>
</body>

</html>

我的一位同事建议在网格容器本身上使用 overflow-y: auto 属性。虽然它的效果不完全与我正在寻找的相同,但它非常相似并且确实防止侧边栏内容溢出容器。唯一的细微差别是,当可用 space 变得小于显示网格内容所需的最小值时,是网格容器而不是视口获得垂直滚动条。

下面是修改后的代码片段来演示它。

* {
  box-sizing: border-box;
}

body {
  margin: 0;
}

ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}

.bordered {
  border-style: solid;
  border-width: 5px;
}

/* grid layout */

.grid {
  display: grid;
  /* Default (small screen) layout. */
  /* Single column with 3 rows, the last one filling out the remaining space. */
  grid-template-rows: min-content min-content 1fr;
  max-height: 100vh;
  min-height: 100vh;
  min-width: min-content;
  overflow-y: auto; /* <-- the only property added to the original CSS */
}

@media (min-width: 640px) {
  .grid {
    /* Larger screen layout. */
    /* 2 columns with 2 rows, the bottom right cell filling out the remaining space. */
    grid-template-columns: max-content 1fr;
    grid-template-rows: min-content 1fr;
  }

  nav {
    grid-column: span 2 / span 2;
  }
}

aside, nav {
  white-space: nowrap;
}

main {
  overflow-y: auto;
}
<html>

<body>
  <div class="grid bordered" style="border-color: black;">
    <nav class="bordered" style="border-color: green;">Top nav</nav>
    <aside class="bordered" style="border-color: red;">
      <ul>
        <li>Some example sidebar item #1</li>
        <li>Some example sidebar item #2</li>
        <li>Some example sidebar item #3</li>
        <li>Some example sidebar item #4</li>
        <li>Some example sidebar item #5</li>
      </ul>
    </aside>
    <main class="bordered" style="border-color: cyan;">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
      <p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
      <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
      <p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </main>
  </div>
</body>

</html>