5

I'm trying to prevent the sidebar height from exceeding the content height.
The "area" will contain an image of any height so its height is not fixed or known in advance.

function toggleTabsContent() {
 const display = document.querySelector('.content').style.display;
  if (display == "none") {
   document.querySelector('.content').style.display = "block";
  } else {
   document.querySelector('.content').style.display = "none";
  }
}
.grid {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: 1fr auto;
  grid-template-areas:
    "tabs area"
    "footer footer";
}

.tabs {
  grid-area: tabs;
  background: #FF9800;
}

.area {
  grid-area: area;
  height: 200px;
  background: #673AB7;
}

.footer {
  grid-area: footer;
  background: #607D8B;
  height: 40px;
}

.content {
  height: 250px;
}
<button onclick="toggleTabsContent()">Make tabs taller/shorter</button>

<div class="grid">
  <div class="tabs">
    <div class="content" style="display: none"></div>
  </div>
  <div class="area"></div>
  <div class="footer"></div>
</div>

JSFiddle

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
unloco
  • 6,928
  • 2
  • 47
  • 58
  • " want to show scrollbar when the "tabs" height is more than the "area" height." do you mean on right of sidebar? – M A Salman Mar 26 '20 at 21:43

4 Answers4

2

Display: flex; allows for a lot of flexibility - in fact it's purpose is exactly to flex the height or width to the required dimensions per the content inside of it.

Based on your question, this is exactly what you need.

I've separated your footer from the grid, in order to separate statically sized elements, from those you wish to flex.

Next I've added a min-width to your area, to avoid it collapsing completely. However if you want this functionality, you can remove this. i.e. if you want that when there is no image it doesn't appear, you can remove this.

Lastly, the display: flex; and flex-flow: row nowrap; allows the sizing to flex, and for elements within the grid (now named "flex") to be placed next to each other with the same dimensions and they won't wrap to the next line to accommodate the sizing changes.

function toggleTabsContent() {
  const display = document.querySelector('.content').style.display;
  if (display == "none") {
    document.querySelector('.content').style.display = "block";
  } else {
    document.querySelector('.content').style.display = "none";
  }
}
.flex {
  display: flex;
  flex-flow: row nowrap;
}

.tabs {
  background: #FF9800;
  height: auto;
  width: 100%;
}

.area {
  height: auto;
  min-height: 200px;
  width: 100%;
  background: #673AB7;
}

.footer {
  background: #607D8B;
  height: 40px;
}

.content {
  height: 400px;
}
<button onclick="toggleTabsContent()">Make tabs taller/shorter</button>

<div class="flex">
  <div class="tabs">
    <div class="content" style="display: none"></div>
  </div>
  <div class="area"></div>
</div>
<div class="footer"></div>
cmprogram
  • 1,854
  • 2
  • 13
  • 25
1

Use height:0;min-height:100%; on the tabs element. This will make sure the height of the element will not contribute on the size of its track then by adding min-height:100% you force it to use the height of the track defined by other elements:

function toggleTabsContent() {
 const display = document.querySelector('.content').style.display;
  if (display == "none") {
   document.querySelector('.content').style.display = "block";
  } else {
   document.querySelector('.content').style.display = "none";
  }
}
.grid {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: 1fr auto;
  grid-template-areas:
    "tabs area"
    "footer footer";
}

.tabs {
  grid-area: tabs;
  background: #FF9800;
  height:0;
  min-height:100%;
  overflow:auto;
}

.area {
  grid-area: area;
  height: 200px;
  background: #673AB7;
}

.footer {
  grid-area: footer;
  background: #607D8B;
  height: 40px;
}

.content {
  height: 250px;
}
<button onclick="toggleTabsContent()">Make tabs taller/shorter</button>

<div class="grid">
  <div class="tabs">
    <div class="content" style="display: none"></div>
  </div>
  <div class="area"></div>
  <div class="footer"></div>
</div>

Related question: How can you set the height of an outer div to always be equal to a particular inner div?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
0

You can set the max-height of tabs to be the height of area

.tabs {
  grid-area: tabs;
  background: #FF9800;
  max-height: 400px;
  overflow: scroll;
}

I added lot of H1 elements and it worked the way you wanted it.

JS Fiddle

  • The area height is not fixed as I mentioned, so I can't use `400px` in this case – unloco Feb 29 '20 at 08:58
  • @UnLoCo if you don't know the area height why not use min-height? This way the sidebar will always show something. Or you can set sidebar min-height... – Leon Vuković Mar 27 '20 at 06:41
0

You should go the flex route, but if the only content in .tabs is an image, you can set it as a background-image and let it automatically fill the area with background-size: cover.

document.getElementById("slider").addEventListener('change', changeAreaHeight);

function changeAreaHeight(event) {
  let sliderValue = event.target.value;
  document.querySelector('.area').style.height = sliderValue + 'px';
}
.grid {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-rows: 1fr auto;
  grid-template-areas:
    "tabs area"
    "footer footer";
}

.tabs {
  grid-area: tabs;
  background: #FF9800;
  background-image: url('https://i.picsum.photos/id/167/100/300.jpg'); /* NEW */
  background-size: cover; /* NEW */
}

.area {
  grid-area: area;
  height: 200px;
  background: #673AB7;
}

.footer {
  grid-area: footer;
  background: #607D8B;
  height: 40px;
}
<input type="range" id="slider" min="50" value="200" max="800" />
<label>Change height on .area</label>

<div class="grid">
  <div class="tabs">
    <div class="content" style="display: none"></div>
  </div>
  <div class="area"></div>
  <div class="footer"></div>
</div>
Rickard Elimää
  • 7,107
  • 3
  • 14
  • 30