Search code examples
javascripthtmlcssreactjscss-animations

How do I create a scroll which is similar to this?


I am trying to create a similar scroll like this.

Now I have created a structure in reactjs but I am not able to figure the left side scroll when right side is sticky without using any library.

.project-section {
  height: 400vh;
  position: relative;
  background-color: lightcoral; 
}

.project-heading {
  display: flex;
  background-color: lightblue;
  font-size: var(--font-size-heading);
}

.project-heading-text {
  font-family: Campton-Font-Bold;
  font-size: var(--font-size-heading);
}

.project-header {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  justify-content: flex-start;
  width: 100%;
  height: 300vh;
  background-color: lightsalmon;
}

.project-container-text {
  display: flex;
  flex-direction: column;
  width: 50%;
  justify-content: center; /* or space-around */
  align-items: center; /* Ensure this has a value, like 'center' */
  height: 300vh;
  border: 1px solid blue;
}

.project-text {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100vh;
  border: 1px solid yellow;
}

.project-container-images {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  width: 50%;
  height: 300vh;
  border: 1px solid green;
  top: 0;
  bottom: 0;
  z-index: 1000;
  position: relative;
}

.project-image {
  display: flex;
  justify-content: center;
  align-content: center;
  width: 100%;
  height: 100vh;
  border: 1px solid black;
  flex-wrap: wrap;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>
<section class="project-section" style="top: 0px;"><div class="project-heading"><span class="project-heading-text">Projects</span></div><div class="project-header"><div class="project-container-text"><span class="project-text">Text 1</span><span class="project-text">Text 2</span><span class="project-text">Text 3</span></div><div class="project-container-images" style="position: initial; top: 0px;"><span class="project-image">image1</span></div></div></section>

Functionality:

  • The Project headline should stick on top.
  • The Right side should also stick on top.
  • The Left side should be able to scroll and the text 1 and text 2 and text 3 should appear one by one while rest of the part should be sticky.

Bonus Question: As given in the link above, for reference, please let me know how to work on the image stack scrolling?

PS: cannot provide the github repo as it is a private project.

Note: I am using it in a react.js project.


Solution

  • The main trick is to use container to set height for the viewport and make right side sticky, while left should be scrollable by y-axis from container css. So, you basically scroll the container, not the left side only, but right part remains sticky

    1. .project-section: Set the height to 100vh so that it takes the full height of the viewport and ensures that the .project-header has a fixed height.
    2. .project-header: Container for both the left and right sections. Set full height (100%) and overflow: hidden to prevent scrolling.
    3. .project-container-text: overflow-y: auto to enable independent scrolling. The height is set to 100% of its parent container so it doesn’t extend beyond it.
    4. .project-container-images: The sticky section on the right has position: sticky and top: 0 to keep it fixed as the viewport scrolls.

    NOTE: Please run snippet in a full window to see the correct result.

    .project-section {
      height: 100vh; /* Set this to viewport height */
      display: flex;
      flex-direction: column;
      background-color: lightcoral;
    }
    
    .project-heading {
      background-color: lightblue;
      font-size: var(--font-size-heading);
      padding: 10px;
    }
    
    .project-header {
      display: flex;
      flex-direction: row;
      width: 100%;
      height: 100%; /* Full height to match the viewport */
      overflow: hidden; /* Hide overflow on the main container */
    }
    
    .project-container-text {
      width: 50%;
      height: 100%; /* Full height of the container */
      overflow-y: auto; /* Make it scrollable */
      border: 1px solid blue;
    }
    
    .project-text {
      height: 100vh; /* Example height for each text block */
      border: 1px solid yellow;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .project-container-images {
      width: 50%;
      height: 100%; /* Full height to match the viewport */
      position: sticky;
      top: 0; /* Sticks the element to the top */
      border: 1px solid green;
      display: flex;
      flex-direction: column;
    }
    
    .project-image {
      height: 100vh; /* Example height for each image block */
      border: 1px solid black;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>
    <section class="project-section">
      <div class="project-heading">
        <span class="project-heading-text">Projects</span>
      </div>
      <div class="project-header">
        <div class="project-container-text">
          <div class="project-text">Text 1</div>
          <div class="project-text">Text 2</div>
          <div class="project-text">Text 3</div>
        </div>
        <div class="project-container-images">
          <div class="project-image">Image 1</div>
          <div class="project-image">Image 2</div>
          <div class="project-image">Image 3</div>
        </div>
      </div>
    </section>