在 CSS 网格布局中为每一列添加滚动
Posted
技术标签:
【中文标题】在 CSS 网格布局中为每一列添加滚动【英文标题】:Add scroll to each column in CSS Grid Layout 【发布时间】:2017-10-08 07:39:29 【问题描述】:我想在我的网格布局中的每一列上单独滚动。
目前,我正在开发一个仅限移动设备的 Web 应用程序。我想为纵向和横向使用不同的网格布局。
纵向只有 1 列,每个元素一个接一个。这里没问题。
在横向中,我想使用 2 列。我的全部内容显示在左侧,我的导航移动到右侧。现在我希望这两个部分都有一个单独的卷轴。有没有办法实现这个?如果当前列的内容结束,滚动应该停止。
CodePen 上的代码:https://codepen.io/SuddenlyRust/pen/rmJOqV
.grid-container
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
grid-gap: 15px 0;
header
background-color: green;
grid-column: 1;
grid-row: 1
main
background-color: blue;
grid-column: 1;
grid-row: 2;
nav
background-color: pink;
grid-column: 1;
grid-row: 3;
footer
background-color: teal;
grid-column: 1;
grid-row: 4;
@media only screen and (orientation: landscape)
.grid-container
grid-template-columns: 5fr 4fr;
nav
grid-column: 2;
grid-row: 1 / span 3;
footer
grid-row: 3;
h1
min-height: 200px;
<div class="grid-container">
<header>
<h1>Logo</h1>
</header>
<main>
<h1>content</h1>
</main>
<nav>
<h1>Navigation</h1>
</nav>
<footer>
<h1>Footer</h1>
</footer>
</div>
非常感谢您的宝贵时间!
【问题讨论】:
【参考方案1】:这是来自my answer on your earlier question 的扩展版本,如何使用flexbox
获得标题/内容/主目录和导航的滚动。
Fiddle demo
堆栈sn-p
(function(w, d, timeout)
w.addEventListener("load", function()
resizer();
, false);
w.addEventListener("resize", function()
if (!timeout)
timeout = setTimeout(function()
timeout = null;
// do resize stuff
resizer();
, 66);
, false);
function resizer()
if (w.innerHeight < w.innerWidth)
if (!(d.body.classList.contains('landscape')))
d.body.classList.add('landscape');
d.body.appendChild(d.querySelector('nav'));
else
if (d.body.classList.contains('landscape'))
d.body.classList.remove('landscape')
d.querySelector('section').appendChild(d.querySelector('nav'));
(window, document));
html, body
margin:0;
header, footer, main, nav
margin: 5px;
padding: 5px;
border-radius: 5px;
min-height: 120px;
border: 1px solid #eebb55;
background: #ffeebb;
footer
order: 2;
nav
order: 1;
section
display: flex;
flex-direction: column;
@media only screen and (orientation: landscape)
main div
height: 400px;
border: 1px dashed red;
nav div
height: 800px;
border: 1px dashed red;
body.landscape
display: flex;
section
display: block;
width: calc(60% - 10px); /* 10px is for the margin */
box-sizing: border-box;
max-height: calc(100vh - 20px);
overflow: auto;
nav
width: calc(40% - 10px); /* 10px is for the margin */
box-sizing: border-box;
max-height: calc(100vh - 20px);
overflow: auto;
<section>
<header>header</header>
<main>content
<div>
This div get a height when in landscape to show scroll in section
</div>
</main>
<footer>footer</footer>
<nav>navigation
<div>
This div get a height when in landscape to show scroll in nav
</div>
</nav>
</section>
【讨论】:
是的,干得好@LGSon。这很完美。我能问你一些基本的问题吗?我对javascript不太熟练。第一部分和最后一部分实际上是做什么的? “(函数(d,超时)”和“(文档));”您总是使用变量 d 来操作 dom,但它是如何定义的?我不明白语法。而且我没有得到超时变量。对我来说就像魔术一样。该代码确实有意义,您如何在树周围移动导航部分。 @SuddenlyRust(function(d, timeout) ...)();
调用一个闭包并包装其中的内容,这样它就不会用变量和其他东西污染全局范围。它使用最后一个(document)
执行自身,其中document
(DOM 的文档)作为第一个参数d
传入。我这样做是为了代替写document.body
等,我可以使用较短的d.body
。 timeout
用于调整大小事件,因为它是这样传入的,作为参数,它可以通过整个闭包函数访问,就像全局变量一样。希望这是有道理的。
是的,谢谢。要学的东西太多了;)真的很珍惜你的时间。祝你有个美好的一天。我要用jQuery重写它哈哈。所以我可以更容易理解它。但我想我可以使用你的解决方案。它工作得很好
@SuddenlyRust 我建议不要重写 resize 处理程序部分并使用 jQuery resize 事件,因为它没有我的 throttler 功能,除非你添加等效插件当然在。我提供的纯 javascript 对性能的影响尽可能小,并且没有真正的理由 jQuery-fy 它。
@SuddenlyRust 类似这样的东西:codepen.io/anon/pen/PmdJGR ... 虽然使用 jQuery 和纯 javascript 都很好。关于动画事件,这里有一篇好文章:sitepoint.com/css3-animation-javascript-event-handlers【参考方案2】:
在横向我想使用 2 列。我的全部内容显示在左侧,我的导航移到右侧。现在我希望这两个部分都有一个单独的卷轴。有没有办法实现这个?如果当前列的内容结束,滚动应该停止。
在左列中有三个单独的网格项:header
、main
和 footer
元素。
在右列中有一个网格项:nav
元素。
向左列添加滚动条(垂直或水平)是不可行的,因为存在三个单独的元素。您需要将所有元素包装在一个容器中以使单个滚动条起作用。
在右列添加滚动条(垂直或水平)非常简单,因为只有一个元素。
假设您在谈论垂直滚动条,这里有一种方法可以使它工作:
body
margin: 0;
.grid-container
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr;
grid-gap: 15px 0;
height: 100vh;
header
background-color: green;
grid-column: 1;
grid-row: 1
main
background-color: blue;
grid-column: 1;
grid-row: 2;
nav
background-color: pink;
grid-column: 1;
grid-row: 3;
overflow: auto;
footer
background-color: teal;
grid-column: 1;
grid-row: 4;
@media only screen and (orientation: landscape)
.grid-container
grid-template-columns: 5fr 4fr;
grid-template-rows: 1fr 1fr 1fr;
nav
grid-column: 2;
grid-row: 1 / span 3;
footer
grid-row: 3;
<div class="grid-container">
<header>
<h1>Logo</h1>
</header>
<main>
<h1>content</h1>
</main>
<nav>
<h1>Navigation<br><br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br>nav item<br></h1>
</nav>
<footer>
<h1>Footer</h1>
</footer>
</div>
revised codepen
浏览器支持 CSS 网格
Chrome - 自 2017 年 3 月 8 日起提供全面支持(版本 57) Firefox - 自 2017 年 3 月 6 日起提供全面支持(版本 52) Safari - 自 2017 年 3 月 26 日起全面支持(版本 10.1) Edge - 自 2017 年 10 月 16 日起提供全面支持(版本 16) IE11 - 不支持当前规范;支持过时版本这是完整的图片:http://caniuse.com/#search=grid
【讨论】:
非常感谢@Michael_B 抽出宝贵时间。但是这个解决方案只有在导航大于左侧内容时才有效。我的导航只占用左侧内容的一半空间。我不确定这是否真的适用于网格布局。 几乎可以使用。但是,如果我在左侧滚动,我的导航就会消失。有没有办法把左边的内容包装在一起? 如果您可以将左侧元素包装在一个容器中,那么一切都会变得容易得多。只需使用弹性盒。 codepen.io/anon/pen/jmZgEo?editors=1100 是的,谢谢。那是我使用 flex 的下一个想法。看起来网格不适合我的解决方案!非常感谢您抽出宝贵时间@Michael_B,您帮了大忙;)以上是关于在 CSS 网格布局中为每一列添加滚动的主要内容,如果未能解决你的问题,请参考以下文章
在 CSS 网格布局中使用 *ngFor 不希望地在一列中显示所有内容