1

I am currently working on a layout using flexbox that has two div elements side by side. The main content needs to fill the height and width of the page. However, I am having a problem styling my contents on the left that list my items in a way that the height will not be any larger than the container to the right and will hide any items that go outside of that height range.

I have created a basic example of what is happening in my app with jsfiddle here: https://jsfiddle.net/od09mjgh/9/

As you can see, the items on the left are pushing the page to scroll, but I am hoping to achieve a way to keep them within the container that is the height of its sibling and having the container overflow-y: auto the rest of the items. Is this possible?

Here is the Code to my basic example:

html {
  height: 100%;
}

body {
  margin: 0;
  padding: 0;
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
}

header {
  width: 100%;
  background-color: red;
  height: 50px;
  flex: 0 0 auto;
}

footer {
  width: 100%;
  background-color: purple;
  height: 100px;
  flex: 0 0 auto;
}

main {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

.container {
  width: 100%;
  max-width: 100%;
  padding: 0;
  margin: 0;
  display: flex;
  flex: 1;
}

#map {
  order: 2;
  flex-grow: 1;
  z-index: 5;
  min-height: 400px;
  position: relative;
  height: 100%;
  background-color: green;
}

#results {
  order: 1;
  min-width: 200px;
  max-width: 375px;
  padding: 0;
  z-index: 10;
  display: flex;
}

.result-items {
  overflow-y: auto;
  width: 100%;
}

.result {
  background-color: aqua;
  height: 75px;
  display: block;
  width: 100%;
  border-bottom: 1px solid #000;
}
<header class="header">

</header>
<main>
  <div class="container">
    <div id="map">

    </div>
    <div id="results">
      <div class="extra-div">

      </div>
      <div class="result-items">
        <div id="item-1" class="result">
          <span>Item 1</span>
        </div>
        <div id="item-2" class="result">
          <span>Item 2</span>
        </div>
        <div id="item-3" class="result">
          <span>Item 3</span>
        </div>
        <div id="item-4" class="result">
          <span>Item 4</span>
        </div>
        <div id="item-5" class="result">
          <span>Item 5</span>
        </div>
        <div id="item-6" class="result">
          <span>Item 6</span>
        </div>
        <div id="item-7" class="result">
          <span>Item 7</span>
        </div>
        <div id="item-8" class="result">
          <span>Item 8</span>
        </div>
        <div id="item-9" class="result">
          <span>Item 9</span>
        </div>
        <div id="item-10" class="result">
          <span>Item 10</span>
        </div>
      </div>
    </div>
  </div>
</main>
<footer class="footer">

</footer>
tacoshy
  • 10,642
  • 5
  • 17
  • 34
scapegoat17
  • 5,509
  • 14
  • 55
  • 90

3 Answers3

2

You need a script to do this.

  1. Set the height of left box to "0": #results { height: 0; }. That way it does not interfer by resizing the right side box.

  2. Use an Eventlistener to run the a function after DOM loading: document.addEventListener('DOMContentLoaded', boxResize);

  3. Use also an Eventlistner to run the same function again if the browser is resized to stay "up-to-date": window.addEventListener('resize', boxResize);

  4. Get the height of the right side box in JS with and save it a variable: let divA = document.querySelector("#map").offsetHeight;

  5. resize the left box with the size of the variable: document.querySelector("#results").style.height = divA + "px";

document.addEventListener('DOMContentLoaded', boxResize);
window.addEventListener('resize', boxResize);

function boxResize() {
  let divA = document.querySelector("#map").offsetHeight,
      divB = document.querySelector("#results");
  divB.style.height = divA + "px";
}
html {
  height: 100%;
}

body {
  margin: 0;
  padding: 0;
  height: 100%;
  position: relative;
  display: flex;
  flex-direction: column;
}

header {
  width: 100%;
  background-color: red;
  height: 50px;
  flex: 0 0 auto;
}

footer {
  width: 100%;
  background-color: purple;
  height: 100px;
  flex: 0 0 auto;
}

main {
  flex: 1 0 auto;
  display: flex;
  flex-direction: column;
}

.container {
  width: 100%;
  max-width: 100%;
  padding: 0;
  margin: 0;
  display: flex;
  flex: 1;
}

#map {
  order: 2;
  flex-grow: 1;
  z-index: 5;
  min-height: 400px;
  position: relative;
  height: 100%;
  background-color: green;
}

#results {
  height: 0;
  order: 1;
  min-width: 200px;
  max-width: 375px;
  padding: 0;
  z-index: 10;
  display: flex;
}

.result-items {
  overflow-y: auto;
  width: 100%;
}

