Search code examples
htmlcsscss-grid

CSS Grid Layout- horizontal and vertical scrolling only for part of the content


I'm trying to create a layout where I have labels on the left and header at the top which should always be in a fixed position. On the right I have some input elements. If input elements are overflowing there should be a horizontal and vertical scrollbar only for input elements (left labels and header should stay untouched). I only want to use solution with CSS grid for some other reasons. I have tried to make header and left label elements sticky, it kind of worked but I feel like there is more elegant solution. I explicitly set grid-column and grid-row on each element and then wrap my content part (which I want to be scrollable) in a div that span across multiple rows and columns. Now, how can I make this part scrollable? I have tried to set explicit width/height on parent/child elements, I have tried overflow: auto but nothing worked.

HTML

<div class="root">
<div class="header">
Header
</div>

<label class="l1">leg1</label>
<label class="l2">leg2</label>

<label class="label1">Label1</label>
<label class="label11">Label11</label>
<label class="label2">Label2</label>

<div class="content">
<input class="input1" value="test1"/>
<input class="input2" value="test2"/>
<input class="input3" value="test3"/>
</div>


</div>

CSS

.root{
  display:grid;
  grid-template-columns: max-content max-content max-content;
}

.header{
  grid-column: 1 / span 3;
  background: blue;
}

div input{
  height:50px;
}



.content{
  grid-column: 3;
  grid-row: 2 / span 3;
  display: grid;
}

.l1{
  grid-column: 1;
  grid-row: 2 / span 2;
  background: yellow;
}
.l2{
  grid-column: 1;
  grid-row: 4;
  background: green;
}

.label1{
  grid-column: 2;
  grid-row: 2;
  background: teal;
}

.label11{
  grid-column: 2;
  grid-row: 3;
  background: pink;
}

.label2{
  grid-column: 2;
  grid-row: 4;
  background: red;
}

.input1{
 
}
.input2{
 
}

Fiddle:

https://jsfiddle.net/kzu0gf4x/3/ -test1/test2/test3 should be scrollable on overflow, so if I scroll down I should see Header, scrollbar should only be on div with class="content"


Solution

  • Is this helpful?

    /* Scrollbar Customization */
    
    .root .body::-webkit-scrollbar {
      width: 10px;
    }
    
    .root .body::-webkit-scrollbar-track {
      box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
    }
    
    .root .body::-webkit-scrollbar-thumb {
      background-color: darkgrey;
      outline: 1px solid slategrey;
    }
    
    
    /* Scrollbar Customization */
    
    .root {
      display: grid;
      grid-template-columns: max-content max-content max-content;
      border: 1px solid;
      width: fit-content;
    }
    
    .header {
      grid-column: 1 / span 3;
      background: blue;
    }
    
    .root .body {
      display: grid;
      max-height: 130px;
      overflow-y: scroll;
      /* Give overflow-y: scroll to show always Vertical scrollbar */
      overflow-x: auto;
      grid-template-areas: "label b" "label b" "label b";
    }
    
    .labels {
      display: grid;
      grid-area: label;
    }
    
    .content {
      grid-column: 3;
      grid-row: 2 / span 3;
      display: grid;
      grid-template-rows: 1fr 1fr 1fr;
      max-width: 220px;
      overflow: auto;
      grid-area: b;
      height: fit-content;
    }
    
    .content .row {
      display: grid;
      width: 100%;
      grid-auto-flow: column;
    }
    
    div input {
      margin: 0;
      border: 1px solid rgb(218, 218, 218);
      outline: 0;
      padding: 21px 10px;
    }
    
    .l1 {
      grid-column: 1;
      grid-row: 1 / span 3;
      background: yellow;
    }
    
    .l2 {
      grid-column: 1;
      grid-row: 3;
      background: green;
    }
    
    .label1 {
      grid-column: 2;
      grid-row: 1;
      background: teal;
    }
    
    .label11 {
      grid-column: 2;
      grid-row: 2;
      background: pink;
    }
    
    .label2 {
      grid-column: 2;
      grid-row: 3;
      background: red;
    }
    <div class="root">
      <div class="header">
        Header
      </div>
    
      <div class="body">
        <div class="labels">
    
          <label class="l1">leg1</label>
          <label class="l2">leg2</label>
    
          <label class="label1">Label1</label>
          <label class="label11">Label11</label>
          <label class="label2">Label2</label>
        </div>
        <div class="content">
          <div class="row">
            <input class="input1" value="test1">
            <input class="input2" value="test2">
            <input class="input3" value="test3">
          </div>
          <div class="row">
            <input class="input1" value="test1.1">
            <input class="input2" value="test2.1">
            <input class="input3" value="test3.1">
          </div>
          <div class="row">
            <input class="input1" value="test1.2">
            <input class="input2" value="test2.2">
            <input class="input3" value="test3.2">
          </div>
        </div>
    
      </div>
    </div>