当网格项目对齐到末尾/底部时滚动不起作用

Scroll doesn't work when grid item aligned to the end / bottom

我想使用 CSS grid 和 运行 创建聊天,解决我无法组合 align-self: end;overflow-y: auto; 的问题。

ul 包含所有消息,并且应该与底部对齐,这样即使只有一条消息,它也会出现在底部。

聊天的 header 和页脚是固定的,您只能滚动浏览消息(例如 Whats App 和类似的应用程序)。

我用一些消息创建了 this pen。消息通过 header 并且它永远不允许我滚动。

html,
body {
  margin: 0;
  height: 100%;
}

#chat {
  display: grid;
  height: inherit;
  grid-template-rows: 50px auto 50px;
}

header,
footer {
  background: #4081ff;
}

ul {
  overflow-y: auto;
  align-self: end;
}
<section id="chat">
  <header>header</header>
  <ul>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>last message</li>
  </ul>
  <footer>footer</footer>
</section>

这似乎是一个错误。

分析

您正在使用 align-self: end 将中间的网格项目 (ul) 固定到行的底部。无法呈现垂直滚动条。

我尝试了多种选择:

  1. 我将 ul 网格项制作为带有 flex-direction: columnjustify-content: flex-end 的弹性容器。

  2. 我用 flex-direction: columnul 网格项目设为弹性容器,并将 margin-top: auto 应用于第一个 li 弹性项目。

  3. 我尝试从

    切换
    grid-template-rows: 50px auto 50px
    

    grid-template-rows: 50px 1fr 50px
    

没有任何效果。在所有情况下,浏览器都无法生成垂直滚动条。

但是,在所有情况下,当没有 "end" 对齐时(换句话说,网格项对齐到默认的 "start" 位置),垂直滚动效果很好。

因为滚动条在 "start" 中有效但在 "end" 中失败,我认为将其称为错误是公平的。

Flexbox 也有同样的问题:Can't get vertical scrollbar with justify-content: flex-end


解决方案 #1:仅 Chrome

如果您使 ul 网格项成为具有 align-content: end 的(嵌套)网格容器,这似乎在 Chrome 中有效,但在 Firefox 和 Edge 中无效。我没有在 Safari、IE11 或其他浏览器中测试。

#chat {
  display: grid;
  height: 100vh;
  grid-template-rows: 50px 1fr 50px;
}

ul {
  overflow-y: auto;
  display: grid;
  align-content: end;
}

header,
footer {
  background: #4081ff;
}

body {
  margin: 0;
}
<section id="chat">
  <header>header</header>
  <ul>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>last message</li>
  </ul>
  <footer>footer</footer>
</section>

revised codepen


解决方案 #2:所有浏览器

此解决方案利用了垂直滚动可以很好地处理 start 位置的项目这一事实。您可以插入另一个 li 或更好的 pseudo-element(因为它们在应用于网格容器时被视为网格项)。此 li 将为空并设置为占用所有空闲 space,这会将实际项目固定在底部。

#chat {
  display: grid;
  height: 100vh;
  grid-template-rows: 50px auto 50px;
}

ul {
  overflow-y: auto;
  display: grid;
  grid-template-rows: 1fr; /* applies to the first row, the only explicit row;
                              all subsequent rows, which are implicit rows, will
                              take `grid-auto-rows: auto` by default */
}

ul::before {
  content: "";
  border: 1px dashed red; /* demo only */
}

header,
footer {
  background: #4081ff;
}

body {
  margin: 0;
}
<section id="chat">
  <header>header</header>
  <ul>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>last message</li>
  </ul>
  <footer>footer</footer>
</section>

revised codepen

我的滚动条解决方案。我添加了额外的 div.

https://codepen.io/anon/pen/zWaRJY

<section id="chat">
  <header>header</header>
  <div id="content">
  <ul>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>Message 1</li>
    <li>last message</li>
  </ul>
  </div>
  <footer>footer</footer>
</section>

html, body {
  margin: 0;
  height: 100%;
}

#chat {
  display: grid;
  height: inherit;
  grid-template-rows: 50px auto 50px;
}

header, footer {
  background: #4081ff;
}

#content {
  overflow-y: auto;
}

ul {
  display: flex;
  flex-direction: column;
  justify-content: end;
  min-height: 100%;
  margin: 0;
}