Seamless transition of text positioning and opacity as you scroll

After exploring multiple techniques for changing opacity and position on scroll, I am still struggling to connect them effectively.


What I'm Looking For:

I have a container with 4 words in a row. Only one word should be visible at a time, transitioning as the user scrolls. The next word should appear from the right as the user scrolls down, and vice versa when scrolling up. I have created a visual representation of my goal:

Step 1:

As the user scrolls, text begins to appear from the right (as shown with 'text 1' and 'text 2'). This transition should apply to each word in the row.

https://i.sstatic.net/V22yU.jpg

Step 2:

Continuing to scroll will move 'text 2' into the position of 'text 1' while 'text 1' becomes less opaque.

https://i.sstatic.net/kwLXj.jpg

Subsequent Steps:

The final two images illustrate how 'text 1' eventually disappears with an opacity change to 0, leaving 'text 2' in its place.

https://i.sstatic.net/oVZPs.jpg https://i.sstatic.net/PDMHk.jpg

The example above details the effect on scroll down, but it should also work in reverse for scroll up. As the user scrolls past 'text 2', 'text 3' should appear, and so forth.


Regrettably, I cannot provide the code I've attempted as I am unsure where to begin tackling this task. One idea I had was to establish current and next sliders.

I hope the description alongside the images is clear enough, as I myself am uncertain if I fully grasp it.

Answer №1

Adjust the height of the <body> element to create a vertical scroll.

body {
  height: 9999px;
  background-color: #333;
}

Add a container for the words and use position: fixed to keep it on screen while scrolling.

body {
  height: 9999px;
  background-color: #333;
}

.words {
  position: fixed;
  width: 300px;
  height: 200px;
  background-color: white;
}
<div class="words">
</div>

Place the texts on top of each other inside the container.

body {
  height: 9999px;
  background-color: #333;
}

.words {
  position: fixed;
  width: 300px;
  height: 200px;
  background-color: white;
}

.word {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: red;
}
<div class="words">
  <div class="word">Foo</div>
  <div class="word">Bar</div>
  <div class="word">Baz</div>
</div>

Align all words except the first to the far right of the container. Use overflow: hidden to hide them from view.

body {
  height: 9999px;
  background-color: #333;
}

.words {
  position: fixed;
  width: 300px;
  height: 200px;
  background-color: white;
  overflow: hidden;
}

.word {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: red;
}

.word:nth-child(n + 2) {
  transform: translate(calc(170px - 50%), -50%);
}
<div class="words">
  <div class="word">Foo</div>
  <div class="word">Bar</div>
  <div class="word">Baz</div>
</div>

Implement JavaScript to update a CSS variable as we scroll.

const container = document.querySelector('.words');

window.addEventListener('scroll', () => {
  container.style.setProperty('--scroll', window.scrollY);
});
body {
  height: 9999px;
  background-color: #333;
}

.words {
  position: fixed;
  width: 300px;
  height: 200px;
  background-color: white;
  overflow: hidden;
}

.word {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: red;
}

.word:nth-child(n + 2) {
  transform: translate(calc(170px - 50%), -50%);
}
<div class="words">
  <div class="word">Foo</div>
  <div class="word">Bar</div>
  <div class="word">Baz</div>
</div>

Utilize the CSS variable to adjust properties like opacity and transform for the .word elements based on scrolling.

const container = document.querySelector('.words');

window.addEventListener('scroll', () => {
  container.style.setProperty('--scroll', window.scrollY);
});
body {
  height: 9999px;
  background-color: #333;
}

.words {
  position: fixed;
  width: 300px;
  height: 200px;
  background-color: white;
  overflow: hidden;
  --segment-length: 200;
}

.word {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: red;
  opacity: calc(((var(--opacity-point) * var(--segment-length)) - var(--scroll, 0)) / var(--segment-length));
}

.word:nth-child(n + 2) {
  transform: translate(calc(clamp(0%, 170px * ((var(--translate-point) * var(--segment-length)) - var(--scroll, 0)) / var(--segment-length), 170px) - 50%), -50%);
}

.word:nth-child(1) {
  --opacity-point: 1;
}

.word:nth-child(2) {
  --opacity-point: 2;
  --translate-point: 1;
}

.word:nth-child(3) {
  --opacity-point: 3;
  --translate-point: 2;
}
<div class="words">
  <div class="word">Foo</div>
  <div class="word">Bar</div>
  <div class="word">Baz</div>
</div>

This script transitions between words at every 200px scrolled, defined by --segment-length.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Alignment issue with Bootstrap dropdowns noticed after dynamically loading dropdown content in Blazor

When working with Blazor, you have the ability to dynamically load content by enclosing it within an @if block and then setting the condition to true, such as when a button is clicked. Recently, I encountered an issue with a Bootstrap dropdown in my proje ...

Maximize the benefits of using React with Typescript by utilizing assignable type for RefObject

