Naz
Naz

Reputation: 131

How to make an auto-resizable div depending on the content on the screen (Expand/Collapse) while scrolling?

How can I have two DIVs split on the screen, and when scrolling - The left DIV is static and the right DIV is scrollable. But the right DIV expands while scrolling if an overflow is detected?

What I want to achieve is:


enter image description here

JsFiddle: JsFiddle

.container {
  margin-top: 32px;
  min-height: 300px;
  display: flex;
  overflow-x: scroll;
  overflow-y: hidden;
}

.container .left {
  width: 100%;
  height: 100%;
  background-color: blue;
  padding: 10px;
}

.container .right {
  width: 50%;
  height: 100%;
  background-color: red;
  padding: 15vh 10px;
  box-sizing: border-box;
  overflow: scroll;
}

.container .right table,
th,
td {
  border: 1px solid black;
  border-collapse: collapse;
}
<div class="container">
  <div class="left">
  </div>
  <div class="right">
    <div class="tableX">
      <table style="width:100%">
        <tr>
          <th>Firstname</th>
          <th>Lastname</th>
          <th>Age</th>
        </tr>
        <tr>
          <td>Jill</td>
          <td>Smith</td>
          <td>50</td>
        </tr>
        <tr>
          <td>Eve</td>
          <td>Jackson</td>
          <td>94</td>
        </tr>
        <tr>
          <td>John</td>
          <td>Doe</td>
          <td>80</td>
        </tr>
      </table>
    </div>
    <div class="par-card">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Orci nulla pellentesque dignissim enim sit. Risus ultricies tristique nulla aliquet enim tortor at. Viverra justo nec ultrices
        dui sapien. Pharetra diam sit amet nisl suscipit adipiscing bibendum. In cursus turpis massa tincidunt dui ut. In vitae turpis massa sed. Libero id faucibus nisl tincidunt. Blandit volutpat maecenas volutpat blandit aliquam. Odio facilisis mauris
        sit amet massa. Libero enim sed faucibus turpis. Praesent tristique magna sit amet. Sit amet porttitor eget dolor morbi non arcu. Turpis egestas pretium aenean pharetra magna ac. Dolor sed viverra ipsum nunc aliquet bibendum enim facilisis. Sagittis
        eu volutpat odio facilisis mauris sit amet. Elementum nibh tellus molestie nunc non. Est ante in nibh mauris cursus. Nisl rhoncus mattis rhoncus urna neque viverra. Sagittis id consectetur purus ut faucibus pulvinar elementum integer enim. Mauris
        augue neque gravida in. Vestibulum morbi blandit cursus risus at ultrices mi tempus imperdiet. Pretium lectus quam id leo in vitae turpis massa sed. Eu consequat ac felis donec et odio pellentesque. A erat nam at lectus urna duis. Quam quisque
        id diam vel quam elementum pulvinar etiam non. In dictum non consectetur a erat. Vitae auctor eu augue ut. Sed id semper risus in hendrerit gravida rutrum. Pellentesque id nibh tortor id aliquet lectus proin nibh nisl. Aliquet nibh praesent tristique
        magna sit. Lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt. Pulvinar etiam non quam lacus suspendisse faucibus interdum posuere lorem. Odio tempor orci dapibus ultrices. Nibh nisl condimentum id venenatis a condimentum
        vitae sapien pellentesque. Nulla aliquet enim tortor at. Netus et malesuada fames ac turpis. Donec pretium vulputate sapien nec sagittis aliquam malesuada bibendum arcu. At augue eget arcu dictum varius duis at consectetur lorem. Leo integer malesuada
        nunc vel risus commodo viverra maecenas accumsan. Libero justo laoreet sit amet. Neque gravida in fermentum et sollicitudin ac orci. Hac habitasse platea dictumst vestibulum rhoncus. Morbi leo urna molestie at elementum eu facilisis sed. Eget
        nunc lobortis mattis aliquam faucibus purus. Risus quis varius quam quisque id diam vel. Gravida rutrum quisque non tellus orci. A scelerisque purus semper eget duis. Ut etiam sit amet nisl. Sem viverra aliquet eget sit amet tellus. In dictum
        non consectetur a erat. Facilisi nullam vehicula ipsum a arcu cursus vitae congue. Volutpat lacus laoreet non curabitur gravida arcu ac. Nunc sed id semper risus in. Tempor orci dapibus ultrices in iaculis nunc sed. Eros in cursus turpis massa.
        Cursus mattis molestie a iaculis at erat pellentesque adipiscing commodo. Tellus molestie nunc non blandit massa enim nec. Tristique magna sit amet purus gravida quis blandit. Leo in vitae turpis massa sed elementum. Ac odio tempor orci dapibus
        ultrices. Turpis in eu mi bibendum neque egestas congue quisque. Vestibulum lorem sed risus ultricies tristique nulla. Bibendum est ultricies integer quis auctor elit sed vulputate. Adipiscing at in tellus integer feugiat scelerisque varius morbi
        enim. Justo laoreet sit amet cursus. Quisque sagittis purus sit amet volutpat. Mi eget mauris pharetra et ultrices neque ornare. Condimentum mattis pellentesque id nibh tortor id aliquet. Eget magna fermentum iaculis eu non diam phasellus vestibulum
        lorem. Faucibus vitae aliquet nec ullamcorper. Etiam erat velit scelerisque in dictum non consectetur a. Leo vel fringilla est ullamcorper. Aenean vel elit scelerisque mauris pellentesque pulvinar. Vitae et leo duis ut diam quam nulla porttitor
        massa. Pretium viverra suspendisse potenti nullam ac tortor vitae. Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant morbi. Feugiat in ante metus dictum. Integer malesuada nunc vel risus commodo viverra maecenas accumsan.
        Id eu nisl nunc mi ipsum.</p>
    </div>
    <div class="image">
      <img src="https://i.imgur.com/hMrkGV8.png" alt="">
    </div>

