skip to Main Content

So in an HTML document I have two DIVs side by side, each with a different height. When the user starts scrolling down, both DIVs should start scrolling at the same time, as you would expect. When the end of the shorter DIV is reached, it should stick to the bottom of the viewport until the end of the taller DIV is reached. The page should then continue to scroll "normally". Here is the starting point:

.parent {
  display: flex
}

.child {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.left {
  background: lightblue;
  height: 200vh;
}

.right {
  background: lightcoral;
  height: 120vh;
}
<div class="parent">
  <div class="child left">
    <div>Top</div>
    <div>Bottom</div>
  </div>
  <div class="child right">
    <div>Top</div>
    <div>Bottom</div>
  </div>
</div>

After fiddling around for some time, I can only achieve the exact opposite of what I try to accomplish:

.parent {
  display: flex
}

.child {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.left {
  background: lightblue;
  height: 200vh;
}

.right {
  background: lightcoral;
  height: 120vh;
  position: sticky;
  top: 0;
}
<div class="parent">
  <div class="child left">
    <div>Top</div>
    <div>Bottom</div>
  </div>
  <div class="child right">
    <div>Top</div>
    <div>Bottom</div>
  </div>
</div>

Any help would be appreciated.

2

Answers


  1. You could indeed consider using position: sticky, but set the top offset to 20vh, which would be the difference in height of the element and the viewport height:

    .parent {
      display: flex
    }
    
    .child {
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      position: sticky;
    }
    
    .left {
      background: lightblue;
      height: 200vh;
    }
    
    .right {
      background: lightcoral;
      height: 120vh;
      top: -20vh;
    }
    <div class="parent">
      <div class="child left">
        <div>Top</div>
        <div>Bottom</div>
      </div>
      <div class="child right">
        <div>Top</div>
        <div>Bottom</div>
      </div>
    </div>
    Login or Signup to reply.
  2. Derived this from @Wongjn’s great solution, using Javascript to calculate the top values for the child divs.

    const randomIntFromInterval = (min, max) => {
      return Math.floor(Math.random() * (max - min + 1) + min)
    }
    
    const d1 = document.querySelectorAll('.d1>*').forEach(c => {
      const q = randomIntFromInterval(50,250)
      c.style.height = q + 'vh'
      c.style.top = (100 - q) + 'vh'
      c.children[1].innerHTML = 'height: ' + c.style.height + '<br>top: ' + c.style.top
    })
    .d1 {
      display: flex;
    }
    
    .d1>* {
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      position: sticky;
      padding: 1em;
      box-sizing: border-box;
    }
    
    .d1>*:nth-child(1) {
      background: lightblue;
    }
    
    .d1>*:nth-child(2) {
      background: lightcoral;
    }
    
    .d1>*:nth-child(3) {
      background: lightgreen;
    }
    
    .d1>*:nth-child(4) {
      background: bisque;
    }
    <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas tempor nunc mauris, sit amet placerat tortor lobortis dapibus. Nam lectus eros, maximus ac magna vel, congue consequat eros. Fusce id pretium diam. Cras sit amet pharetra ante. Sed quis commodo quam, vel facilisis ipsum. Vestibulum sodales iaculis arcu, et fringilla nisi ullamcorper sed. Donec interdum sit amet est non accumsan. Donec non augue feugiat, fermentum nunc non, convallis est. Cras vel ligula nec odio faucibus ultricies. Sed vulputate tortor eget pretium convallis. Cras interdum elit eget mi porta suscipit. Morbi ut velit diam. Etiam finibus eros et efficitur rutrum. Quisque viverra metus ac eleifend imperdiet. Quisque pretium ut purus vitae tempus. Duis varius risus congue velit faucibus, sed interdum purus consectetur.
    </p>
    
    <div class="d1">
      <div>
        <div>Top</div>
        <div>Middle</div>
        <div>Bottom</div>
      </div>
      <div>
        <div>Top</div>
        <div>Middle</div>
        <div>Bottom</div>
      </div>
      <div>
        <div>Top</div>
        <div>Middle</div>
        <div>Bottom</div>
      </div>
      <div>
        <div>Top</div>
        <div>Middle</div>
        <div>Bottom</div>
      </div>
    </div>
    
    <p>
    Cras volutpat velit non mi sagittis condimentum. Cras tempor aliquet turpis sed pretium. Nunc aliquet sodales turpis quis ultrices. Duis auctor accumsan enim, quis maximus ex malesuada a. Donec a felis ut erat tempus euismod non vel neque. Proin lectus massa, sagittis at imperdiet nec, consequat ut neque. Sed vel placerat neque, vel varius urna. Vivamus interdum euismod urna a accumsan. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
    </p>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search