【问题标题】:Add scroll to each column in CSS Grid Layout在 CSS 网格布局中为每一列添加滚动
【发布时间】: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>

非常感谢您的宝贵时间!

【问题讨论】:

    标签: html css flexbox css-grid


    【解决方案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.bodytimeout 用于调整大小事件,因为它是这样传入的,作为参数,它可以通过整个闭包函数访问,就像全局变量一样。希望这是有道理的。
    • 是的,谢谢。要学的东西太多了;)真的很珍惜你的时间。祝你有个美好的一天。我要用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 列。我的全部内容显示在左侧,我的导航移到右侧。现在我希望这两个部分都有一个单独的卷轴。有没有办法实现这个?如果当前列的内容结束,滚动应该停止。

    在左列中有三个单独的网格项:headermainfooter 元素。

    在右列中有一个网格项: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,您帮了大忙;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 2015-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-14
    • 2019-05-19
    相关资源
    最近更新 更多