[Typescript] Vertical parallax
Last updated: 5th September 2024
I've always been fascinated by the little details that can make a difference in a project. Recently, I decided to challenge myself by creating a vertical parallax component using TypeScript. My goal was simple: build something lightweight, easy to integrate, and, above all, efficient across different devices.
Why I Created This Parallax Component
When I set out to build this component, I had a few specific objectives in mind. First, I wanted it to be straightforward to implement, no unnecessary complexity. Code should be clean and efficient. Secondly, customization was key. Different projects have different needs, and I wanted to make sure this component could adapt to those needs. Most importantly, I focused on performance, particularly on mobile devices.
Mobile performance is crucial. With so much web traffic coming from mobile, any lag or unnecessary processing can lead to a poor user experience. That's why I made a deliberate choice not to enable the parallax effect on mobile devices. Instead of forcing an effect that could slow things down, the component simply displays the final image state right away on mobile. This keeps the experience smooth and fast where it matters most.
Key Features
- Desktop-Only Parallax: On desktops, the parallax effect adds that extra visual interest as you scroll. On mobile, it's about keeping things simple and fast. No parallax, just the final image in place.
- Optimized performance: Carefully crafted to minimize performance overhead on scrolling, ensuring a smooth user experience even on devices with lower processing power.
- Ease of Use: The component is easy to integrate, requiring minimal setup. Just a few lines of code, and it's ready to go.
- Flexibility: You can adjust the speed of the parallax effect for each element, giving you control over how the effect is applied.
How It Works
The component first checks whether the user is on a mobile device or a desktop. If it's a desktop, the parallax effect activates as you scroll, offering a smooth experience. On mobile devices, the component doesn't attach any parallax events; it simply renders the final image state, ensuring optimal performance.
Here's the breakdown:
- Container and Elements: The component allows easy selection of the container and target elements for the parallax effect.
- Event Handling: Scroll event listeners are added on desktop to trigger the parallax effect.
- Mobile Optimization: On mobile, the code bypasses the parallax effect entirely, focusing instead on delivering a fast, responsive experience.
Exemple of the parallax effect with a floating text.
Class code and how to use it
Fully documented class code in TypeScript:
class VerticalParallax {
private container: HTMLDivElement; // Reference to the container element
private elements: NodeListOf<HTMLElement>; // Collection of elements to apply parallax effect
private isMobile: boolean; // Boolean to check if the device is mobile
/**
* Constructor for creating a VerticalParallax instance.
* @param container - The ID of the container HTMLDivElement.
* @param selector - The selector used to find elements within the container for applying the parallax effect.
* Initializes the parallax elements and attaches the necessary event listeners.
*/
constructor(container: string, selector: string) {
this.container = document.getElementById(container) as HTMLDivElement; // Initializes the main container div
this.elements = document.querySelectorAll(selector); // Initializes the elements based on the selector
this.isMobile = this.checkIfMobile(); // Determine if the device is mobile
if (!this.isMobile) {
this.attachEvents(); // Set up event listeners for the scroll event if not on mobile
}
}
/**
* Checks if the device is a mobile device.
* @returns boolean - True if the device is mobile, false otherwise.
*/
private checkIfMobile(): boolean {
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
return /android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
}
/**
* Attaches scroll event listeners to the window.
* Listens for scroll events to apply the parallax effect.
*/
private attachEvents(): void {
window.addEventListener("scroll", () => {
this.handleScroll();
});
}
/**
* Handles the scroll event to apply parallax effects to the elements.
* Calculates and applies the vertical parallax effect based on the scroll position.
*/
private handleScroll(): void {
const containerRect = this.container.getBoundingClientRect(); // Get the container's position relative to the viewport
// Check if the top of the container is within view
if (containerRect.top <= 0 && containerRect.bottom >= 0) {
this.elements.forEach((element) => {
const speed = parseFloat(
element.getAttribute("data-parallax-speed") || "0.2"
); // Read and parse the parallax speed attribute
const containerOffset = -containerRect.top;
const parallaxOffset = containerOffset * speed;
element.style.transform = `translateY(${parallaxOffset}px)`; // Apply the parallax transformation
});
} else if (containerRect.top > 0) {
this.elements.forEach((element) => {
element.style.transform = `translateY(0px)`; // Reset transformation when the container is above the viewport
});
}
}
/**
* Refreshes the parallax effects manually, for use when significant page layout changes occur (like theme changes).
*/
public refresh(): void {
if (!this.isMobile) {
this.elements = this.container.querySelectorAll('[data-parallax-speed]');
this.handleScroll();
}
}
}
Easy to use in any other TypeScript file:
document.addEventListener("DOMContentLoaded", () => {
new VerticalParallax("verticalParallax-container", ".verticalParallax-layer");
});
HTML implementation with 2 pictures: