htmlcsslayoutflexbox

Achieving synchronized scroll for dual-column layout with CSS


I have a two-column layout using CSS with a sticky effect, similar to the example provided below. However, the scrolling behaviour differs slightly from what I need.

Currently, the blue column starts scrolling first, followed by the red column 50% down the page. Both columns then stop at the bottom.

Desired Behavior:

I'd like the opposite effect. Upon initial scrolling, both columns (blue and red) should scroll simultaneously until the red column reaches its content limit. At that point, the red column should stop scrolling, while the blue column continues scrolling until its content ends.

Question:

Can this synchronized scrolling behaviour be achieved using pure CSS?

.container {
  display: flex;
  justify-content: space-around;
  align-items: flex-start;
  border: 2px dashed rgba(114, 186, 94, 0.35);
  background: rgba(114, 186, 94, 0.05);
}

.col {
  position: sticky;
  top: 0;
}

.col div {
  height: 250px;
  width: 250px;
  border: 2px dashed rgba(255, 186, 94, 0.35);
  margin-bottom: 20px;
}

.col div:nth-child(2n) {
  opacity: 0.5;
}

.op {
  opacity: 0.7;
}

.col1 div {
    background-color: red;
}

.col2 div {
    background-color: blue;
}
<!DOCTYPE html>
<html lang="en">
<body>
  <div class="container">
    <div class="col col1">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>
    <div class="col col2">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>
  </div>
  </body>
</html>


Solution

  • Adjust the alignment of the first item to place it at the bottom then use a bottom sticky behavior

    .container {
      display: flex;
      justify-content: space-around;
      align-items: flex-start;
      border: 2px dashed rgba(114, 186, 94, 0.35);
      background: rgba(114, 186, 94, 0.05);
    }
    
    .col {
      margin-top: auto; /* place item at bottom */
      position: sticky;
      bottom: 0; /* instead of top */
    }
    
    .col div {
      height: 250px;
      width: 250px;
      border: 2px dashed rgba(255, 186, 94, 0.35);
      margin-bottom: 20px;
    }
    
    .col div:nth-child(2n) {
      opacity: 0.5;
    }
    
    .op {
      opacity: 0.7;
    }
    
    .col1 div {
        background-color: red;
    }
    
    .col2 div {
        background-color: blue;
    }
    <!DOCTYPE html>
    <html lang="en">
    <body>
      <div class="container">
        <div class="col col1">
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
        </div>
        <div class="col col2">
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
          <div></div>
        </div>
      </div>
      </body>
    </html>