Search code examples
htmlcssflexboxcss-grid

CSS horizontally scrolling flex box within grid


Disclaimer: I have read through a ton of almost my use case but not found exactly the same so:

I want to have a grid with a fixed width left sidebar and the right content column should just fill the rest of the window but not more.

I have it working in a "pure" flex box layout but for some weird reason not within a grid.

What happens is that the flex item will just make the entire grid wider than the window and scroll the entire thing.

What I want is that only the flex container scrolls and the headline above stays where it is.

<style media="screen">
  * {
    margin: 0;
    padding: 0;
  }
  body {
    height: 100%;
  }
  sidebar {
    background-color: red;
    display: block;
  }
  main {
    display: grid;
    grid-template-columns: 300px auto;
    width: 100vw;
  }
  content {
    background-color: blue;
    display: block;
  }
  image-container-wrapper {
    display: block;
    overflow: scroll;
  }
  image-container {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
  }
  my-image {
    display: block;
    flex: 0 0 auto;
    margin-right: 3px;
    min-width: 100px;
    min-height: 100px;
    background-color: grey;
  }
</style>


<header>Header</header>
<main>
  <sidebar>This should be "fixed"
  </sidebar>
  <content>
    <h1>Slider below</h1>
    <image-container-wrapper>
      <image-container>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
        <my-image></my-image>
      </image-container>
    </image-container-wrapper>
  </content>
</main>
<footer></footer>

Solution

  • Instead of:

    grid-template-columns: 300px auto
    

    where auto means content-length, and will expand an element to fit the content (i.e., no overflow)...

    Use this:

    grid-template-columns: 300px minmax(0px, auto)
    

    which allows the column to shrink to 0 width.

    sidebar {
      background-color: red;
      /* display: block; */
    }
    
    main {
      display: grid;
      /* grid-template-columns: 300px auto; */
      grid-template-columns: 300px minmax(0px, auto);
      width: 100vw;
    }
    
    content {
      background-color: blue;
      display: block;
    }
    
    image-container-wrapper {
      /*  display: block;
            overflow: scroll; */
    }
    
    image-container {
      display: flex;
      flex-wrap: nowrap;
      overflow-x: auto;
    }
    
    my-image {
      display: block;
      flex: 0 0 auto;
      margin-right: 3px;
      min-width: 100px;
      min-height: 100px;
      background-color: grey;
    }
    
    * {
      margin: 0;
      padding: 0;
    }
    
    body {
      height: 100%;
    }
    <header>Header</header>
    <main>
      <sidebar>This should be "fixed"</sidebar>
      <content>
        <h1>Slider below</h1>
        <image-container-wrapper>
          <image-container>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
            <my-image></my-image>
          </image-container>
        </image-container-wrapper>
      </content>
    </main>
    <footer></footer>