.result {
  background-color: aqua;
  height: 75px;
  display: block;
  width: 100%;
  border-bottom: 1px solid #000;
}
<header class="header">

</header>
<main>
  <div class="container">
    <div id="map">

    </div>
    <div id="results">
      <div class="extra-div">

      </div>
      <div class="result-items">
        <div id="item-1" class="result">
          <span>Item 1</span>
        </div>
        <div id="item-2" class="result">
          <span>Item 2</span>
        </div>
        <div id="item-3" class="result">
          <span>Item 3</span>
        </div>
        <div id="item-4" class="result">
          <span>Item 4</span>
        </div>
        <div id="item-5" class="result">
          <span>Item 5</span>
        </div>
        <div id="item-6" class="result">
          <span>Item 6</span>
        </div>
        <div id="item-7" class="result">
          <span>Item 7</span>
        </div>
        <div id="item-8" class="result">
          <span>Item 8</span>
        </div>
        <div id="item-9" class="result">
          <span>Item 9</span>
        </div>
        <div id="item-10" class="result">
          <span>Item 10</span>
        </div>
      </div>
    </div>
  </div>
</main>
<footer class="footer">

</footer>
tacoshy
  • 10,642
  • 5
  • 17
  • 34
  • Thank you! I didn't even think about JS to resolve this. While I try to stay away from using JS to solve styling issues I think in this case it might be unavoidable... – scapegoat17 Mar 30 '21 at 22:14
0

I think I understand the layout you're trying to build. If my understanding is correct, setting the height to 100vh will fix everything for you.

Here's a working example.

   .container {
      height: 100vh;
      width: 100%;
      max-width: 100%;
      padding: 0;
      margin: 0;
      display: flex;
      flex: 1;
    }
Dharman
  • 30,962
  • 25
  • 85
  • 135
Rehan H
  • 314
  • 3
  • 13
  • Thanks for responding! Unfortunately, this is not quite what I am looking for. Your recommended solution pushes the `#map` height out to accommodate `#results`. What I am looking for is the `#map` element to stay the same size and have the `#results` content match its height while letting its items `overflow`. – scapegoat17 Mar 30 '21 at 20:19
  • 1
    In order for the result-items to overflow, it must have or be within a fixed height element. Your requirement is calling for some javascript to be included to get the height of Map and apply that to the results items. Please check @tacoshy solution. – Rehan H Mar 30 '21 at 21:50
0

You needed a height limit on main that would serve as a trigger for the overflow function.

Here's a revised version of the code:

body {
  height: 100vh;
  display: flex;
  flex-direction: column;
  margin: 0;
}

header {
  flex: 0 0 50px;
  background-color: red;
}

footer {
  flex: 0 0 100px;
  background-color: purple;
}

main {
  height: calc(100vh - 150px);  /* less header and footer heights */
  display: flex;
  flex-direction: column;
}

.container {
  display: flex;
  min-height: 0;
}

#map {
  order: 2;
  flex: 1 0 400px;
  z-index: 5;
  position: relative;
  background-color: green;
}

#results {
  order: 1;
  min-width: 200px;
  max-width: 375px;
  padding: 0;
  z-index: 10;
  display: flex;
}

.result-items {
  overflow-y: auto;
  width: 100%;
}

.result {
  background-color: aqua;
  height: 75px;
  border-bottom: 1px solid #000;
}
<header class="header"></header>
<main>
  <div class="container">
    <div id="map"></div>
    <div id="results">
      <div class="extra-div"></div>
      <div class="result-items">
        <div id="item-1" class="result">
          <span>Item 1</span>
        </div>
        <div id="item-2" class="result">
          <span>Item 2</span>
        </div>
        <div id="item-3" class="result">
          <span>Item 3</span>
        </div>
        <div id="item-4" class="result">
          <span>Item 4</span>
        </div>
        <div id="item-5" class="result">
          <span>Item 5</span>
        </div>
        <div id="item-6" class="result">
          <span>Item 6</span>
        </div>
        <div id="item-7" class="result">
          <span>Item 7</span>
        </div>
        <div id="item-8" class="result">
          <span>Item 8</span>
        </div>
        <div id="item-9" class="result">
          <span>Item 9</span>
        </div>
        <div id="item-10" class="result">
          <span>Item 10</span>
        </div>
      </div>
    </div>
  </div>
</main>
<footer class="footer"></footer>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • this disalignts the layout and moved the purple boxfrom the bottom below the aqua box. The Aquabox is supposed to adept its height to the green box according to the OP. – tacoshy Mar 30 '21 at 20:43
  • I had just missed one line of code (in the `#map` element). Check the demo again. I don't think you need JS for this. – Michael Benjamin Mar 31 '21 at 14:11