I'm building a top sticky navigation with swiper. It should provide a mobile friendly navigation for long pages. If you click on one item it scrolls to the referenced content on the page.
Right now swiper highlights clicked items with the class "slideActiveClass". This should stay as it is. It also applies this class when sliding through the menu.
I need to change two things.
Any Idea how to implement this properly?
I think I'd need to use "
swiper.slideTo(index, speed, runCallbacks)
Run transition to the slide with index number equal to 'index' parameter for the duration equal to 'speed' parameter.
index - number - Index number of slide.
speed - number - Transition duration (in ms).
runCallbacks - boolean - Set it to false (by default it is true) and transition will not produce transition events."
taken from: https://swiperjs.com/swiper-api#method-swiper-slideTo
Any help is appreciated.
I'm planning to release the finished code to codepen, since I had trouble finding an example for the requested functionality and think it might be useful for a lot of projects.
var swiper = new Swiper(".swiper-container", {
slidesPerView: "auto",
freeMode: true,
slideToClickedSlide: true,
spaceBetween: 10,
mousewheel: true
});
html {
scroll-behavior: smooth;
}
.swiper-container {
width: 100%;
}
.swiper-slide {
background-color: rgba(0,255,0,0.1);
padding: 10px;
width: 20%!important;
}
.swiper-slide-active {
background-color: red;
}
.swiper-container ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.swiper-container a {
color: black;
text-align: center;
text-decoration: none;
display: inline-block;
width: 100%;
height: 100%;
}
.sticky {
position: sticky;
top: 0px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.1/css/swiper.min.css" rel="stylesheet"/>
<div class="sticky">
<div class="swiper-container" id="scroll-tags">
<ul class="swiper-wrapper">
<li class="swiper-slide"><a href="#1">One</a></li>
<li class="swiper-slide"><a href="#2">Two</a></li>
<li class="swiper-slide"><a href="#3">Three</a></li>
<li class="swiper-slide"><a href="#4">Four</a></li>
<li class="swiper-slide "><a href="#5">Five</a></li>
<li class="swiper-slide"><a href="#6">Six</a></li>
<li class="swiper-slide"><a href="#">item 7</a></li>
<li class="swiper-slide"><a href="#">item 8</a></li>
<li class="swiper-slide"><a href="#">item 9</a></li>
</ul>
</div>
</div>
<div style="height: 500vh">
<div class="class1" style="height:50vh;background-color: rgba(255,0,0,0.1);" id="1">One</div>
<div class="class2" style="height:50vh;background-color: rgba(255,123,32,0.1);" id="2">Two</div>
<div class="class3" style="height:50vh;background-color: rgba(255,122,0,0.1);" id="3">Three</div>
<div class="class4" style="height:50vh;background-color: rgba(255,122,0,0.1);" id="4">Four</div>
<div class="class5" style="height:50vh;background-color: rgba(255,122,0,0.1);" id="5">Five</div>
<div class="class6" style="height:50vh;background-color: rgba(255,122,0,0.1);" id="6">Six</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.1/js/swiper.min.js"></script>
Found a solution myself.
Got rid of using the ".swiper-slide-active" class to display active navigation and used ".swiper-slide-active2" instead.
I added an "alt" tag to every element in the swiper container. Every "alt" value corresponds to the swiper index number (starting at 0).
I change the class of the nav elements with an observer and tell swiper to slide to the index number. works okay. Improvements are welcome.
Link to codepen: https://codepen.io/peplebe/pen/MWOJgXe
var swiper = new Swiper(".swiper-container", {
slidesPerView: "auto",
freeMode: {
enabled: true,
sticky: true,
},
spaceBetween: 10,
mousewheel: true
});
//
function selectElementByClass(className) {
return document.querySelector(`.${className}`);
}
const sections = [
selectElementByClass("firstClass"),
selectElementByClass("secondClass"),
selectElementByClass("thirdClass"),
selectElementByClass("fourthClass"),
selectElementByClass("fifthClass"),
selectElementByClass("sixtClass")
];
const navItems = {
firstID: selectElementByClass("FirstNavItem"),
secondID: selectElementByClass("SecondNavItem"),
thirdID: selectElementByClass("ThirdNavItem"),
fourthID: selectElementByClass("FourthNavItem"),
fifthID: selectElementByClass("FifthNavItem"),
sixtID: selectElementByClass("SixtNavItem")
};
// intersection observer setup
const observerOptions = {
root: null,
rootMargin: "0px",
threshold: 0.1
};
function observerCallback(entries, observer) {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// get the nav item corresponding to the id of the section
// that is currently in view
const navItem = navItems[entry.target.id];
//get the "alt" tag of section in view
// alt tag equals slide index of swiper
const navItemAlt = navItem.getAttribute("alt");
// tell swiper to slide to the slide with index of "alt"
swiper.slideTo(navItemAlt, 300, true)
// add 'active' class on the navItem
navItem.classList.add("swiper-slide-active2");
// remove 'active' class from any navItem that is not
// same as 'navItem' defined above
Object.values(navItems).forEach((item) => {
if (item != navItem) {
item.classList.remove("swiper-slide-active2");
}
});
}
});
}
const observer = new IntersectionObserver(observerCallback, observerOptions);
sections.forEach((sec) => observer.observe(sec));
html {
scroll-behavior: smooth;
}
.swiper-container {
width: 100%;
}
.swiper-slide {
padding: 10px;
width: 33vw!important;
}
.swiper-slide-active2 {
background-color: #95D5B2;
border-radius: 25px;
}
.swiper-container ul {
list-style-type: none;
margin: 0;
padding: 0;
}
.swiper-container a {
color: black;
text-align: center;
text-decoration: none;
display: inline-block;
width: 100%;
height: 100%;
}
.sticky {
position: sticky;
top: 0px;
}
section {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.1/css/swiper.min.css" rel="stylesheet"/>
<!--Sticky wrapper-->
<div class="sticky">
<!--swiper container-->
<div class="swiper-container" id="scroll-tags">
<ul class="swiper-wrapper">
<a alt="0" class="swiper-slide FirstNavItem" href="#firstID">First</a>
<a alt="1" class="swiper-slide SecondNavItem" href="#secondID">Second</a>
<a alt="2" class="swiper-slide ThirdNavItem" href="#thirdID">Third</a>
<a alt="3" class="swiper-slide FourthNavItem"href="#fourthID">Fourth</a>
<a alt="4" class="swiper-slide FifthNavItem"href="#fifthID">Fifth</a>
<a alt="5" class="swiper-slide SixtNavItem"href="#sixtID">Sixt</a>
</ul>
</div>
</div>
<!--wrapping div to extend page below last section-->
<div style="height: 500vh">
<!--Page sections-->
<section class="firstClass" id="firstID">
<h1>
First
</h1>
</section>
<section class="secondClass" id="secondID">
<h1>
Second
</h1>
</section>
<section class="thirdClass" id="thirdID">
<h1>
Third
</h1>
</section>
<section class="fourthClass" id="fourthID">
<h1>
Fourth
</h1>
</section>
<section class="fifthClass" id="fifthID">
<h1>
Fifth
</h1>
</section>
<section class="sixtClass" id="sixtID">
<h1>
Sixt
</h1>
</section>
<section></section>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.5.1/js/swiper.min.js"></script>