This appears to be a bug.
Analysis
You are using align-self: end
to pin the middle grid item (ul
) to the bottom of the row. That fails to render a vertical scrollbar.
I tried various alternatives:
I made the ul
grid item a flex container with flex-direction: column
and justify-content: flex-end
.
I made the ul
grid item a flex container with flex-direction: column
and applied margin-top: auto
to the first li
flex item.
I tried switching from
grid-template-rows: 50px auto 50px
to
grid-template-rows: 50px 1fr 50px
Nothing worked. In all cases, the browser failed to generate a vertical scrollbar.
However, in all cases, when there is no "end" alignment (in other words, the grid item is aligned to the default "start" position), vertical scroll works fine.
Because the scrollbar works in "start" but fails in "end", I think it's fair to call this a bug.
Here's the same problem in flexbox: Can't get vertical scrollbar with justify-content: flex-end
Solution #1: Chrome only
If you make the ul
grid item a (nested) grid container with align-content: end
, that seems to work in Chrome, but not Firefox and Edge. I didn't test in Safari, IE11 or other browsers.
#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
Solution #2: All browsers
This solution takes advantage of the fact that vertical scroll works fine with items in the start
position. You can insert another li
or, even better, a pseudo-element (as they are considered grid items when applied to grid containers). This li
will be empty and set to occupy all free space, which will pin the actual items to the bottom.
#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