Technologies:
Tolerim
a month ago
What is the method for refreshing AOS animations on a main element with scroll-snap enabled sections that have scroll-snap-align?
To animate elements on my webpage upon scrolling, I am using the AOS (Animate On Scroll) library. However, I am encountering difficulty when implementing AOS on a main element that has scroll-snap enabled and has scroll-snap-align sections inside it. The issue arises because the scroll-snap sections have a height of 100vh, causing the main element to lack a scrollbar, resulting in AOS animations not functioning. I attempted to use AOS.refreshHard() to recalculate the AOS animations, but it was unsuccessful. Can someone provide suggestions on how to make AOS animations work with a scroll-snap enabled main element that has scroll-snap sections? Below is the code that I am currently working with:
import React, { useEffect, useState } from "react";
import { Parallax, ParallaxLayer } from "@react-spring/parallax";
import "../styles/Home.scss";
import Loader from "../components/loader/Loader";
import FirstSection from "../components/Home/FirstSection";
import SecondSection from "../components/Home/SecondSection";
import ThirdSection from "../components/Home/ThirdSection.jsx";
import FourthSection from "../components/Home/FourthSection";
import FifthSection from "../components/Home/FifthSection";
import SixthSection from "../components/Home/SixthSection";
import SeventhSection from "../components/Home/SeventhSection";
import EigthSection from "../components/Home/EigthSection";
function Home() {
const [loading, setLoading] = useState(true);
useEffect(() => {
setTimeout(() => {
setLoading(false);
}, 4300);
}, []);
return (
<>
{loading ? (
<Loader />
) : (
<>
<main
style={{
height: "100vh",
scrollSnapType: "y mandatory",
scrollBehavior: "smooth",
overflowY: "scroll",
overflowX: "hidden",
}}
>
<FirstSection />
<SecondSection />
<ThirdSection />
<section style={{ scrollSnapAlign: "center" }}>
<Parallax
pages={2}
className="custom-parallax"
style={{
height: "100vh",
}}
>
<ParallaxLayer
offset={0}
factor={1}
speed={0.2}
sticky={{ start: 0, end: 1 }}
style={{
zIndex: "1",
height: "100vh",
}}
>
<FourthSection />
</ParallaxLayer>
<ParallaxLayer
offset={1}
factor={1}
speed={0.2}
sticky={{ start: 1, end: 2 }}
style={{
zIndex: "1",
height: "100vh",
}}
>
<FifthSection />
</ParallaxLayer>
</Parallax>
</section>
<SixthSection />
<SeventhSection />
<EigthSection />
</main>
</>
)}
</>
);
}
export default Home;
Answers(2)
Vogi
a month ago
Verified Answer
I understand that you are having difficulty implementing AOS on a main element that has scroll-snap enabled and has scroll-snap-align sections inside it. The issue arises because the scroll-snap sections have a height of 100vh, causing the main element to lack a scrollbar, resulting in AOS animations not functioning. You attempted to use AOS.refreshHard() to recalculate the AOS animations, but it was unsuccessful.
One suggestion is to use the following code snippet:
import AOS from "aos";
import "aos/dist/aos.css";
function App() {
useEffect(() => {
const aos = AOS.init({
disable: "mobile",
once: true,
startEvent: "load",
});
aos.refresh();
}, []);
return (
<div>
<h1 data-aos="fade-up">Hello World</h1>
</div>
);
}
export default App;
This code snippet initializes AOS and refreshes it after the component mounts. The aos.refresh() method recalculates all of the elements' positions and updates the animation state.
Another suggestion is to use the following CSS:
.main {
overflow-y: scroll;
}
.section {
height: 100vh;
scroll-snap-align: start;
overflow-y: auto;
}
This CSS sets the overflow-y property of the main element to scroll, which adds a scrollbar to the main element. It also sets the overflow-y property of the scroll-snap sections to auto, which allows them to have their own scrollbar.
I hope this helps! Let me know if you have any other questions.Sources
Cool on Scroll Animations Made Easy With the AOS Librarycss - Scroll snap duration & AOS - Stack Overflowjavascript - How to refresh AOS animations on a scroll-snap enabled ...Tolerim
a month ago
One potential solution could be to add a custom AOS offset for each section, based on its position within the scroll-snap container. You can calculate the offset value based on the height of each section and the position of the scroll-snap container using JavaScript.
Here's an example implementation:
import AOS from "aos";
import "aos/dist/aos.css";
import React, { useEffect, useState, useRef } from "react";
import { Parallax, ParallaxLayer } from "@react-spring/parallax";
import "../styles/Home.scss";
import Loader from "../components/loader/Loader";
import FirstSection from "../components/Home/FirstSection";
import SecondSection from "../components/Home/SecondSection";
import ThirdSection from "../components/Home/ThirdSection.jsx";
import FourthSection from "../components/Home/FourthSection";
import FifthSection from "../components/Home/FifthSection";
import SixthSection from "../components/Home/SixthSection";
import SeventhSection from "../components/Home/SeventhSection";
import EigthSection from "../components/Home/EigthSection";
function Home() {
const [loading, setLoading] = useState(true);
const scrollContainerRef = useRef(null);
useEffect(() => {
setTimeout(() => {
setLoading(false);
// Initialize AOS after the content has loaded
AOS.init({
once: true,
offset: calculateAOSOffsets(),
});
}, 4300);
}, []);
/**
* Calculate the AOS offset for each section based on its position
* within the scroll container
*/
const calculateAOSOffsets = () => {
const sectionOffsets = [];
const sections = scrollContainerRef.current.querySelectorAll(
"section[data-aos]"
);
const scrollContainerRect = scrollContainerRef.current.getBoundingClientRect();
sections.forEach((section) => {
const sectionRect = section.getBoundingClientRect();
const sectionOffset =
sectionRect.top -
scrollContainerRect.top -
window.innerHeight / 2 +
sectionRect.height / 2;
sectionOffsets.push(sectionOffset);
});
return sectionOffsets.join(",");
};
return (
<>
{loading ? (
<Loader />
) : (
<>
<main
ref={scrollContainerRef}
data-aos-easing="ease-out-back"
data-aos-delay="200"
style={{
height: "100vh",
scrollSnapType: "y mandatory",
scrollBehavior: "smooth",
overflowY: "scroll",
overflowX: "hidden",
}}
>
<FirstSection data-aos="fade-up" />
<SecondSection data-aos="fade-down" />
<ThirdSection data-aos="fade-up" />
<section
style={{ scrollSnapAlign: "center" }}
data-aos-offset="-100"
data-aos="fade-left"
>
<Parallax
pages={2}
className="custom-parallax"
style={{
height: "100vh",
}}
>
<ParallaxLayer
offset={0}
factor={1}
speed={0.2}
sticky={{ start: 0, end: 1 }}
style={{
zIndex: "1",
height: "100vh",
}}
>
<FourthSection />
</ParallaxLayer>
<ParallaxLayer
offset={1}
factor={1}
speed={0.2}
sticky={{ start: 1, end: 2 }}
style={{
zIndex: "1",
height: "100vh",
}}
>
<FifthSection />
</ParallaxLayer>
</Parallax>
</section>
<SixthSection data-aos="fade-up" />
<SeventhSection data-aos="fade-down" />
<EigthSection data-aos="fade-up" />
</main>
</>
)}
</>
);
}
export default Home;
In this example, we are using the ref attribute to get a reference to the scroll container element, and then we are using that reference to calculate the AOS offset values for each section. We are also setting the data-aos-offset attribute on each section element to set its custom AOS offset value.
Then, in the calculateAOSOffsets function, we are looping through each section element and calculating its AOS offset based on its position within the scroll container. We are using the getBoundingClientRect method to get the position and size of each element, and then we are calculating the AOS offset value based on the vertical center of the element and the height of the window.
Finally, we are initializing AOS with the calculated offset values in the useEffect hook, and we are setting the data-aos and data-aos-offset attributes on each section element to enable AOS and set its custom offset value.
With this implementation, AOS should work properly even on a scroll-snap enabled main element with scroll-snap sections.