CSS: 当 flex 换行时,如何防止可滚动列被向下推到其容器的折叠下方?
CSS: When flex row wraps, how to keep scrollable column from being pushed down below its container's fold?
在固定高度的容器中,我有一个带有 flex-direction: row 和 flex-wrap: wrap 的 flexbox (.main)。在宽屏幕尺寸下,我希望它的子项 — 图像 (.image-column) 和大量文本 (.text-column) — 成为列,其中图像保持静态,文本滚动。到目前为止,一切都很好。当尺寸缩小超过列的最小宽度时,我希望它们环绕和堆叠。这一切都有效,但问题在于:当它们换行和堆叠时,可滚动文本会偏移其上方 .image-column 的最小高度,这样当您向下滚动到文本底部时,滚动条就会消失离开屏幕而不是留在其容器内。但是,如果您调整高度以解决此偏移量,则 .text-column 在展开状态下会被压扁。
两个相互矛盾的元素似乎是:
- .image-column's min-height: 200px — 但如果没有这个,图像在包裹时根本不会显示
- .text-column's height: 100% — 但没有这个,文本不会滚动
我试过 .text-column with height: calc(100% - 200px) — 这修复了堆叠时的偏移量,但在列中时会产生不必要的空白,无论如何我宁愿避免这种特殊性
我想找到一个只有 CSS 而 没有媒体查询 的解决方案,因为这个容器可能与其他容器处于多列布局中。我愿意使用 flex、grid、float 或任何其他神秘的布局技巧。
有没有其他人遇到过弹性换行和滚动的这个问题?
(您可以 运行 下面的代码片段查看换行的布局,然后按整页查看处于宽 2 列状态的布局。)
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 40px;
padding: 40px;
background: #f6f6f6;
font-family: sans-serif; font-size: 120%; line-height: 1.5; color: #111;
}
.container {
height: 600px;
min-width: 300px;
max-width: 900px;
width: 100%;
display: flex;
flex-direction: column;
background-color: white;
border-radius: 10px;
overflow: hidden; /* don't scroll */
border: 1px solid #ccc;
}
.header {
border-bottom: 1px solid #ccc;
padding: 20px;
}
.main {
flex: 1 1 auto; /* fills remainder of height */
display: flex;
flex-direction: row;
flex-wrap: wrap; /* wrap after elements reach min-width / flex-basis */
overflow: hidden; /* don't scroll */
}
.image-column {
min-height: 200px;
flex: 1 1 300px; /* column width, min for wrapping */
background-image: url('https://images.unsplash.com/photo-1641361784653-73767ccfdf60?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDM0fDZzTVZqVExTa2VRfHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=900&q=60');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.text-column {
height: 100%;
flex: 2 1 420px; /* column width, min for wrapping */
overflow: auto; /* scroll */
padding: 20px;
}
.footer {
border-top: 1px solid #ccc;
padding: 20px;
}
<div class="container">
<div class="header">Header</div>
<div class="main">
<div class="image-column"></div>
<div class="text-column">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla varius enim eu justo posuere, a laoreet urna sodales. Mauris ac porta lorem, id malesuada ipsum. In ac ipsum sapien. Nunc nisi tellus, auctor vitae placerat sit amet, posuere id velit. In semper ex placerat purus sollicitudin, at aliquet metus viverra. Nam malesuada vel tellus malesuada fermentum. Curabitur iaculis vel lacus nec scelerisque. Praesent feugiat ac augue bibendum facilisis. Curabitur dapibus malesuada magna sit amet vehicula. Fusce ipsum eros, consectetur in sodales ac, lacinia at purus. Quisque laoreet justo et semper luctus. Nam ligula orci, ultricies et enim non, elementum rutrum massa. Aenean cursus lacus in magna hendrerit, in fermentum ex porttitor. Integer elementum, enim sit amet vehicula mollis, diam tortor congue massa, eget accumsan nulla arcu a leo. Maecenas convallis placerat magna, vitae lacinia mi ullamcorper quis. Etiam congue aliquet dolor eget dignissim. Donec malesuada laoreet nibh, sit amet tristique lacus facilisis nec. Quisque sit amet enim ac lectus bibendum laoreet. Pellentesque eleifend urna eget ultricies commodo. Nulla ex sapien, accumsan sit amet est vitae, pretium sollicitudin metus. Nullam finibus, ipsum id tincidunt tristique, diam tortor pellentesque orci, non rutrum turpis arcu ultricies eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla varius enim eu justo posuere, a laoreet urna sodales. Mauris ac porta lorem, id malesuada ipsum. In ac ipsum sapien. Nunc nisi tellus, auctor vitae placerat sit amet, posuere id velit. In semper ex placerat purus sollicitudin, at aliquet metus viverra. Nam malesuada vel tellus malesuada fermentum. Curabitur iaculis vel lacus nec scelerisque. Praesent feugiat ac augue bibendum facilisis. Curabitur dapibus malesuada magna sit amet vehicula. Fusce ipsum eros, consectetur in sodales ac, lacinia at purus. Quisque laoreet justo et semper luctus. Nam ligula orci, ultricies et enim non, elementum rutrum massa. Aenean cursus lacus in magna hendrerit, in fermentum ex porttitor. Integer elementum, enim sit amet vehicula mollis, diam tortor congue massa, eget accumsan nulla arcu a leo. Maecenas convallis placerat magna, vitae lacinia mi ullamcorper quis. Etiam congue aliquet dolor eget dignissim. Donec malesuada laoreet nibh, sit amet tristique lacus facilisis nec. Quisque sit amet enim ac lectus bibendum laoreet. Pellentesque eleifend urna eget ultricies commodo. Nulla ex sapien, accumsan sit amet est vitae, pretium sollicitudin metus. Nullam finibus, ipsum id tincidunt tristique, diam tortor pellentesque orci, non rutrum turpis arcu ultricies eros.</p>
</div>
</div>
<div class="footer">Footer</div>
</div>
尝试将 .text-column 的高度设置为 260px
.text-column {
height: 260px;
flex: 2 1 420px; /* column width, min for wrapping */
overflow: auto; /* don't scroll */
}
我找到了解决我自己问题的方法。
Grid 有类似的换行方式,使用 repeat 的自动调整,每列的 minmax 是固定宽度。
.main {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
overflow: hidden; /* don't scroll */
}
使用这种方法,当列换行时,第一列的最小高度不再将第二列及其滚动条偏移到容器之外,就像使用弹性换行时那样。
唯一的小缺点是网格的两列宽度必须相等才能进行换行。对于我的使用,这是可以接受的。
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 40px;
padding: 40px;
background: #f6f6f6;
font-family: sans-serif; font-size: 120%; line-height: 1.5; color: #111;
}
.container {
height: 600px;
min-width: 300px;
max-width: 900px;
width: 100%;
display: flex;
flex-direction: column;
background-color: white;
border-radius: 10px;
overflow: hidden; /* don't scroll */
border: 1px solid #ccc;
}
.header {
border-bottom: 1px solid #ccc;
padding: 20px;
}
.main {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
overflow: hidden; /* don't scroll */
}
.image-column {
min-height: 200px;
background-image: url('https://images.unsplash.com/photo-1641361784653-73767ccfdf60?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDM0fDZzTVZqVExTa2VRfHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=900&q=60');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.text-column {
overflow: auto; /* scroll */
padding: 20px;
}
.footer {
border-top: 1px solid #ccc;
padding: 20px;
}
<div class="container">
<div class="header">Header</div>
<div class="main">
<div class="image-column"></div>
<div class="text-column">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla varius enim eu justo posuere, a laoreet urna sodales. Mauris ac porta lorem, id malesuada ipsum. In ac ipsum sapien. Nunc nisi tellus, auctor vitae placerat sit amet, posuere id velit. In semper ex placerat purus sollicitudin, at aliquet metus viverra. Nam malesuada vel tellus malesuada fermentum. Curabitur iaculis vel lacus nec scelerisque. Praesent feugiat ac augue bibendum facilisis. Curabitur dapibus malesuada magna sit amet vehicula. Fusce ipsum eros, consectetur in sodales ac, lacinia at purus. Quisque laoreet justo et semper luctus. Nam ligula orci, ultricies et enim non, elementum rutrum massa. Aenean cursus lacus in magna hendrerit, in fermentum ex porttitor. Integer elementum, enim sit amet vehicula mollis, diam tortor congue massa, eget accumsan nulla arcu a leo. Maecenas convallis placerat magna, vitae lacinia mi ullamcorper quis. Etiam congue aliquet dolor eget dignissim. Donec malesuada laoreet nibh, sit amet tristique lacus facilisis nec. Quisque sit amet enim ac lectus bibendum laoreet. Pellentesque eleifend urna eget ultricies commodo. Nulla ex sapien, accumsan sit amet est vitae, pretium sollicitudin metus. Nullam finibus, ipsum id tincidunt tristique, diam tortor pellentesque orci, non rutrum turpis arcu ultricies eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla varius enim eu justo posuere, a laoreet urna sodales. Mauris ac porta lorem, id malesuada ipsum. In ac ipsum sapien. Nunc nisi tellus, auctor vitae placerat sit amet, posuere id velit. In semper ex placerat purus sollicitudin, at aliquet metus viverra. Nam malesuada vel tellus malesuada fermentum. Curabitur iaculis vel lacus nec scelerisque. Praesent feugiat ac augue bibendum facilisis. Curabitur dapibus malesuada magna sit amet vehicula. Fusce ipsum eros, consectetur in sodales ac, lacinia at purus. Quisque laoreet justo et semper luctus. Nam ligula orci, ultricies et enim non, elementum rutrum massa. Aenean cursus lacus in magna hendrerit, in fermentum ex porttitor. Integer elementum, enim sit amet vehicula mollis, diam tortor congue massa, eget accumsan nulla arcu a leo. Maecenas convallis placerat magna, vitae lacinia mi ullamcorper quis. Etiam congue aliquet dolor eget dignissim. Donec malesuada laoreet nibh, sit amet tristique lacus facilisis nec. Quisque sit amet enim ac lectus bibendum laoreet. Pellentesque eleifend urna eget ultricies commodo. Nulla ex sapien, accumsan sit amet est vitae, pretium sollicitudin metus. Nullam finibus, ipsum id tincidunt tristique, diam tortor pellentesque orci, non rutrum turpis arcu ultricies eros.</p>
</div>
</div>
<div class="footer">Footer</div>
</div>
(您可以 运行 下面的代码片段来查看环绕的布局,然后按整页查看处于宽 2 列状态的布局。)
在固定高度的容器中,我有一个带有 flex-direction: row 和 flex-wrap: wrap 的 flexbox (.main)。在宽屏幕尺寸下,我希望它的子项 — 图像 (.image-column) 和大量文本 (.text-column) — 成为列,其中图像保持静态,文本滚动。到目前为止,一切都很好。当尺寸缩小超过列的最小宽度时,我希望它们环绕和堆叠。这一切都有效,但问题在于:当它们换行和堆叠时,可滚动文本会偏移其上方 .image-column 的最小高度,这样当您向下滚动到文本底部时,滚动条就会消失离开屏幕而不是留在其容器内。但是,如果您调整高度以解决此偏移量,则 .text-column 在展开状态下会被压扁。
两个相互矛盾的元素似乎是:
- .image-column's min-height: 200px — 但如果没有这个,图像在包裹时根本不会显示
- .text-column's height: 100% — 但没有这个,文本不会滚动
我试过 .text-column with height: calc(100% - 200px) — 这修复了堆叠时的偏移量,但在列中时会产生不必要的空白,无论如何我宁愿避免这种特殊性
我想找到一个只有 CSS 而 没有媒体查询 的解决方案,因为这个容器可能与其他容器处于多列布局中。我愿意使用 flex、grid、float 或任何其他神秘的布局技巧。
有没有其他人遇到过弹性换行和滚动的这个问题?
(您可以 运行 下面的代码片段查看换行的布局,然后按整页查看处于宽 2 列状态的布局。)
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 40px;
padding: 40px;
background: #f6f6f6;
font-family: sans-serif; font-size: 120%; line-height: 1.5; color: #111;
}
.container {
height: 600px;
min-width: 300px;
max-width: 900px;
width: 100%;
display: flex;
flex-direction: column;
background-color: white;
border-radius: 10px;
overflow: hidden; /* don't scroll */
border: 1px solid #ccc;
}
.header {
border-bottom: 1px solid #ccc;
padding: 20px;
}
.main {
flex: 1 1 auto; /* fills remainder of height */
display: flex;
flex-direction: row;
flex-wrap: wrap; /* wrap after elements reach min-width / flex-basis */
overflow: hidden; /* don't scroll */
}
.image-column {
min-height: 200px;
flex: 1 1 300px; /* column width, min for wrapping */
background-image: url('https://images.unsplash.com/photo-1641361784653-73767ccfdf60?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDM0fDZzTVZqVExTa2VRfHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=900&q=60');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.text-column {
height: 100%;
flex: 2 1 420px; /* column width, min for wrapping */
overflow: auto; /* scroll */
padding: 20px;
}
.footer {
border-top: 1px solid #ccc;
padding: 20px;
}
<div class="container">
<div class="header">Header</div>
<div class="main">
<div class="image-column"></div>
<div class="text-column">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla varius enim eu justo posuere, a laoreet urna sodales. Mauris ac porta lorem, id malesuada ipsum. In ac ipsum sapien. Nunc nisi tellus, auctor vitae placerat sit amet, posuere id velit. In semper ex placerat purus sollicitudin, at aliquet metus viverra. Nam malesuada vel tellus malesuada fermentum. Curabitur iaculis vel lacus nec scelerisque. Praesent feugiat ac augue bibendum facilisis. Curabitur dapibus malesuada magna sit amet vehicula. Fusce ipsum eros, consectetur in sodales ac, lacinia at purus. Quisque laoreet justo et semper luctus. Nam ligula orci, ultricies et enim non, elementum rutrum massa. Aenean cursus lacus in magna hendrerit, in fermentum ex porttitor. Integer elementum, enim sit amet vehicula mollis, diam tortor congue massa, eget accumsan nulla arcu a leo. Maecenas convallis placerat magna, vitae lacinia mi ullamcorper quis. Etiam congue aliquet dolor eget dignissim. Donec malesuada laoreet nibh, sit amet tristique lacus facilisis nec. Quisque sit amet enim ac lectus bibendum laoreet. Pellentesque eleifend urna eget ultricies commodo. Nulla ex sapien, accumsan sit amet est vitae, pretium sollicitudin metus. Nullam finibus, ipsum id tincidunt tristique, diam tortor pellentesque orci, non rutrum turpis arcu ultricies eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla varius enim eu justo posuere, a laoreet urna sodales. Mauris ac porta lorem, id malesuada ipsum. In ac ipsum sapien. Nunc nisi tellus, auctor vitae placerat sit amet, posuere id velit. In semper ex placerat purus sollicitudin, at aliquet metus viverra. Nam malesuada vel tellus malesuada fermentum. Curabitur iaculis vel lacus nec scelerisque. Praesent feugiat ac augue bibendum facilisis. Curabitur dapibus malesuada magna sit amet vehicula. Fusce ipsum eros, consectetur in sodales ac, lacinia at purus. Quisque laoreet justo et semper luctus. Nam ligula orci, ultricies et enim non, elementum rutrum massa. Aenean cursus lacus in magna hendrerit, in fermentum ex porttitor. Integer elementum, enim sit amet vehicula mollis, diam tortor congue massa, eget accumsan nulla arcu a leo. Maecenas convallis placerat magna, vitae lacinia mi ullamcorper quis. Etiam congue aliquet dolor eget dignissim. Donec malesuada laoreet nibh, sit amet tristique lacus facilisis nec. Quisque sit amet enim ac lectus bibendum laoreet. Pellentesque eleifend urna eget ultricies commodo. Nulla ex sapien, accumsan sit amet est vitae, pretium sollicitudin metus. Nullam finibus, ipsum id tincidunt tristique, diam tortor pellentesque orci, non rutrum turpis arcu ultricies eros.</p>
</div>
</div>
<div class="footer">Footer</div>
</div>
尝试将 .text-column 的高度设置为 260px
.text-column {
height: 260px;
flex: 2 1 420px; /* column width, min for wrapping */
overflow: auto; /* don't scroll */
}
我找到了解决我自己问题的方法。
Grid 有类似的换行方式,使用 repeat 的自动调整,每列的 minmax 是固定宽度。
.main {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
overflow: hidden; /* don't scroll */
}
使用这种方法,当列换行时,第一列的最小高度不再将第二列及其滚动条偏移到容器之外,就像使用弹性换行时那样。
唯一的小缺点是网格的两列宽度必须相等才能进行换行。对于我的使用,这是可以接受的。
body {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 40px;
padding: 40px;
background: #f6f6f6;
font-family: sans-serif; font-size: 120%; line-height: 1.5; color: #111;
}
.container {
height: 600px;
min-width: 300px;
max-width: 900px;
width: 100%;
display: flex;
flex-direction: column;
background-color: white;
border-radius: 10px;
overflow: hidden; /* don't scroll */
border: 1px solid #ccc;
}
.header {
border-bottom: 1px solid #ccc;
padding: 20px;
}
.main {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
overflow: hidden; /* don't scroll */
}
.image-column {
min-height: 200px;
background-image: url('https://images.unsplash.com/photo-1641361784653-73767ccfdf60?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHx0b3BpYy1mZWVkfDM0fDZzTVZqVExTa2VRfHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=900&q=60');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.text-column {
overflow: auto; /* scroll */
padding: 20px;
}
.footer {
border-top: 1px solid #ccc;
padding: 20px;
}
<div class="container">
<div class="header">Header</div>
<div class="main">
<div class="image-column"></div>
<div class="text-column">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla varius enim eu justo posuere, a laoreet urna sodales. Mauris ac porta lorem, id malesuada ipsum. In ac ipsum sapien. Nunc nisi tellus, auctor vitae placerat sit amet, posuere id velit. In semper ex placerat purus sollicitudin, at aliquet metus viverra. Nam malesuada vel tellus malesuada fermentum. Curabitur iaculis vel lacus nec scelerisque. Praesent feugiat ac augue bibendum facilisis. Curabitur dapibus malesuada magna sit amet vehicula. Fusce ipsum eros, consectetur in sodales ac, lacinia at purus. Quisque laoreet justo et semper luctus. Nam ligula orci, ultricies et enim non, elementum rutrum massa. Aenean cursus lacus in magna hendrerit, in fermentum ex porttitor. Integer elementum, enim sit amet vehicula mollis, diam tortor congue massa, eget accumsan nulla arcu a leo. Maecenas convallis placerat magna, vitae lacinia mi ullamcorper quis. Etiam congue aliquet dolor eget dignissim. Donec malesuada laoreet nibh, sit amet tristique lacus facilisis nec. Quisque sit amet enim ac lectus bibendum laoreet. Pellentesque eleifend urna eget ultricies commodo. Nulla ex sapien, accumsan sit amet est vitae, pretium sollicitudin metus. Nullam finibus, ipsum id tincidunt tristique, diam tortor pellentesque orci, non rutrum turpis arcu ultricies eros. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla varius enim eu justo posuere, a laoreet urna sodales. Mauris ac porta lorem, id malesuada ipsum. In ac ipsum sapien. Nunc nisi tellus, auctor vitae placerat sit amet, posuere id velit. In semper ex placerat purus sollicitudin, at aliquet metus viverra. Nam malesuada vel tellus malesuada fermentum. Curabitur iaculis vel lacus nec scelerisque. Praesent feugiat ac augue bibendum facilisis. Curabitur dapibus malesuada magna sit amet vehicula. Fusce ipsum eros, consectetur in sodales ac, lacinia at purus. Quisque laoreet justo et semper luctus. Nam ligula orci, ultricies et enim non, elementum rutrum massa. Aenean cursus lacus in magna hendrerit, in fermentum ex porttitor. Integer elementum, enim sit amet vehicula mollis, diam tortor congue massa, eget accumsan nulla arcu a leo. Maecenas convallis placerat magna, vitae lacinia mi ullamcorper quis. Etiam congue aliquet dolor eget dignissim. Donec malesuada laoreet nibh, sit amet tristique lacus facilisis nec. Quisque sit amet enim ac lectus bibendum laoreet. Pellentesque eleifend urna eget ultricies commodo. Nulla ex sapien, accumsan sit amet est vitae, pretium sollicitudin metus. Nullam finibus, ipsum id tincidunt tristique, diam tortor pellentesque orci, non rutrum turpis arcu ultricies eros.</p>
</div>
</div>
<div class="footer">Footer</div>
</div>
(您可以 运行 下面的代码片段来查看环绕的布局,然后按整页查看处于宽 2 列状态的布局。)