Scroll animation effect
April 21, 2025 Β· AI Conversations
let lastScrollY = window.scrollY;
if (redBanner) {
let observer = new IntersectionObserver(
function (entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Detect scroll direction
let currentScrollY = window.scrollY;
let direction = currentScrollY > lastScrollY ? "down" : "up";
redBanner.classList.remove("scroll-up", "scroll-down"); // reset both
void redBanner.offsetWidth; // force reflow to restart animation
if (direction === "down") {
redBanner.classList.add("scroll-down");
} else {
redBanner.classList.add("scroll-up");
}
lastScrollY = currentScrollY;
} else {
redBanner.classList.remove("scroll-up", "scroll-down");
}
});
},
{ threshold: 0.3 }
);
observer.observe(redBanner);
}
MOve content to extreme left to extreme right
Here's how you can update your **CSS** to achieve that animation:
.blue-banner {
transition: transform 0.5s ease;
transform: translateX(0);
}
.blue-banner.scroll-down {
transform: translateX(100vw); /* move to extreme right */
}
.blue-banner.scroll-up {
transform: translateX(-100vw); /* move to extreme left */
}
Or if you prefer to animate it smoothly:
@keyframes slide-right {
from {
transform: translateX(0);
}
to {
transform: translateX(100vw);
}
}
@keyframes slide-left {
from {
transform: translateX(0);
}
to {
transform: translateX(-100vw);
}
}
.blue-banner.scroll-down {
animation: slide-right 0.6s forwards;
}
.blue-banner.scroll-up {
animation: slide-left 0.6s forwards;
}
Let me know if you want the banner to **return to original position** afterward or stay off-screen!
—
### β Updated JavaScript (same base, scroll-aware)
let redBanner = document.querySelector(".blue-banner");
let lastScrollY = window.scrollY;
if (redBanner) {
let observer = new IntersectionObserver(
function (entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
let currentScrollY = window.scrollY;
let direction = currentScrollY > lastScrollY ? "down" : "up";
redBanner.classList.remove("scroll-up", "scroll-down");
void redBanner.offsetWidth; // force reflow
if (direction === "down") {
redBanner.classList.add("scroll-down");
} else {
redBanner.classList.add("scroll-up");
}
lastScrollY = currentScrollY;
} else {
redBanner.classList.remove("scroll-up", "scroll-down");
}
});
},
{ threshold: 0.5 } // change depending on when you want it to trigger
);
observer.observe(redBanner);
}
—
### β CSS for Left-to-Right and Right-to-Left Transitions
.blue-banner {
position: relative;
width: 100%;
transition: transform 0.6s ease;
}
/* When scrolling down, move banner to the right */
.blue-banner.scroll-down {
transform: translateX(100vw);
}
/* When scrolling up, move banner to the left */
.blue-banner.scroll-up {
transform: translateX(-100vw);
}
—
### π Optional: Keep the banner coming back to center after leaving viewport
If you want it to come back once it's out of view:
entry.isIntersecting === false
can be used to reset the transform:
redBanner.style.transform = "translateX(0)";
—
Let me know if you want to animate it **once only**, or **every time** it re-enters viewport, or return to center after a delay!
const banner = document.querySelector(".moving-image img");
window.addEventListener("scroll", () => {
const scrollY = window.scrollY;
banner.style.transform = `translateX(${scrollY * 0.12}px)`;
});
});
we have a parent div moving-banner now when its visible then start move it form extreme left to extreme right
Hereβs a clean and efficient solution using `IntersectionObserver` to **start the scroll-based transform only when `.moving-banner` is visible**:
—
### β Final JavaScript Solution
document.addEventListener("DOMContentLoaded", function () {
const bannerWrapper = document.querySelector(".moving-banner");
const bannerImage = document.querySelector(".moving-image img");
let isVisible = false;
// Create observer for the parent
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
isVisible = entry.isIntersecting;
});
},
{
threshold: 0.2, // adjust how much of the element must be visible
}
);
if (bannerWrapper) {
observer.observe(bannerWrapper);
}
window.addEventListener("scroll", () => {
if (!isVisible || !bannerImage) return;
// Move from extreme left to right gradually
const maxMove = window.innerWidth; // max move range
const scrollTop = window.scrollY;
const offset = scrollTop * 0.3; // adjust speed
bannerImage.style.transform = `translateX(${Math.min(offset, maxMove)}px)`;
});
});
—
### β Minimal Required CSS
.moving-image img {
transform: translateX(0);
transition: transform 0.2s ease-out;
will-change: transform;
}
—
### π§ͺ Explanation:
– The image only moves if `.moving-banner` is in the viewport.
– Scroll transforms the `img` from left to right.
– The movement is capped to prevent overflow beyond screen width.
—
Want it to **reset back** when not visible or move **from right to left** on scroll-up? I can help with that too.
– When the **`.moving-banner`** is visible in the viewport.
– And the user is scrolling **up and down** while itβs visible.
– The image should:
– Move **left on scroll up**
– Move **right on scroll down**
– And it should move **smoothly** with **every scroll movement**.
—
### β Full JavaScript Code (with scroll direction detection while in view):
document.addEventListener("DOMContentLoaded", function () {
const bannerWrapper = document.querySelector(".moving-banner");
const bannerImage = document.querySelector(".moving-image img");
let isVisible = false;
let lastScrollY = window.scrollY;
let offsetX = 0;
// Observe when .moving-banner is in view
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
isVisible = entry.isIntersecting;
});
},
{ threshold: 0.2 }
);
if (bannerWrapper) observer.observe(bannerWrapper);
window.addEventListener("scroll", () => {
if (!isVisible || !bannerImage) return;
const currentScrollY = window.scrollY;
const direction = currentScrollY > lastScrollY ? "down" : "up";
// Update position based on direction
if (direction === "down") {
offsetX += 5; // Move right
} else {
offsetX -= 5; // Move left
}
// Optional: Clamp the movement to stay within screen width range
const maxOffset = window.innerWidth - bannerImage.offsetWidth;
offsetX = Math.max(Math.min(offsetX, maxOffset), -maxOffset);
bannerImage.style.transform = `translateX(${offsetX}px)`;
lastScrollY = currentScrollY;
});
});
—
### β CSS for Smooth Movement
.moving-image img {
transition: transform 0.1s ease-out;
will-change: transform;
}
—
### π‘ Notes:
– `offsetX` accumulates left/right movement with every scroll change.
– It respects the visible area by detecting the scroll direction.
– Movement is bounded to prevent infinite image overflow.
—
Want to reset it when the section is out of view or add bounce-back effect? I can help tweak that too!
—
### β JavaScript: Always move right when scrolling (while in view)
document.addEventListener("DOMContentLoaded", function () {
const bannerWrapper = document.querySelector(".moving-banner");
const bannerImage = document.querySelector(".moving-image img");
let isVisible = false;
let offsetX = 0;
// Observe visibility of .moving-banner
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
isVisible = entry.isIntersecting;
});
},
{ threshold: 0.2 }
);
if (bannerWrapper) observer.observe(bannerWrapper);
// On scroll, always move right while visible
window.addEventListener("scroll", () => {
if (!isVisible || !bannerImage) return;
offsetX += 5; // Always move right
// Optional: prevent overflow beyond screen
const maxOffset = window.innerWidth;
if (offsetX > maxOffset) offsetX = 0;
bannerImage.style.transform = `translateX(${offsetX}px)`;
});
});
—
### β CSS for Smooth Rightward Movement
.moving-image img {
transition: transform 0.1s linear;
will-change: transform;
}
—
### π§ Optional Enhancements (if needed later):
– Reset position when section exits the viewport.
– Add looping animation when fully moved off-screen.
– Vary speed based on scroll delta.
Let me know if you'd like any of those!
—
### β Final Updated JavaScript (Scroll = Slide Right, Fully Visible)
document.addEventListener("DOMContentLoaded", function () {
const bannerWrapper = document.querySelector(".moving-banner");
const bannerImage = document.querySelector(".moving-image img");
let isVisible = false;
let offsetX = 0;
// Watch if .moving-banner is in viewport
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
isVisible = entry.isIntersecting;
});
},
{ threshold: 0.2 }
);
if (bannerWrapper) observer.observe(bannerWrapper);
window.addEventListener("scroll", () => {
if (!isVisible || !bannerImage) return;
// Max allowed offset so full image stays in view
const parentWidth = bannerWrapper.offsetWidth;
const imageWidth = bannerImage.offsetWidth;
const maxOffset = parentWidth - imageWidth;
if (offsetX < maxOffset) {
offsetX += 5; // Move slowly to right
bannerImage.style.transform = `translateX(${offsetX}px)`;
}
});
});
—
### β CSS for Smooth Movement
.moving-image img {
transition: transform 0.15s ease-out;
will-change: transform;
}
—
### β
Bonus Tip (Optional Reset)
If you'd like it to **reset to the left** when the user scrolls back to the top or exits the section, let me know β I can add that logic too.
Let me know if `.moving-image` is **smaller than its parent** β in that case, we can center or align it differently.
β
Move the image to the right on every scroll **while `.moving-banner` is visible**
β
Reset the image **back to the left** (`translateX(0)`) **when it goes out of view**
—
### β Final JavaScript (with auto-reset when out of view)
document.addEventListener("DOMContentLoaded", function () {
const bannerWrapper = document.querySelector(".moving-banner");
const bannerImage = document.querySelector(".moving-image img");
let offsetX = 0;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
const isVisible = entry.isIntersecting;
if (isVisible) {
// Start tracking scroll to move right
window.addEventListener("scroll", handleScroll);
} else {
// Stop tracking and reset to left
window.removeEventListener("scroll", handleScroll);
offsetX = 0;
bannerImage.style.transform = `translateX(0px)`;
}
});
},
{ threshold: 0.2 }
);
if (bannerWrapper) observer.observe(bannerWrapper);
function handleScroll() {
const parentWidth = bannerWrapper.offsetWidth;
const imageWidth = bannerImage.offsetWidth;
const maxOffset = parentWidth - imageWidth;
if (offsetX < maxOffset) {
offsetX += 5;
bannerImage.style.transform = `translateX(${offsetX}px)`;
}
}
});
—
### β Matching CSS
.moving-image img {
transition: transform 0.15s ease-out;
will-change: transform;
}
—
Let me know if you want:
– It to **reset with an animation** (slide back left smoothly)
– Or allow **looping motion** (restart from left after reaching max)
I'm happy to tweak it!
β
When `.moving-banner` **enters the visible area**,
β
The image inside `.moving-image img` should **animate once from left to right**
β
Then **stop** β no further movement on scroll
β
And when the section goes out of view and comes back in, the animation should **trigger again**
—
### β JavaScript: Animate Once Left-to-Right When Visible
document.addEventListener("DOMContentLoaded", function () {
const bannerWrapper = document.querySelector(".moving-banner");
const bannerImage = document.querySelector(".moving-image img");
let hasAnimated = false;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
const isVisible = entry.isIntersecting;
if (isVisible && !hasAnimated) {
bannerImage.classList.add("slide-right");
hasAnimated = true;
}
// Reset when leaving view, so animation can run again next time
if (!isVisible) {
bannerImage.classList.remove("slide-right");
hasAnimated = false;
}
});
},
{ threshold: 0.3 }
);
if (bannerWrapper) observer.observe(bannerWrapper);
});
—
### β CSS: Left-to-Right Animation
.moving-image img {
transform: translateX(0);
transition: none;
}
.moving-image img.slide-right {
animation: slideRightOnce 1.2s ease-out forwards;
}
@keyframes slideRightOnce {
from {
transform: translateX(0%);
}
to {
transform: translateX(100%);
}
}
—
### β
Result:
– Smooth **one-time slide** from left to right when the section appears
– **Resets** if user scrolls away
– Replays again when section re-enters viewport
Let me know if you want it to move **partially (like 50%)** or **adjust timing/distance**!
β
Animate the image from **left to right** when `.moving-banner` becomes visible
β
This should happen **every time** it's scrolled into view β both from top and bottom
β
Animation should **reset** once it goes out of view
—
### β Final JavaScript
document.addEventListener("DOMContentLoaded", function () {
const bannerWrapper = document.querySelector(".moving-banner");
const bannerImage = document.querySelector(".moving-image img");
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
const isVisible = entry.isIntersecting;
if (isVisible) {
// Restart animation
bannerImage.classList.remove("slide-right");
void bannerImage.offsetWidth; // Force reflow to retrigger animation
bannerImage.classList.add("slide-right");
} else {
// Remove class to prep for next entry
bannerImage.classList.remove("slide-right");
}
});
},
{ threshold: 0.3 } // adjust as needed
);
if (bannerWrapper) observer.observe(bannerWrapper);
});
—
### β CSS Animation
.moving-image img {
transform: translateX(0);
}
.moving-image img.slide-right {
animation: slideRightOnce 1.2s ease-out forwards;
}
@keyframes slideRightOnce {
from {
transform: translateX(0%);
}
to {
transform: translateX(100%);
}
}
—
### β
Optional: Limit distance to not go off screen
If you want the image to move **just halfway or stay fully visible**, modify the `to` value:
to {
transform: translateX(50%); /* Or whatever fits */
}
—
Let me know if you want a bounce effect or fade-in along with this!
const bannerWrapper = document.querySelector(".moving-banner");
const bannerImage = document.querySelector(".moving-image img");
let offsetX = 0;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
const isVisible = entry.isIntersecting;
if (isVisible) {
// Start tracking scroll to move right
window.addEventListener("scroll", handleScroll);
} else {
// Stop tracking and reset to left
window.removeEventListener("scroll", handleScroll);
offsetX = 0;
bannerImage.style.transform = `translateX(0px)`;
}
});
},
{ threshold: 0.2 }
);
if (bannerWrapper) observer.observe(bannerWrapper);
function handleScroll() {
const parentWidth = bannerWrapper.offsetWidth;
const imageWidth = bannerImage.offsetWidth;
const maxOffset = parentWidth – imageWidth;
if (offsetX < maxOffset) {
offsetX += 5;
bannerImage.style.transform = `translateX(${offsetX}px)`;
}
}
});
Above code is working correct just wnat move left to right speedy so that user can left to right movement clearly
### β
**Increase the `offsetX` step per scroll**
This will make the image move more **clearly and quickly** across the screen.
—
### β Updated Code with Faster Movement:
document.addEventListener("DOMContentLoaded", function () {
const bannerWrapper = document.querySelector(".moving-banner");
const bannerImage = document.querySelector(".moving-image img");
let offsetX = 0;
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
const isVisible = entry.isIntersecting;
if (isVisible) {
window.addEventListener("scroll", handleScroll);
} else {
window.removeEventListener("scroll", handleScroll);
offsetX = 0;
bannerImage.style.transform = `translateX(0px)`;
}
});
},
{ threshold: 0.2 }
);
if (bannerWrapper) observer.observe(bannerWrapper);
function handleScroll() {
const parentWidth = bannerWrapper.offsetWidth;
const imageWidth = bannerImage.offsetWidth;
const maxOffset = parentWidth - imageWidth;
// π₯ Increase speed from 5px β 20px
if (offsetX < maxOffset) {
offsetX += 20;
bannerImage.style.transform = `translateX(${offsetX}px)`;
}
}
});
—
### β (Optional) CSS for smoother motion:
.moving-image img {
transition: transform 0.1s ease-out;
will-change: transform;
}
—
### π οΈ Tweak suggestion:
You can adjust this line to control speed:
offsetX += 20; // β try 15, 25, or even 40 for a more dramatic effect
Let me know if you want it to animate smoothly **on its own without scroll**, or bounce back when it hits the right side.