I am currently working with React, Typescript, and Material UI. My goal is to pass a ref as a prop. Within WidgetDialog, I have the following: export interface WidgetDialogProps { .... ref?: React.RefObject<HTMLDivElement>; } .... <div d ...

What could be causing my component to not refresh when used as a child?

I have been experimenting with some code to track rerenders. The initial approach failed when passing <MyComponent> as a child component. it("should return the same object after parent component rerenders", async () => { jest.useF ...

Tips for adjusting a div to perfectly fit your screen height

When I try to display images or videos in modal divs, they end up being taller than my screen size: Here is my code snippet: <div class="modal fade" id="showMedia" tabindex="-1" role="dialog" aria-hidden="true"> < ...

Converting JavaScript CanvasRenderingContext2D states array into a serialized format

Looking for a way to serialize a canvas' state in order to save it to a database for later restoration. Want to store the data as an object rather than a bitmap file. I've tried using .save() and .restore() on the context object, but they only m ...

Exploring AngularJS and Node.js Express: routing and page reloading

My application seems to be running smoothly, but once I hit F5 in the browser, an issue arises. The structure of my app is as follows: Node.js + Express, in Express : app.use(express.static('public')); app.use( app.router ); app.use(function(r ...

Update the current Backend React framework capabilities with Server Side Rendering

My project has a project hierarchy setup as follows: Project directory -client -package.json -src //folder with react components -.... -build -... -package.json -app.js //server After doing some research, it seems like SSR (Server Side Rendering) ...

Utilizing Binding Time in Angular for Enhanced Views

I am completely new to Angular JS. I have a simple question that I have been searching for answers on SO. My goal is to display the current time in real-time (refreshing every second as the clock ticks) on my view. Here's what I have tried so far: H ...

Difficulty Aligning Header Elements - Combining Navigation and Logo on the Same Line

I am currently facing an issue with positioning a logo and navigation links within a <header> element. When I apply the CSS property text-align:center;, the logo aligns to the center on one line while the navigation links appear on another line direc ...

Is there a way to trigger an Ajax function after individually selecting each checkbox in a list in MVC 4 using Razor syntax?

Is it possible to trigger an AJAX function when a checkbox within the ul below is checked? Each checkbox has a unique name attribute, such as chkbrand_1, chkbrand_2, chkbrand_3, etc. I am able to obtain the correct value using this code: $('.sear ...

Issues with the functionality of the Customer ListItem on a Selectable List have been identified within the material-ui framework

When using the Selectable List, I encountered an issue where if I wrote a custom list item, the list wasn't selectable. However, when I used the list item directly, it was selectable. var DataCenterRow = React.createClass({ render: function () { ...

I am unable to log the response, but I can view it in Postman and the network tab

Currently, I am working on setting up a register feature with a specific endpoint. The challenge I am facing revolves around handling validation responses from the backend. For instance, if I attempt to register with a username that is less than six charac ...

Guide on utilizing the root feature in babel-plugin-module-resolver?

Currently, I'm attempting to integrate babel-plugin-module-resolver into a react-native application. When I include the plugin configuration in my babel.config.js, everything functions as expected. plugins: [ [ 'module-resolver', ...

Exploring Angular JS: Understanding the Framework's Structure and FAQs

After diving into the world of AngularJS and familiarizing myself with its tutorial and documentation, I find myself in need of guidance on organizing the structure of my project. My goal is to create a single page app with different main sections such as ...

The positioning problem arising from using a Vuetify select dropdown within a datatable

Vuetify datatable is being used with 20 columns, functioning properly. To view all the columns, horizontal scrolling is available. Filters are needed for each column in the header, achieved using v-slot:header. An issue arises when clicking on the select ...

Why is it that a JSX element can take a method with parentheses or without as its child?

Why is it that when I attempt to pass a method without parentheses into a React component as a child of one of the JSX elements, an error appears in the console? However, simply adding parentheses resolves the issue. What's the deal? For example: ran ...

Adjust the height of images to be consistent

I'm currently working on creating a grid layout with 4 images in a row using DaisyUI card component. However, I've run into an issue where there is white space at the bottom of some images due to varying image heights. Is there a solution that wo ...

Initiate a connection to the cloud management system

I am utilizing the following library to establish a connection with the cloud controller https://github.com/prosociallearnEU/cf-nodejs-client const endpoint = "https://api.mycompany.com/"; const username = "myuser"; const password = "mypass"; const Clou ...

Position Font Awesome to the right of the text in the list

Hi there, I am currently working on a project where I want to align font awesome icons to the right of my text within a list. My website is in a Right-to-Left (RTL) language and I can't seem to find any resources on how to achieve this. Any help would ...

Unable to Add Dependency to Subclassed Object

In my setup, there are three classes that interact with each other. I am utilizing inversify for handling dependency injection. However, I encountered an issue when I injected the class MessageBroker into the derived class Repository and found that the Mes ...