Reputation: 1
I want to replicate a section for my site. The inspiration I took is from clay.com
and I want to replicate the How it works section. So far my code is having two main issues, the button functionality is not working properly, and second, after refreshing the page when I scroll the overall section gets disturbed. The code is custom and will be implemented on Elementor. My code is:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
margin: 0;
background: #15151e;
overflow-x: hidden;
}
.racesWrapper {
position: relative;
height: 100vh; / Adjust based on the number of slides /
overflow: hidden;
transition: background-color 1s ease; / Add this line for smooth color transition /
}
.swiper-container {
height: 100%;
}
.swiper-wrapper {
display: flex;
flex-direction: row;
}
.swiper-slide {
font-family: 'Staatliches', cursive;
/*font-size: 30vw;*/
/*color: #e10600;*/
display: flex;
align-items: center;
justify-content: center;
text-align: center;
height: 80vh;
width: 100vw; / Full width for horizontal scroll /
/*background: #e1e1ff;*/
/*background: #e1e1ff36;*/
}
.button-container {
position: absolute;
top: 10px;
z-index: 1000;
display: flex;
justify-content: space-around;
width: 100%;
}
.button-container button {
display: block;
margin-bottom: 5px;
width: 24%;
height: 50px;
}
.progress-bar {
position: absolute;
bottom: 0;
left: 0;
height: 5px;
background: #333;
width: 100%;
z-index: 1000;
}
.progress-bar-inner {
height: 100%;
background: #e10600;
width: 0;
transition: width 0.2s ease, background-color 0.2s ease;
}
/*Content styling start*/
.swiper-slide .row {
/*border: 1px solid red;*/
width: 100%;
height: 100%;
margin: 0 auto;
}
.swiper-slide .col-md-6 {
/*border: 1px solid blue;*/
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding-inline: 50px;
}
.swiper-slide .col-md-6 :is(p,h2){
text-align: left;
}
.swiper-slide .img-wrapper {
width: 75%;
}
.swiper-slide .img-col{
align-items: center !important;
justify-content: center !important;
}
.swiper-slide a.cta-btn {
background: #222;
color: white;
padding: 10px 20px;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="racesWrapper">
<!-- Swiper -->
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">
<div class="row">
<div class="col-md-6">
<h2>Unbeatable Performance 14X Faster Speed</h2>
<p>Devrims provides enterprise-grade, managed cloud servers tailored to your specific website and project requirements. The platform offers high performance storage, lightweight technology stacks optimized for PHP applications.</p>
<a class="cta-btn">Start Free Trial</a>
</div>
<div class="col-md-6 img-col">
<div class="img-wrapper">
<img src="https://images.unsplash.com/photo-1551288049-bebda4e38f71?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D">
</div>
</div>
</div>
</div>
<div class="swiper-slide">Flexibility</div>
<div class="swiper-slide">Reliability</div>
<div class="swiper-slide">Costing</div>
</div>
</div>
<div class="progress-bar">
<div class="progress-bar-inner"></div>
</div>
<div class="button-container">
<button onclick="goToSlide(0)">Performance</button>
<button onclick="goToSlide(1)">Flexibility</button>
<button onclick="goToSlide(2)">Reliability</button>
<button onclick="goToSlide(3)">Costing</button>
</div>
</div>
<script src="https://unpkg.com/swiper/swiper-bundle.min.js" defer></script>
<script src="https://unpkg.com/gsap@3/dist/gsap.min.js" defer></script>
<script src="https://unpkg.com/gsap@3/dist/ScrollTrigger.min.js" defer></script>
<script src="https://unpkg.com/gsap@3/dist/ScrollToPlugin.min.js" defer></script>
<script>
gsap.registerPlugin(ScrollTrigger, ScrollToPlugin);
const swiper = new Swiper('.swiper-container', {
direction: 'horizontal',
loop: false,
speed: 1000,
slidesPerView: 1,
spaceBetween: 0,
});
function getSwiperWrapperWidth() {
return document.querySelector(".swiper-wrapper").scrollWidth;
}
const horizontalScroll = gsap.to(".swiper-wrapper", {
xPercent: -100 * (swiper.slides.length - 1),
ease: "none",
scrollTrigger: {
trigger: ".racesWrapper",
pin: true,
scrub: 1,
markers: true,
start: 'top top',
end: () => `+=${getSwiperWrapperWidth()}`,
invalidateOnRefresh: true,
onUpdate: self => {
const progress = self.progress;
document.querySelector(".progress-bar-inner").style.width = `${progress * 100}%`;
const colorIndex = Math.floor(progress * (colors.length - 1));
document.querySelector(".racesWrapper").style.backgroundColor = colors[colorIndex];
gsap.to(".racesWrapper", {
backgroundColor: colors[colorIndex],
duration: 0.05, // Adjust duration if necessary
ease: "power1.inOut" // Smooth easing function
});
}
}
});
const colors = [
"#DADDEF", "#D6DAEE", "#D2D5EC", "#CDD3EB", "#CACFE9",
"#C6CAE7", "#C1C7E5", "#BDC3E3", "#B9C0E1", "#ADB5DC",
"#A9B1DA", "#A5AED8", "#A2ABD6", "#9DA6D4", "#98A3D2",
"#919CCF", "#9EA4D3", "#A7AAD5", "#B1AEC8", "#BCB2B6",
"#C8B7A3", "#D3BB91", "#DFC07D", "#EAC36A", "#F6C85A",
"#FFCC4A", "#F3C264", "#E9B780", "#DDAC9C", "#D2A1B9",
"#C697D2", "#BB8BEF", "#B384FE", "#B384FE", "#B384FE",
"#B384FE", "#B384FE", "#B384FE"
];
function updateProgressBar() {
const progress = (swiper.activeIndex / (swiper.slides.length - 1)) * 100;
document.querySelector(".progress-bar-inner").style.width = `${progress}%`;
const colorIndex = Math.floor((swiper.activeIndex / (swiper.slides.length - 1)) * (colors.length - 1));
document.querySelector(".racesWrapper").style.backgroundColor = colors[colorIndex];
gsap.to(".racesWrapper", {
backgroundColor: colors[colorIndex],
duration: 0.05, // Adjust duration if necessary
ease: "power1.inOut" // Smooth easing function
});
}
function goToSlide(index) {
// Slide to the desired index
swiper.slideTo(index);
// Define the swiper wrapper width
const swiperWrapperWidth = 5616;
// Determine the scroll position based on the button clicked
let scrollPosition;
switch (index) {
case 0:
// Fixed scroll position for the first button
scrollPosition = 1400;
break;
case 1:
// 26% of the swiper wrapper width
// scrollPosition = swiperWrapperWidth * 0.26;
scrollPosition = 3108;
break;
case 2:
// 52% of the swiper wrapper width
// scrollPosition = swiperWrapperWidth * 0.52;
scrollPosition = 4812;
break;
case 3:
// 76% of the swiper wrapper width
// scrollPosition = swiperWrapperWidth * 0.76;
scrollPosition = 6520;
break;
default:
// Default to the calculated position for other slides
scrollPosition = (index / (swiper.slides.length - 1)) * swiperWrapperWidth;
break;
}
// Log the scroll position for debugging
console.log("Scroll Position: ", scrollPosition);
// Smoothly scroll to the calculated position
gsap.to(window, {
scrollTo: {
y: scrollPosition,
autoKill: false },
duration: 0.5,
ease: "linear"
});
// Update the progress bar and background color
updateProgressBar();
// Refresh ScrollTrigger to account for changes
ScrollTrigger.refresh();
}
swiper.on('slideChange', () => {
updateProgressBar();
});
// Initial update
updateProgressBar();
</script>
</body>
</html>
I tried the code mentioned above but the button functionality is not working properly
Upvotes: 0
Views: 119
Reputation: 489
After testing your code, I found some issues which leads to some errors in the console.
swiper
before initialization": This is because the swiper
variable is being accessed before it is initialized.goToSlide
is not defined": The goToSlide
function is not defined in a scope accessible to the button onclick
handlers.Fixes:
Used DomContentLoaded
event ensuring proper initialization of the swiper
variable inside a DOMContentLoaded
event listener. This ensures the DOM is fully loaded before the script runs, so swiper
is initialized before any function tries to access it. This is done by wrapping your initial code inside the DOMContentLoaded
event listener.
document.addEventListener('DOMContentLoaded', function() {
const swiper = new Swiper('.swiper-container', {
direction: 'horizontal',
loop: false,
speed: 1000,
slidesPerView: 1,
spaceBetween: 0,
});
});
Defining goToSlide
function in the correct scope, within the DOMContentLoaded
event listener. Assign it to window
object to make it globally accessible.
function goToSlide(index) {
swiper.slideTo(index);
// Additional logic...
}
window.goToSlide = goToSlide;
The full correct code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Swiper and GSAP Integration</title>
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
<style>
body {
margin: 0;
background: #15151e;
overflow-x: hidden;
}
.racesWrapper {
position: relative;
height: 100vh; /* Adjust based on the number of slides */
overflow: hidden;
transition: background-color 1s ease; /* Add this line for smooth color transition */
}
.swiper-container {
height: 100%;
}
.swiper-wrapper {
display: flex;
flex-direction: row;
}
.swiper-slide {
font-family: 'Staatliches', cursive;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
height: 80vh;
width: 100vw; /* Full width for horizontal scroll */
}
.button-container {
position: absolute;
top: 10px;
z-index: 1000;
display: flex;
justify-content: space-around;
width: 100%;
}
.button-container button {
display: block;
margin-bottom: 5px;
width: 24%;
height: 50px;
}
.progress-bar {
position: absolute;
bottom: 0;
left: 0;
height: 5px;
background: #333;
width: 100%;
z-index: 1000;
}
.progress-bar-inner {
height: 100%;
background: #e10600;
width: 0;
transition: width 0.2s ease, background-color 0.2s ease;
}
/* Content styling start */
.swiper-slide .row {
width: 100%;
height: 100%;
margin: 0 auto;
}
.swiper-slide .col-md-6 {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding-inline: 50px;
}
.swiper-slide .col-md-6 :is(p, h2) {
text-align: left;
}
.swiper-slide .img-wrapper {
width: 75%;
}
.swiper-slide .img-col {
align-items: center !important;
justify-content: center !important;
}
.swiper-slide a.cta-btn {
background: #222;
color: white;
padding: 10px 20px;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="racesWrapper">
<!-- Swiper -->
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">
<div class="row">
<div class="col-md-6">
<h2>Unbeatable Performance 14X Faster Speed</h2>
<p>Devrims provides enterprise-grade, managed cloud servers tailored to your specific website and project requirements. The platform offers high performance storage, lightweight technology stacks optimized for PHP applications.</p>
<a class="cta-btn">Start Free Trial</a>
</div>
<div class="col-md-6 img-col">
<div class="img-wrapper">
<img src="https://images.unsplash.com/photo-1551288049-bebda4e38f71?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D">
</div>
</div>
</div>
</div>
<div class="swiper-slide">Flexibility</div>
<div class="swiper-slide">Reliability</div>
<div class="swiper-slide">Costing</div>
</div>
</div>
<div class="progress-bar">
<div class="progress-bar-inner"></div>
</div>
<div class="button-container">
<button onclick="goToSlide(0)">Performance</button>
<button onclick="goToSlide(1)">Flexibility</button>
<button onclick="goToSlide(2)">Reliability</button>
<button onclick="goToSlide(3)">Costing</button>
</div>
</div>
<script src="https://unpkg.com/swiper/swiper-bundle.min.js" defer></script>
<script src="https://unpkg.com/gsap@3/dist/gsap.min.js" defer></script>
<script src="https://unpkg.com/gsap@3/dist/ScrollTrigger.min.js" defer></script>
<script src="https://unpkg.com/gsap@3/dist/ScrollToPlugin.min.js" defer></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
gsap.registerPlugin(ScrollTrigger, ScrollToPlugin);
const swiper = new Swiper('.swiper-container', {
direction: 'horizontal',
loop: false,
speed: 1000,
slidesPerView: 1,
spaceBetween: 0,
});
function getSwiperWrapperWidth() {
return document.querySelector(".swiper-wrapper").scrollWidth;
}
const horizontalScroll = gsap.to(".swiper-wrapper", {
xPercent: -100 * (swiper.slides.length - 1),
ease: "none",
scrollTrigger: {
trigger: ".racesWrapper",
pin: true,
scrub: 1,
markers: true,
start: 'top top',
end: () => `+=${getSwiperWrapperWidth()}`,
invalidateOnRefresh: true,
onUpdate: self => {
const progress = self.progress;
document.querySelector(".progress-bar-inner").style.width = `${progress * 100}%`;
const colorIndex = Math.floor(progress * (colors.length - 1));
document.querySelector(".racesWrapper").style.backgroundColor = colors[colorIndex];
gsap.to(".racesWrapper", {
backgroundColor: colors[colorIndex],
duration: 0.05, // Adjust duration if necessary
ease: "power1.inOut" // Smooth easing function
});
}
}
});
const colors = [
"#DADDEF", "#D6DAEE", "#D2D5EC", "#CDD3EB", "#CACFE9",
"#C6CAE7", "#C1C7E5", "#BDC3E3", "#B9C0E1", "#ADB5DC",
"#A9B1DA", "#A5AED8", "#A2ABD6", "#9DA6D4", "#98A3D2",
"#919CCF", "#9EA4D3", "#A7AAD5", "#B1AEC8", "#BCB2B6",
"#C8B7A3", "#D3BB91", "#DFC07D", "#EAC36A", "#F6C85A",
"#FFCC4A", "#F3C264", "#E9B780", "#DDAC9C", "#D2A1B9",
"#C697D2", "#BB8BEF", "#B384FE", "#B384FE", "#B384FE",
"#B384FE", "#B384FE", "#B384FE"
];
function updateProgressBar() {
const progress = (swiper.activeIndex / (swiper.slides.length - 1)) * 100;
document.querySelector(".progress-bar-inner").style.width = `${progress}%`;
const colorIndex = Math.floor((swiper.activeIndex / (swiper.slides.length - 1)) * (colors.length - 1));
document.querySelector(".racesWrapper").style.backgroundColor = colors[colorIndex];
gsap.to(".racesWrapper", {
backgroundColor: colors[colorIndex],
duration: 0.05, // Adjust duration if necessary
ease: "power1.inOut" // Smooth easing function
});
}
function goToSlide(index) {
// Slide to the desired index
swiper.slideTo(index);
// Define the swiper wrapper width
const swiperWrapperWidth = 5616;
// Determine the scroll position based on the button clicked
let scrollPosition;
switch (index) {
case 0:
// Fixed scroll position for the first button
scrollPosition = 1400;
break;
case 1:
// 26% of the swiper wrapper width
scrollPosition = 3108;
break;
case 2:
// 52% of the swiper wrapper width
scrollPosition = 4812;
break;
case 3:
// 76% of the swiper wrapper width
scrollPosition = 6520;
break;
default:
// Default to the calculated position for other slides
scrollPosition = (index / (swiper.slides.length - 1)) * swiperWrapperWidth;
break;
}
// Log the scroll position for debugging
console.log("Scroll Position: ", scrollPosition);
// Smoothly scroll to the calculated position
gsap.to(window, {
scrollTo: {
y: scrollPosition,
autoKill: false
},
duration: 0.5,
ease: "linear"
});
// Update the progress bar and background color
updateProgressBar();
// Refresh ScrollTrigger to account for changes
ScrollTrigger.refresh();
}
swiper.on('slideChange', () => {
updateProgressBar();
});
// Initial update
updateProgressBar();
// Make goToSlide function accessible globally
window.goToSlide = goToSlide;
});
</script>
</body>
</html>
Upvotes: 1