Sections
Tabs with horizontal Swiper
05 Jul 2023
Tabs with animation current tab indicator
HTML
SCSS
PostCSS
JS
<section class="section services">
<div class="cont">
<h2 class="section__title" data-aos="fade-right">Services</h2>
<div class="services__main-title" data-aos="fade-right">
Huntress Services
</div>
<div class="services-list-slider" data-aos="fade-up">
<div class="swiper-wrapper">
<div class="swiper-slide" data-adaptive-cursor="invert">
<div class="text">Volume Recruitment</div>
</div>
<div class="swiper-slide" data-adaptive-cursor="invert">
Payroll Services
</div>
<!-- -->
<div class="swiper-slide" data-adaptive-cursor="invert">
Delivery into Managed Service
</div>
<div class="swiper-slide" data-adaptive-cursor="invert">
Exclusive Partnerships
</div>
<div class="swiper-slide" data-adaptive-cursor="invert">
Urgent Cover
</div>
<div class="swiper-slide" data-adaptive-cursor="invert">
CSS Non-surgical staffing
</div>
</div>
</div>
<div class="services-info-slider" data-aos="fade-up">
<div class="swiper-wrapper">
<div class="swiper-slide">
<div class="services-info-slider__slide">
<div class="services-info-slider__slide-text">
A dedicated recruitment coordinator, experienced in volume
campaigns, will fully manage the process from advertising to
interviews to the first day in the role.
</div>
<div class="services-info-slider__slide-btns">
<button class="btn">More about this service</button>
<button class="btn outline-btn">Contact us</button>
</div>
</div>
</div>
<div class="swiper-slide">
<div class="services-info-slider__slide">
<div class="services-info-slider__slide-text">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Aliquid,
iure.
</div>
<div class="services-info-slider__slide-btns">
<button class="btn">More about this service</button>
<button class="btn outline-btn">Contact us</button>
</div>
</div>
</div>
<div class="swiper-slide">
<div class="services-info-slider__slide">
<div class="services-info-slider__slide-text">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illum,
optio. Suscipit quos iure laboriosam ipsum possimus, nesciunt
officiis harum alias magnam illo temporibus, impedit accusamus.
Doloremque earum enim atque incidunt.
</div>
<div class="services-info-slider__slide-btns">
<button class="btn">More about this service</button>
<button class="btn outline-btn">Contact us</button>
</div>
</div>
</div>
<div class="swiper-slide">
<div class="services-info-slider__slide">
<div class="services-info-slider__slide-text">
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Obcaecati temporibus voluptatibus eveniet quisquam odit
laboriosam!
</div>
<div class="services-info-slider__slide-btns">
<button class="btn">More about this service</button>
<button class="btn outline-btn">Contact us</button>
</div>
</div>
</div>
<div class="swiper-slide">
<div class="services-info-slider__slide">
<div class="services-info-slider__slide-text">
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Architecto.
</div>
<div class="services-info-slider__slide-btns">
<button class="btn">More about this service</button>
<button class="btn outline-btn">Contact us</button>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
.services-list-slider {
--indicator-pos: 0px;
--indicator-w: 50px;
position: relative;
z-index: 1;
margin-bottom: ac(50px, 40px);
background: var(--light-bege);
&.show-indicator {
&::before {
display: block;
}
}
&::before {
display: none;
content: "";
position: absolute;
top: 50%;
right: 0;
z-index: 2;
transform: translateY(-50%);
width: 40px;
height: 40px;
border-radius: 999px;
opacity: 0;
background: var(--white);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
pointer-events: none;
transition: setTransition(transform);
animation: swipe-animation 2000ms infinite;
@keyframes swipe-animation {
0% {
opacity: 0;
transform: translate(0px, -50%);
}
75% {
opacity: 1;
transform: translate(-70px, -50%);
}
100% {
opacity: 0;
transform: translate(-70px, -50%);
}
}
}
.swiper-wrapper {
padding-bottom: 17px;
&::before {
content: "";
position: absolute;
top: 100%;
left: 0;
transform: translateY(-50%);
/* width: 100%; */
width: var(--line-w);
height: 2px;
border-radius: 999px;
background: var(--galaxy-cl);
}
&::after {
content: "";
position: absolute;
top: 100%;
left: var(--indicator-pos);
transform: translateY(-50%);
width: var(--indicator-w);
height: 5px;
border-radius: 999px;
background: var(--primary-cl);
transition: setTransition(width, left);
}
}
.swiper-slide {
width: fit-content;
font-size: 18px;
cursor: pointer;
}
}
.services-list-indicator {
position: absolute;
top: 100%;
transform: translateY(-50%);
width: 50px;
height: 5px;
border-radius: 999px;
background: var(--primary-cl);
}
.services-info-slider__slide {
display: flex;
align-items: start;
justify-content: space-between;
gap: ac(40px, 30px);
@include media(769) {
flex-direction: column;
}
}
.services-info-slider__slide-text {
max-width: 740px;
font-size: ac(22px, 18px);
line-height: 1.45;
}
.services-info-slider__slide-btns {
display: flex;
align-items: center;
justify-content: end;
gap: ac(25px, 20px);
flex-grow: 1;
flex-shrink: 0;
@include media(769) {
flex-wrap: wrap;
justify-content: start;
}
@include media(651) {
flex-direction: column;
align-items: start;
}
}
.services-list-slider {
--indicator-pos: 0px;
--indicator-w: 50px;
position: relative;
z-index: 1;
margin-bottom: ac(50px, 40px);
background: var(--light-bege);
&.show-indicator {
&::before {
display: block;
}
}
&::before {
display: none;
content: "";
position: absolute;
top: 50%;
right: 0;
z-index: 2;
transform: translateY(-50%);
width: 40px;
height: 40px;
border-radius: 999px;
opacity: 0;
background: var(--white);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
pointer-events: none;
transition: setTransition(transform);
animation: swipe-animation 2000ms infinite;
@keyframes swipe-animation {
0% {
opacity: 0;
transform: translate(0px, -50%);
}
75% {
opacity: 1;
transform: translate(-70px, -50%);
}
100% {
opacity: 0;
transform: translate(-70px, -50%);
}
}
}
.swiper-wrapper {
padding-bottom: 17px;
&::before {
content: "";
position: absolute;
top: 100%;
left: 0;
transform: translateY(-50%);
/* width: 100%; */
width: var(--line-w);
height: 2px;
border-radius: 999px;
background: var(--galaxy-cl);
}
&::after {
content: "";
position: absolute;
top: 100%;
left: var(--indicator-pos);
transform: translateY(-50%);
width: var(--indicator-w);
height: 5px;
border-radius: 999px;
background: var(--primary-cl);
transition: setTransition(width, left);
}
}
.swiper-slide {
width: fit-content;
font-size: 18px;
cursor: pointer;
}
}
.services-list-indicator {
position: absolute;
top: 100%;
transform: translateY(-50%);
width: 50px;
height: 5px;
border-radius: 999px;
background: var(--primary-cl);
}
.services-info-slider__slide {
display: flex;
align-items: start;
justify-content: space-between;
gap: ac(40px, 30px);
@mixin media 769 {
flex-direction: column;
}
}
.services-info-slider__slide-text {
max-width: 740px;
font-size: ac(22px, 18px);
line-height: 1.45;
}
.services-info-slider__slide-btns {
display: flex;
align-items: center;
justify-content: end;
gap: ac(25px, 20px);
flex-grow: 1;
flex-shrink: 0;
@mixin media 769 {
flex-wrap: wrap;
justify-content: start;
}
@mixin media 651 {
flex-direction: column;
align-items: start;
}
}
import { valueObserver } from "./meta-settings.js";
const servicesSection = document.querySelector(".services");
if (servicesSection) {
const servicesListSlider = servicesSection.querySelector(
".services-list-slider"
);
const serviceItems = servicesListSlider.querySelectorAll(".swiper-slide");
if (servicesListSlider) {
const servicesListSwiper = new Swiper(servicesListSlider, {
freeMode: true,
slidesPerView: "auto",
spaceBetween: 50,
on: {
afterInit({ wrapperEl, isEnd }) {
if (!isEnd) servicesListSlider.classList.add("show-indicator");
servicesListSlider.style.setProperty(
"--line-w",
wrapperEl.scrollWidth + "px"
);
},
sliderMove() {
servicesListSlider.classList.remove("show-indicator");
},
},
});
}
const serviceInfoSlider = servicesSection.querySelector(
".services-info-slider"
);
let serviceInfoSwiper = null;
if (serviceInfoSlider) {
serviceInfoSwiper = new Swiper(serviceInfoSlider, {
slidesPerView: 1,
effect: "fade",
// autoHeight: true,
fadeEffect: {
crossFade: true,
},
});
}
const handleServiceClick = (idx) => {
const el = serviceItems[idx];
servicesListSlider.style.setProperty(
"--indicator-pos",
el.offsetLeft + "px"
);
servicesListSlider.style.setProperty(
"--indicator-w",
el.clientWidth + "px"
);
serviceInfoSwiper.slideTo(idx);
};
const activeServiceIdx = valueObserver(0, handleServiceClick, true);
serviceItems.forEach((item, idx) =>
item.addEventListener("click", () => (activeServiceIdx.value = idx))
);
}