Upvotes: 2

Views: 121

Answers (2)

A Haworth
A Haworth

Reputation: 36532

If you put an intersection observer on each child in the right hand div you will be told when it comes into or goes out of view.

Looking more closely at the GIF in the question what happens is that the content is completely painted on the right hand side, with wide parts taking the whole width and narrower ones taking half that. Then if a wide part is in view the blue left hand side retracts to display it. If no wide parts are in view then the blue div expands to cover half the right hand div.

It is not obvious from the given HTML which parts of right are to be shown wide (for example, in the GIF a table at the top is wide - it's not just an adjustment for images). Therefore an extra class 'wide' has been added to those divs in right which you want to be wide.

This snippet takes the HTML from the question but adds this class to both the table at the top and the image div at the bottom so as to emulate more closely the GIF.

We keep a count of the number of children that are wide and in view. If there are any then contract the left hand div.

          function callback(entries) {
            for (let i=0; i < entries.length; i++) {
              let entry = entries[i];
              let child = entry.target;
              if ( child.offsetWidth > originalWidth/2 ) {
                if (entry.isIntersecting) { count++; }
                else {
                  if (child.getAttribute('data-firsttime') == 0 ) { count--; }
                }
              }
              child.setAttribute('data-firsttime', 0);
            }
            if (count > 0) { left.classList.remove('expand'); }
            else { count = 0; left.classList.add('expand'); }
          }
          
          const observer = new IntersectionObserver(callback);
          const left = document.querySelector('.left');
          const right = document.querySelector('.right');
          let originalWidth = right.offsetWidth;
          const children = right.children;
          let count = 0; // keep a count of how many children in view are wider
          function setup() {
            for ( let i = 0; i < children.length; i++ ) {
              children[i].setAttribute('data-firsttime', 1); //set a marker to say if not yet been observed
              observer.observe(children[i]);
            }
          }
          function resize() {
            originalWidth = right.offsetWidth;
          }
          window.onload = setup;
          window.onresize = resize;
    * {
      margin: 0;
      padding: 0;
    }
    
    .container {
        margin-top: 32px;
        min-height: 300px;
        height: 100vh;
        overflow-x: scroll;
        overflow-y: hidden;
      position: relative;
    }
    
    .container .left {
        width: calc(50% - 20px); /* allow space for padding */
      height: 100%;
        background-color: blue;
        padding: 10px;
      z-index: 1;
      position: absolute;
      top: 0;
      left: 0;
      transition: width 1s;
    }
    
    .container .left.expand {
      width: calc(75% - 40px); /* allow space for padding of container and right */
    }
    
    .container .right {
        width: 50%;
        height: 100%;
        background-color: red;
        padding: 15vh 10px;
        box-sizing: border-box;
        overflow-y: auto;/* ADDED */
      position: relative;
      left: 50%;
    }
    
    .container .right table, th, td {
        border: 1px solid black;
        border-collapse: collapse;
    }
    
    .container .right > * {
      position: relative;
      left: 50%;
      width: 50%;  
    }
    
    .container .right div.wide {
      left: 0;
      width: 100%;
    }
    
    .container .right div.wide.image img{
      width: 100%;
      height: auto;
    }
        <div class="container">
          <div class="left">
          </div>
          <div class="right">
            <div class="tableX wide">
              <table style="width:100%">
                <tr>
                  <th>Firstname</th>
                  <th>Lastname</th>
                  <th>Age</th>
                </tr>
                <tr>
                  <td>Jill</td>
                  <td>Smith</td>
                  <td>50</td>
                </tr>
                <tr>
                  <td>Eve</td>
                  <td>Jackson</td>
                  <td>94</td>
                </tr>
                <tr>
                  <td>John</td>
                  <td>Doe</td>
                  <td>80</td>
                </tr>
              </table>
            </div>
            <div class="par-card">
              <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Orci nulla pellentesque dignissim enim sit. Risus ultricies tristique nulla aliquet enim tortor at. Viverra justo nec ultrices dui sapien. Pharetra diam sit amet nisl suscipit adipiscing bibendum. In cursus turpis massa tincidunt dui ut. In vitae turpis massa sed. Libero id faucibus nisl tincidunt. Blandit volutpat maecenas volutpat blandit aliquam. Odio facilisis mauris sit amet massa. Libero enim sed faucibus turpis. Praesent tristique magna sit amet. Sit amet porttitor eget dolor morbi non arcu. Turpis egestas pretium aenean pharetra magna ac. Dolor sed viverra ipsum nunc aliquet bibendum enim facilisis. Sagittis eu volutpat odio facilisis mauris sit amet.
    
                Elementum nibh tellus molestie nunc non. Est ante in nibh mauris cursus. Nisl rhoncus mattis rhoncus urna neque viverra. Sagittis id consectetur purus ut faucibus pulvinar elementum integer enim. Mauris augue neque gravida in. Vestibulum morbi blandit cursus risus at ultrices mi tempus imperdiet. Pretium lectus quam id leo in vitae turpis massa sed. Eu consequat ac felis donec et odio pellentesque. A erat nam at lectus urna duis. Quam quisque id diam vel quam elementum pulvinar etiam non. In dictum non consectetur a erat. Vitae auctor eu augue ut. Sed id semper risus in hendrerit gravida rutrum. Pellentesque id nibh tortor id aliquet lectus proin nibh nisl. Aliquet nibh praesent tristique magna sit. Lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt. Pulvinar etiam non quam lacus suspendisse faucibus interdum posuere lorem. Odio tempor orci dapibus ultrices.
    
                Nibh nisl condimentum id venenatis a condimentum vitae sapien pellentesque. Nulla aliquet enim tortor at. Netus et malesuada fames ac turpis. Donec pretium vulputate sapien nec sagittis aliquam malesuada bibendum arcu. At augue eget arcu dictum varius duis at consectetur lorem. Leo integer malesuada nunc vel risus commodo viverra maecenas accumsan. Libero justo laoreet sit amet. Neque gravida in fermentum et sollicitudin ac orci. Hac habitasse platea dictumst vestibulum rhoncus. Morbi leo urna molestie at elementum eu facilisis sed. Eget nunc lobortis mattis aliquam faucibus purus. Risus quis varius quam quisque id diam vel. Gravida rutrum quisque non tellus orci.
    
                A scelerisque purus semper eget duis. Ut etiam sit amet nisl. Sem viverra aliquet eget sit amet tellus. In dictum non consectetur a erat. Facilisi nullam vehicula ipsum a arcu cursus vitae congue. Volutpat lacus laoreet non curabitur gravida arcu ac. Nunc sed id semper risus in. Tempor orci dapibus ultrices in iaculis nunc sed. Eros in cursus turpis massa. Cursus mattis molestie a iaculis at erat pellentesque adipiscing commodo. Tellus molestie nunc non blandit massa enim nec. Tristique magna sit amet purus gravida quis blandit. Leo in vitae turpis massa sed elementum. Ac odio tempor orci dapibus ultrices. Turpis in eu mi bibendum neque egestas congue quisque. Vestibulum lorem sed risus ultricies tristique nulla. Bibendum est ultricies integer quis auctor elit sed vulputate. Adipiscing at in tellus integer feugiat scelerisque varius morbi enim. Justo laoreet sit amet cursus. Quisque sagittis purus sit amet volutpat.
    
                Mi eget mauris pharetra et ultrices neque ornare. Condimentum mattis pellentesque id nibh tortor id aliquet. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Faucibus vitae aliquet nec ullamcorper. Etiam erat velit scelerisque in dictum non consectetur a. Leo vel fringilla est ullamcorper. Aenean vel elit scelerisque mauris pellentesque pulvinar. Vitae et leo duis ut diam quam nulla porttitor massa. Pretium viverra suspendisse potenti nullam ac tortor vitae. Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant morbi. Feugiat in ante metus dictum. Integer malesuada nunc vel risus commodo viverra maecenas accumsan. Id eu nisl nunc mi ipsum.</p>
            </div>
            <div class="image wide">
              <img src="https://i.imgur.com/hMrkGV8.png" alt="">
            </div>

UPDATE: Explanation of the Javascript:

  1. Create an IntersectionObserver which will call the function callback whenever an element that it has been asked to observe enters or leaves the viewport.

  2. Go through all the immediate children of the right element and ask the observer to observe each of them - so whenever they come into or go out of the viewport the callback function will be entered.

  3. When the callback function is entered it gives a list of the entries - each entry tells you which element has been observed coming into or going out of the viewport (element.target) and whether it was observed coming into or going out of the viewport (element.isIntersecting).

  4. If a wide element is seen to be entering the viewport then we add one to the count of wide elements in the viewport.

  5. if it is seen to be leaving the viewport (element.isIntersecting is false) then we take one off this count UNLESS it's the first time - this is because when we first set up the observer to observe an element it immediately tells us whether it's inside or outside the viewport so we dont want at the beginning to count any elements that are outside (this was the problem you had when you put the image at the top, there was also one at the bottom, out of view, so the count went to 0).

  6. If there is something that is wide (or some things) in the viewport then we want the blue left element to shrink down so we see the whole of the right element.

  7. If there is nothing wide in the viewport then we want the blue left element to expand so making the right element thinner.

IntersectionObserver is a cleaner way of dealing with some scrolling situations since you dont have to keep looking every time the user scrolls, only when the elements you are interested in come and go out of the viewport. See MDN for further info.

Upvotes: 3

Jim Vercoelen
Jim Vercoelen

Reputation: 1077

@Naz I answered on your previous post. Did it not work?

Answer:

Something like this should do

<!DOCTYPE html>
    <head>
        <style>
            html,
            body {
                margin: 0;
                padding: 0;
            }

            * {
                box-sizing: border-box;
            }

            .container {
                margin-top: 32px;
                display: flex;
                flex-flow: row nowrap;
                width: 100%;
                height: calc(100vh - 32px); /* minus margin top offset */
            }

            .container .left {
                padding: 10px;
                width: 50%;
                height: 100%;
                background-color: blue;
            }

            .container .right {
                padding: 10px;
                width: 50%;
                height: 100%;
                max-height: 100%;
                background-color: red;
                overflow-y: scroll;
            }

            .container .right table, th, td {
                border: 1px solid black;
                border-collapse: collapse;
            }
        </style>
    </head>
    <body>
        <div class="container">
            <div class="left">

            </div>
            <div class="right">
                <div class="tableX">
                    <table style="width:100%">
                        <tr>
                            <th>Firstname</th>
                            <th>Lastname</th>
                            <th>Age</th>
                        </tr>
                        <tr>
                            <td>Jill</td>
                            <td>Smith</td>
                            <td>50</td>
                        </tr>
                        <tr>
                            <td>Eve</td>
                            <td>Jackson</td>
                            <td>94</td>
                        </tr>
                        <tr>
                            <td>John</td>
                            <td>Doe</td>
                            <td>80</td>
                        </tr>
                    </table>
                </div>
                <div class="par-card">
                    <p>
                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Orci nulla pellentesque dignissim enim sit. Risus ultricies tristique nulla aliquet enim tortor at. Viverra justo nec ultrices dui sapien. Pharetra diam sit amet nisl suscipit adipiscing bibendum. In cursus turpis massa tincidunt dui ut. In vitae turpis massa sed. Libero id faucibus nisl tincidunt. Blandit volutpat maecenas volutpat blandit aliquam. Odio facilisis mauris sit amet massa. Libero enim sed faucibus turpis. Praesent tristique magna sit amet. Sit amet porttitor eget dolor morbi non arcu. Turpis egestas pretium aenean pharetra magna ac. Dolor sed viverra ipsum nunc aliquet bibendum enim facilisis. Sagittis eu volutpat odio facilisis mauris sit amet.

                        Elementum nibh tellus molestie nunc non. Est ante in nibh mauris cursus. Nisl rhoncus mattis rhoncus urna neque viverra. Sagittis id consectetur purus ut faucibus pulvinar elementum integer enim. Mauris augue neque gravida in. Vestibulum morbi blandit cursus risus at ultrices mi tempus imperdiet. Pretium lectus quam id leo in vitae turpis massa sed. Eu consequat ac felis donec et odio pellentesque. A erat nam at lectus urna duis. Quam quisque id diam vel quam elementum pulvinar etiam non. In dictum non consectetur a erat. Vitae auctor eu augue ut. Sed id semper risus in hendrerit gravida rutrum. Pellentesque id nibh tortor id aliquet lectus proin nibh nisl. Aliquet nibh praesent tristique magna sit. Lectus vestibulum mattis ullamcorper velit sed ullamcorper morbi tincidunt. Pulvinar etiam non quam lacus suspendisse faucibus interdum posuere lorem. Odio tempor orci dapibus ultrices.

                        Nibh nisl condimentum id venenatis a condimentum vitae sapien pellentesque. Nulla aliquet enim tortor at. Netus et malesuada fames ac turpis. Donec pretium vulputate sapien nec sagittis aliquam malesuada bibendum arcu. At augue eget arcu dictum varius duis at consectetur lorem. Leo integer malesuada nunc vel risus commodo viverra maecenas accumsan. Libero justo laoreet sit amet. Neque gravida in fermentum et sollicitudin ac orci. Hac habitasse platea dictumst vestibulum rhoncus. Morbi leo urna molestie at elementum eu facilisis sed. Eget nunc lobortis mattis aliquam faucibus purus. Risus quis varius quam quisque id diam vel. Gravida rutrum quisque non tellus orci.

                        A scelerisque purus semper eget duis. Ut etiam sit amet nisl. Sem viverra aliquet eget sit amet tellus. In dictum non consectetur a erat. Facilisi nullam vehicula ipsum a arcu cursus vitae congue. Volutpat lacus laoreet non curabitur gravida arcu ac. Nunc sed id semper risus in. Tempor orci dapibus ultrices in iaculis nunc sed. Eros in cursus turpis massa. Cursus mattis molestie a iaculis at erat pellentesque adipiscing commodo. Tellus molestie nunc non blandit massa enim nec. Tristique magna sit amet purus gravida quis blandit. Leo in vitae turpis massa sed elementum. Ac odio tempor orci dapibus ultrices. Turpis in eu mi bibendum neque egestas congue quisque. Vestibulum lorem sed risus ultricies tristique nulla. Bibendum est ultricies integer quis auctor elit sed vulputate. Adipiscing at in tellus integer feugiat scelerisque varius morbi enim. Justo laoreet sit amet cursus. Quisque sagittis purus sit amet volutpat.

                        Mi eget mauris pharetra et ultrices neque ornare. Condimentum mattis pellentesque id nibh tortor id aliquet. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Faucibus vitae aliquet nec ullamcorper. Etiam erat velit scelerisque in dictum non consectetur a. Leo vel fringilla est ullamcorper. Aenean vel elit scelerisque mauris pellentesque pulvinar. Vitae et leo duis ut diam quam nulla porttitor massa. Pretium viverra suspendisse potenti nullam ac tortor vitae. Ipsum dolor sit amet consectetur adipiscing elit pellentesque habitant morbi. Feugiat in ante metus dictum. Integer malesuada nunc vel risus commodo viverra maecenas accumsan. Id eu nisl nunc mi ipsum.
                    </p>
                </div>
                <div class="image">
                    <img src="https://i.imgur.com/hMrkGV8.png" alt="">
                </div>
            </div>
        </div>
    </body>
</html>

Upvotes: 0

Related Questions