I’m trying to implement a sticky card scroll effect, but I’m running into some issues and haven’t had any luck so far.
Here are the specific problems I’m facing:
The headline “Our Workflow” does not work as intended. Here is the screenshot

None of the workflow cards scroll or animate — they remain static on the page.
I’ve spent the entire day troubleshooting this without success. Below is a code snippet of my current implementation (HTML, CSS, and JS).
I’d really appreciate any guidance, or if someone could share a working version of this kind of scroll effect, that would be incredibly helpful.
Thanks in advance for your support!
HTMLCode:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Infinite Masta LLC - Launch Your Dream App</title>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/aos.css" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"/>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- Workflow Section -->
<section id="workflow" class="workflow">
<h2>Our Workflow</h2>
<div class="workflow-sticky-container">
<div class="workflow-sticky-content">
<div class="workflow-card active" id="card-1">
<div class="left-section">
<div class="icon"><i class="fas fa-lightbulb"></i></div>
</div>
<div class="right-section">
<div class="label">First</div>
<h3>Discovery & Planning</h3>
<p>Through in-depth discussions with stakeholders and thorough analysis, we gather all necessary requirements, conduct feasibility study, and clearly define the project scope to set a solid foundation for successful project execution.</p>
</div>
</div>
<div class="workflow-card" id="card-2">
<div class="left-section">
<div class="icon"><i class="fa-solid fa-code icon"></i></div>
</div>
<div class="right-section">
<div class="label">Then</div>
<h3>Design & Development</h3>
<p>Our team of expert designers and developers work together to create a user-friendly, visually appealing, and functional product that meets your specific business needs.</p>
</div>
</div>
<div class="workflow-card" id="card-3">
<div class="left-section">
<div class="icon"><i class="fas fa-vial"></i></div>
</div>
<div class="right-section">
<div class="label">And</div>
<h3>Testing & Deployment</h3>
<p>Before launching your product, we conduct rigorous testing to ensure that it performs flawlessly. Once everything is in order, we deploy the product and provide ongoing support to ensure its success.</p>
</div>
</div>
<div class="workflow-card" id="card-4">
<div class="left-section">
<div class="icon"><i class="fas fa-cogs"></i></div>
</div>
<div class="right-section">
<div class="label">Finally</div>
<h3>Support & Maintenance</h3>
<p>Our commitment doesn't end with the launch. We provide continuous support and maintenance to keep your project up-to-date, secure, and optimized. You can count on us as your reliable IT partner.</p>
</div>
</div>
</div>
</div>
</section>
<footer>
© 2025 Infinite Masta LLC. All rights reserved.
</footer>
<script src="https://unpkg.com/[email protected]/dist/aos.js"></script>
<script src="script.js"></script>
</body>
</html>
Here is the CSS CODE:
.workflow {
position: relative;
padding: 80px 20px;
background: #0F0F1A;
color: #fff;
text-align: center;
min-height: 100vh;
display: flex;
flex-direction: column;
}
.workflow h2 {
font-size: 42px;
color: #00FFFF;
margin-bottom: 40px;
position: sticky;
top: 120px;
z-index: 10;
background: linear-gradient(180deg, #0F0F1A 80%, rgba(15, 15, 26, 0));
padding: 20px 0 40px;
margin-top: -20px;
transition: all 0.3s ease;
}
.workflow h2.scrolled-past {
position: relative;
top: auto;
background: transparent;
}
/* Sticky Scroll Container */
.workflow-sticky-container {
position: relative;
width: 100%;
height: 400vh; /* 4x viewport height for 4 cards */
}
.workflow-sticky-content {
position: sticky;
top: 220px; /* Adjusted to account for sticky header and heading */
height: calc(100vh - 220px);
display: flex;
flex-direction: column;
justify-content: center;
}
/* Original Workflow Cards */
.workflow-card {
position: absolute;
top: 0;
left: 50%;
width: 90%;
max-width: 800px;
background: linear-gradient(145deg, #1A1A2E, #141421);
padding: 30px;
border-radius: 20px;
box-shadow: 0 15px 35px rgba(0,0,0,0.3);
display: flex;
transform: translateX(-50%) translateY(110%);
opacity: 0;
pointer-events: none;
transition: transform 0.8s cubic-bezier(0.23, 1, 0.32, 1), opacity 0.6s ease;
will-change: transform, opacity;
z-index: 1;
}
.workflow-card.active {
transform: translateX(-50%) translateY(0%);
opacity: 1;
pointer-events: auto;
z-index: 2;
}
.workflow-card .left-section {
width: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
border-right: 1px solid #2a2a42;
}
.workflow-card .icon {
font-size: 100px;
color: #00FFFF;
margin-bottom: 20px;
}
.workflow-card .label {
font-size: 18px;
color: #FF00C7;
font-weight: bold;
text-transform: uppercase;
}
.workflow-card .right-section {
width: 50%;
padding: 20px;
text-align: left;
}
.workflow-card h3 {
font-size: 28px;
margin: 15 0 15px;
color: white;
}
.workflow-card p {
font-size: 18px;
color: #b9b9b9;
line-height: 1.6;
margin: 0;
}
.workflow-card:hover {
transform: translateX(-50%) translateY(-5px);
box-shadow: 0 20px 40px rgba(0,0,0,0.4);
}
.workflow-card.active:hover {
transform: translateX(-50%) translateY(-5px);
}
Here is the js code
// Sticky Card Scroll Effect for Workflow Section
document.addEventListener("DOMContentLoaded", function () {
const workflowSection = document.querySelector("#workflow");
const workflowHeading = document.querySelector(".workflow h2");
const stickyContainer = document.querySelector(".workflow-sticky-container");
const stickyContent = document.querySelector(".workflow-sticky-content");
const cards = Array.from(document.querySelectorAll(".workflow-card"));
// Set the height of the sticky container based on number of cards
stickyContainer.style.height = `${cards.length * 100}vh`;
// Initialize the first card as active
cards.forEach((card, index) => {
if (index === 0) {
card.classList.add("active");
} else {
card.classList.remove("active");
}
});
// Scroll event listener for the sticky effect
window.addEventListener("scroll", function () {
const workflowTop = workflowSection.offsetTop;
const workflowHeight = workflowSection.offsetHeight;
const scrollPosition = window.scrollY;
const viewportHeight = window.innerHeight;
// Check if we're in the workflow section
if (scrollPosition >= workflowTop && scrollPosition <= workflowTop + workflowHeight) {
// Calculate which card should be active based on scroll position
const scrollProgress = (scrollPosition - workflowTop) / (workflowHeight - viewportHeight);
const activeIndex = Math.min(
Math.floor(scrollProgress * cards.length),
cards.length - 1
);
// Update active card
cards.forEach((card, index) => {
if (index === activeIndex) {
card.classList.add("active");
} else {
card.classList.remove("active");
}
});
// Check if we've scrolled past the last card
if (scrollPosition >= workflowTop + workflowHeight - viewportHeight * 0.8) {
workflowHeading.classList.add("scrolled-past");
} else {
workflowHeading.classList.remove("scrolled-past");
}
} else {
// Reset when not in workflow section
workflowHeading.classList.remove("scrolled-past");
}
});
});