CSS Position Sticky to preview content of next div

ghz 8months ago ⋅ 74 views

I am trying to create a floating preview of the content that follows the current part of the page being scrolled. It may be easier to explain with code.

We have the current content.

<div class="current-content">
  <p>hi 1</p>
    <p>hi 2</p>
    <p>hi 3</p>
    <p>hi 4</p>
    <p>hi 5</p>
    <p>hi 6</p>
    <p>hi 7</p>
    <p>hi 8</p>
    <p>hi 9</p>
</div>

After that we have some more content.

<div class="next-content">
  <p>hi 1</p>
    <p>hi 2</p>
    <p>hi 3</p>
    <p>hi 4</p>
    <p>hi 5</p>
    <p>hi 6</p>
    <p>hi 7</p>
    <p>hi 8</p>
    <p>hi 9</p>
</div>

The idea is that whilst we are scrolling the page from the top, we scroll through current content, but next content occupies 50% of the viewport using position sticky until it is scrolled into view.

p {
  font-size: 28px;
  marin: 20px;
}

.current-content {
  background: yellow;
}

.next-content {
  background: pink;
  position: sticky;
  bottom: -50vh;
}

The problem is, that this does not appear to be possible using top because next-content appears after current-content in the HTML tree. Therefore it can only be accomplished using bottom. The problem is, that bottom is a reference to the bottom position of next-content relative to the viewport and therefore without knowing the height of next-content there is no way to make it fill only 50% of the viewport whilst stuck.

I hope that makes sense, and is there a way to achieve this.

For context, think of a news website where you directly scroll from one article to the the next article but whilst scrolling, there is always a preview of what the next article will be that will scroll into view once you get there.

p {
  font-size: 28px;
  marin: 20px;
}

.current-content {
  background: yellow;
}

.next-content {
  background: pink;
  position: sticky;
  bottom: -100%; // set to -100% for demonstration purposes
}
<body>
  <div class="current-content">
    <p>hi 1</p>
    <p>hi 2</p>
    <p>hi 3</p>
    <p>hi 4</p>
    <p>hi 5</p>
    <p>hi 6</p>
    <p>hi 7</p>
    <p>hi 8</p>
    <p>hi 9</p>
  </div>
  <div class="next-content">
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
    <p>hi</p>
  </div>
</body>

Answers

To achieve the floating preview effect where the next content occupies 50% of the viewport until it is scrolled into view, you can use a combination of CSS positioning and JavaScript to dynamically adjust the position of the preview content. Here's how you can do it:

HTML:

<body>
  <div class="current-content">
    <p>hi 1</p>
    <p>hi 2</p>
    <!-- Add more content here -->
  </div>
  <div class="next-content">
    <!-- Add preview content here -->
  </div>
</body>

CSS:

p {
  font-size: 28px;
  margin: 20px;
}

.current-content {
  background: yellow;
}

.next-content {
  background: pink;
  position: fixed;
  bottom: 0;
  width: 100%;
  height: 50%; /* Initially, occupy 50% of the viewport */
  overflow-y: auto; /* Enable scrolling if content exceeds height */
  transition: height 0.3s; /* Smooth transition */
}

JavaScript:

window.addEventListener('scroll', function() {
  var currentContent = document.querySelector('.current-content');
  var nextContent = document.querySelector('.next-content');
  
  // Get the height of the viewport
  var viewportHeight = window.innerHeight;

  // Get the height of the current content
  var currentContentHeight = currentContent.getBoundingClientRect().height;

  // Calculate the distance from the top of the viewport to the top of the current content
  var distanceToTop = currentContent.getBoundingClientRect().top;

  // If the top of the current content is at or above the top of the viewport
  // and the bottom of the current content is below the bottom of the viewport
  // then the next content is in view
  if (distanceToTop <= 0 && currentContentHeight + distanceToTop >= viewportHeight) {
    // Set the height of the next content to occupy 50% of the viewport
    nextContent.style.height = '50%';
  } else {
    // Otherwise, set the height of the next content to 0
    nextContent.style.height = '0';
  }
});

This JavaScript code listens for the scroll event and dynamically adjusts the height of the next content based on its position relative to the viewport. When the top of the current content is at or above the top of the viewport and the bottom of the current content is below the bottom of the viewport, the next content is considered to be in view, and its height is set to occupy 50% of the viewport. Otherwise, the height of the next content is set to 0, effectively hiding it from view.