Nested, centered, CSS grid column appears off the screen in the negative X axis, even with "overflow-x: scroll"

The requirement here is to display a series of nested, centered CSS grid items. We're rendering something like a hierarchical tree, with the head node on top, then second level nodes, third level nodes, and so on.

The problem is that later levels run off the div in the negative and positive X-axis directions.

Setting overflow-x: scroll solves the problem only for the positive X-axis direction. That is to say, you can scroll to the right, but not to the left.

The example below is a greatly simplified example of the real problem I'm trying to address. The red element on the 3rd level is off the page in the negative X-axis. You can scroll to the right, but not the left.

Image of problem

What can be done to make it so the entire tree, and all nodes, are able to be scrolled to?

Code follows(Link to JS Fiddle.):

#tree {
  overflow-x: scroll;
}

.flex-col {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.grid {
  display: grid;
}

.content {
  width: 300px;
  border-radius: 5px;
  background-color: blue;
  color: white
}
<div id="tree" class="flex-col">
  <div class="content">Content</div>
  <div class="grid">
    <div class="flex-col" style="grid-column: 1">
      <div class="content">Content</div>
      <div class="grid">
        <div class="flex-col" style="grid-column: 1;">
          <div class="content" style="background-color: red;">** This is off the screen **</div>
        </div>
        <div class="flex-col" style="grid-column: 2">
          <div class="content">Content</div>
        </div>
      </div>
    </div>
    <div class="flex-col" style="grid-column: 2">
      <div class="content">Content</div>
      <div class="grid">
        <div class="flex-col" style="grid-column: 1">
          <div class="content">Content</div>
        </div>
        <div class="flex-col" style="grid-column: 2">
          <div class="content">Content</div>
        </div>
      </div>
    </div>
  </div>
</div>

2 answers

  • answered 2019-05-15 03:17 Obsidian Age

    You need to make sure that the grid elements don't expand wider than their container.

    To resolve this, you can set max-width: 100% on .grid:

    #tree {
      overflow-x: scroll;
    }
    
    .flex-col {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    
    .grid {
      display: grid;
      max-width: 100%;
    }
    
    .content {
      width: 300px;
      border-radius: 5px;
      background-color: blue;
      color: white
    }
    <div id="tree" class="flex-col">
      <div class="content">Content</div>
      <div class="grid">
        <div class="flex-col" style="grid-column: 1">
          <div class="content">Content</div>
          <div class="grid">
            <div class="flex-col" style="grid-column: 1;">
              <div class="content" style="background-color: red;">** This is off the screen **</div>
            </div>
            <div class="flex-col" style="grid-column: 2">
              <div class="content">Content</div>
            </div>
          </div>
        </div>
        <div class="flex-col" style="grid-column: 2">
          <div class="content">Content</div>
          <div class="grid">
            <div class="flex-col" style="grid-column: 1">
              <div class="content">Content</div>
            </div>
            <div class="flex-col" style="grid-column: 2">
              <div class="content">Content</div>
            </div>
          </div>
        </div>
      </div>
    </div>

  • answered 2019-05-15 04:51 kukkuz

    You can create an extra wrapper inside the tree element which will be an inline flexbox container so that it takes as much space as its contents. Use text-align: center to center the tree when there is no scroll - see demo below:

    #tree {
      overflow-x: auto; /* overflow horizontally here */
      text-align: center; /* align horizontally */
    }
    
    #tree > .flex-col {
      display: inline-flex; /* inline flex container */
      text-align: initial; /* reset text align to default left */
    }
    
    .flex-col {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    
    .grid {
      display: grid;
    }
    
    .content {
      width: 300px;
      border-radius: 5px;
      background-color: blue;
      color: white
    }
    <div id="tree">
      <div class="flex-col"> <!-- <-- extra wrapper -->
        <div class="content">Content</div>
        <div class="grid">
          <div class="flex-col" style="grid-column: 1">
            <div class="content">Content</div>
            <div class="grid">
              <div class="flex-col" style="grid-column: 1;">
                <div class="content" style="background-color: red;">** This is off the screen **</div>
              </div>
              <div class="flex-col" style="grid-column: 2">
                <div class="content">Content</div>
              </div>
            </div>
          </div>
          <div class="flex-col" style="grid-column: 2">
            <div class="content">Content</div>
            <div class="grid">
              <div class="flex-col" style="grid-column: 1">
                <div class="content">Content</div>
              </div>
              <div class="flex-col" style="grid-column: 2">
                <div class="content">Content</div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>