具有可滚动单元格的响应式 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>
我有一个经典的“顶部导航栏 - 侧边栏 - 主要内容”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>