Hello StackOverflow Community,
I’m currently working on a HTML/CSS project where I have a 3 column grid layout. The left column contains a terminal-like interface with an output area and an input area. The output area () contains paragraphs of text that often exceed the available vertical space.
Here’s a simplified version of my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocket Game Client</title>
</head>
<style>
html,
body {
height: 100vh;
width: 100vw;
margin: 0;
padding: 0;
}
.three-columns {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
display: grid;
grid-template-columns: 1fr auto 1fr;
}
.split {
height: 100%;
width: 100%;
}
.horizontal-gutter {
height: 100%;
width: 20px;
background-color: black;
}
.terminal {
width: 100%;
height: 100%;
display: grid;
grid-template-rows: 1fr auto;
background-color: rgb(46, 46, 46);
font-family: "Roboto Mono", monospace;
font-size: 16px;
overflow: hidden;
}
.output-buffer {
width: 100%;
height: 100%;
overflow-y: auto;
overflow-x: auto;
color: white;
}
.input-wrapper {
width: 100%;
display: grid;
grid-template-columns: auto 1fr;
background-color: rgb(69, 64, 64);
padding: 5px;
}
.command-input {
height: 100%;
width: 100%;
background-color: rgb(69, 64, 64);
border: none;
color: white;
font-family: "Roboto Mono", monospace;
font-size: 16px;
}
</style>
<body>
<div id="main" class="three-columns">
<div id="split-1" class="split">
<div class="terminal">
<div id="output" class="output-buffer">
<p>This is an output buffer that is expected to have scrollbars on this div when the content exceeds its size. Instead it expands. 😒</p>
<!-- Repeated content will be generated here by JavaScript -->
</div>
<div id="input" class="input-wrapper">
<input id="command-input" type="text" placeholder="> command" autocomplete="off" class="command-input" />
</div>
</div>
</div>
<div class="horizontal-gutter"></div>
<div id="split-2" class="split">
<div style="background-color: rgb(72, 0, 0); height: 100%; width: 100%;" />
</div>
</div>
<script>
// Get the output buffer element
var outputBuffer = document.getElementById('output');
// Generate many paragraphs of psuedo-content
// to overflow the output buffer and show the problem
for (var i = 0; i < 50; i++) {
var p = document.createElement('p');
p.textContent = 'All your base are belong to us!';
outputBuffer.appendChild(p);
}
</script>
</body>
My intention is for the output-buffer div to have appropriate scrollbars when the content doesn’t fit. However, instead of showing a scrollbar, the div just expands its size to accommodate the extra content.
I’ve tried using overflow: auto; and height: 100%; on the output-buffer, but it doesn’t work as expected. Instead of the div becoming scrollable, it just expands its size. At least in the vertical as (sometimes, depending on different approaches) too-wide content does provide a horizontal scrollbar as expected (shrink browser window width to see this).
How can I modify my CSS so that the output-buffer becomes scrollable when the content overflows, and doesn’t expand its size?
Any help would be greatly appreciated!
Thank you in advance.
2
Answers
The fundamental problem is that Grid layout has an odd behavior when it comes to nested divs and overflow. This might be by design or a gray area in terms of implementation in browsers. I can find no spec that suggests this is correct so far.
The achieve the proper behavior, use flex layout instead. This seems to respect overflow of inner divs just fine.
Using overflow-y: auto; is the right thing to do to add scrolling, now you just need to set a max-height. Right now it can’t add scrolling when the div gets too big, because it doesn’t know what "too big" is.
Try something like-
Edit: If it has to be dynamically sized, try view height instead of pixels, like this-