Search code examples
htmlcssoverflowcss-grid

How to Enable Scrolling for Overflowing Content in a CSS Grid Layout?


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.


Solution

  • 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.