Tabs

Circle Animated Tabs with slider

17 Oct 2022

Circle Animated Tabs with slider
HTML
SCSS
PostCSS
JS
                            <section class="specialisms-list" data-default-transform="-15deg">
  <div class="container">
    <div class="specialisms-items">
      <div class="logo">
        <img src="./images/Logo.svg" alt="" />
      </div>

      <div class="specialisms_text"></div>

      <div class="specialisms-wrap">
        <div class="specialism_item">
          <p>Manufacturing and Production</p>
          <div class="icon">
            <img src="./images/benefit-1.svg" alt="" />
          </div>
        </div>
      </div>
      <div class="specialisms-wrap">
        <div class="specialism_item">
          <p>Materials Management</p>
          <div class="icon">
            <img src="./images/benefit-2.svg" alt="" />
          </div>
        </div>
      </div>
      <div class="specialisms-wrap">
        <div class="specialism_item">
          <p>Admin and office management</p>
          <div class="icon">
            <img src="./images/benefit-3.svg" alt="" />
          </div>
        </div>
      </div>
      <div class="specialisms-wrap">
        <div class="specialism_item">
          <p>Supply Chain, Inventory and Planning</p>
          <div class="icon">
            <img src="./images/benefit-4.svg" alt="" />
          </div>
        </div>
      </div>
      <div class="specialisms-wrap">
        <div class="specialism_item">
          <p>Commercial & Business Development</p>
          <div class="icon">
            <img src="./images/benefit-5.svg" alt="" />
          </div>
        </div>
      </div>
      <div class="specialisms-wrap">
        <div class="specialism_item">
          <p>Purchasing & Procurement</p>
          <div class="icon">
            <img src="./images/benefit-6.svg" alt="" />
          </div>
        </div>
      </div>
      <div class="specialisms-wrap">
        <div class="specialism_item">
          <p>Consultancy</p>
          <div class="icon">
            <img src="./images/benefit-7.svg" alt="" />
          </div>
        </div>
      </div>
      <div class="specialisms-wrap">
        <div class="specialism_item">
          <p>Freight & Shipping/import and export management</p>
          <div class="icon">
            <img src="./images/benefit-8.svg" alt="" />
          </div>
        </div>
      </div>
      <div class="specialisms-wrap">
        <div class="specialism_item">
          <p>Project Management /Business Transformation</p>
          <div class="icon">
            <img src="./images/benefit-9.svg" alt="" />
          </div>
        </div>
      </div>
      <div class="specialisms-wrap">
        <div class="specialism_item">
          <p>Warehousing and Distribution</p>
          <div class="icon">
            <img src="./images/benefit-10.svg" alt="" />
          </div>
        </div>
      </div>
    </div>
    <div class="swiper specialisms-slider">
      <div class="swiper-wrapper">
        <div class="swiper-slide specialism_item">
          <div class="slide-inner">
            <div class="icon">
              <img src="./images/benefit-1.svg" alt="" />
            </div>
            <p>Manufacturing and Production</p>
          </div>
        </div>
        <div class="swiper-slide specialism_item">
          <div class="slide-inner">
            <div class="icon">
              <img src="./images/benefit-2.svg" alt="" />
            </div>
            <p>Materials Management</p>
          </div>
        </div>
        <div class="swiper-slide specialism_item">
          <div class="slide-inner">
            <div class="icon">
              <img src="./images/benefit-3.svg" alt="" />
            </div>
            <p>Admin and office management</p>
          </div>
        </div>
        <div class="swiper-slide specialism_item">
          <div class="slide-inner">
            <div class="icon">
              <img src="./images/benefit-4.svg" alt="" />
            </div>
            <p>Supply Chain, Inventory and Planning</p>
          </div>
        </div>
        <div class="swiper-slide specialism_item">
          <div class="slide-inner">
            <div class="icon">
              <img src="./images/benefit-5.svg" alt="" />
            </div>
            <p>Commercial & Business Development</p>
          </div>
        </div>
        <div class="swiper-slide specialism_item">
          <div class="slide-inner">
            <div class="icon">
              <img src="./images/benefit-6.svg" alt="" />
            </div>
            <p>Purchasing & Procurement</p>
          </div>
        </div>
        <div class="swiper-slide specialism_item">
          <div class="slide-inner">
            <div class="icon">
              <img src="./images/benefit-7.svg" alt="" />
            </div>
            <p>Consultancy</p>
          </div>
        </div>
        <div class="swiper-slide specialism_item">
          <div class="slide-inner">
            <div class="icon">
              <img src="./images/benefit-8.svg" alt="" />
            </div>
            <p>Freight & Shipping/import and export management</p>
          </div>
        </div>
        <div class="swiper-slide specialism_item">
          <div class="slide-inner">
            <div class="icon">
              <img src="./images/benefit-9.svg" alt="" />
            </div>
            <p>Engineering, quality and facilities management</p>
          </div>
        </div>
        <div class="swiper-slide specialism_item">
          <div class="slide-inner">
            <div class="icon">
              <img src="./images/benefit-10.svg" alt="" />
            </div>
            <p>Logistics & Transport</p>
          </div>
        </div>
      </div>
      <div class="container">
        <div class="slider-btns-list">
          <div class="slider-btn gradient prev">Prev</div>
          <div class="slider-btn gradient next">Next</div>
        </div>
      </div>
    </div>
  </div>
</section>
                        
                            .specialisms-list {
  padding-top: 100px;
  padding-bottom: 10px;
  width: 100%;

  .container {
    width: 89%;
    margin: 0 auto;
  }
}

.swiper.specialisms-slider {
  display: none;
  overflow: visible;

  .slider-btns-list {
    display: flex;
    justify-content: center;
    padding-top: 30px;
    padding-bottom: 10px;

    .slider-btn.prev {
      margin-right: 15px;
    }
  }

  .slider-btn {
    position: relative;
    font-size: 16px;
    font-family: var(--font-main);
    line-height: 1.4;
    font-weight: 500;
    text-transform: uppercase;
    cursor: pointer;
    transition: opacity .3s ease;
    opacity: 1;

    &:before {
      content: "";
      position: absolute;
      bottom: 0;
      right: 0;
      width: 0;
      background: #fff;
      height: 2px;
      transition: all .3s ease;
    }

    &:hover {
      transition: opacity .3s ease;
      opacity: .8;

      &:before {
        right: auto;
        left: 0;
        width: 100%;
      }
    }
  }

  .specialism_item {
    height: auto;

    .slide-inner {
      margin: 0 auto;
      width: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: flex-start;

      .icon {
        margin-right: 0;
        margin-bottom: 10px;
      }

      p {
        text-align: center;
      }
    }
  }

  @include media(1025) {
    display: block;
  }
}

.specialisms-items {
  position: relative;
  flex-shrink: 0;
  width: min(80vh, 80vw);
  height: min(80vh, 80vw);
  max-width: 848px;
  max-height: 848px;
  margin: 0 auto;
  border-radius: 50%;

  display: flex;
  align-items: center;
  justify-content: center;

  .logo {
    position: absolute;
    width: 300px;
    top: 50%;
    transform: translateY(-50%);
    transition: all .3s ease;
    display: flex;
    justify-content: center;
    align-items: center;

    &.active {
      top: 35%;
      transform: translateY(-50%) scale(0.8);
    }
  }

  @include media(1025) {
    display: none;
  }
}

.specialisms-wrap {

  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  transform-origin: center;
  transform: rotate(0deg);
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;

  transition: ease-in-out 0.5s;
}

.specialism_item {
  @include min-media(1025) {
    border-radius: 50%;
    width: min(15vh, 15vw);
    height: min(15vh, 15vw);
    max-width: 221px;
    max-height: 221px;
    position: absolute;
    top: 0;
    transform: translateY(-50%);
    transform-origin: top;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
  }

  transition: ease-in-out 0.5s;
  opacity: 0.5;

  &.active {
    opacity: 1;
  }

  p {
    display: none;
  }

  .icon {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;

    img {
      width: min(100%, 72px);
      height: min(100%, 72px);
      object-fit: contain;
    }
  }

  @include media(1025) {
    opacity: 1;

    p {
      display: block;
    }

    .icon {
      width: 72px;
      height: 72px;
      flex-shrink: 0;
      margin-right: 30px;
    }
  }
}

.specialisms_text {
  position: absolute;
  text-align: center;

  p {
    font-size: ac(22px, 16px);
  }
}

                        
                            .specialisms-list {
  padding-top: 100px;
  padding-bottom: 10px;
  width: 100%;

  .container {
    width: 89%;
    margin: 0 auto;
  }
}

.swiper.specialisms-slider {
  display: none;
  overflow: visible;
  .slider-btns-list {
    display: flex;
    justify-content: center;
    padding-top: 30px;
    padding-bottom: 10px;
    .slider-btn.prev {
      margin-right: 15px;
    }
  }

  .slider-btn {
    position: relative;
    font-size: 16px;
    font-family: var(--font-main);
    line-height: 1.4;
    font-weight: 500;
    text-transform: uppercase;
    cursor: pointer;
    transition: opacity .3s ease;
    opacity: 1;

    &:before {
      content: "";
      position: absolute;
      bottom: 0;
      right: 0;
      width: 0;
      background: #fff;
      height: 2px;
      transition: all .3s ease;
    }

    &:hover {
      transition: opacity .3s ease;
      opacity: .8;
      &:before {
        right: auto;
        left: 0;
        width: 100%;
      }
    }
  }

  .specialism_item {
    height: auto;
    .slide-inner {
      margin: 0 auto;
      width: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: flex-start;

      .icon {
        margin-right: 0;
        margin-bottom: 10px;
      }

      p {
        text-align: center;
      }
    }
  }


  @mixin media 1025 {
    display: block;
  }
}

.specialisms-items {
  position: relative;
  flex-shrink: 0;
  width: min(80vh, 80vw);
  height: min(80vh, 80vw);
  max-width: 848px;
  max-height: 848px;
  margin: 0 auto;
  border-radius: 50%;

  display: flex;
  align-items: center;
  justify-content: center;

  .logo {
    position: absolute;
    width: 300px;
    top: 50%;
    transform: translateY(-50%);
    transition: all .3s ease;
    display: flex;
    justify-content: center;
    align-items: center;

    &.active {
      top: 35%;
      transform: translateY(-50%) scale(0.8);
    }
  }

  @mixin media 1025 {
    display: none;
  }
}

.specialisms-wrap {

  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  transform-origin: center;
  transform: rotate(0deg);
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;

  transition: ease-in-out 0.5s;
}

.specialism_item {

  @mixin min-media 1025 {
    border-radius: 50%;
    width: min(15vh, 15vw);
    height: min(15vh, 15vw);
    max-width: 221px;
    max-height: 221px;
    position: absolute;
    top: 0;
    transform: translateY(-50%);
    transform-origin: top;
    display: flex;
    justify-content: center;
    align-items: center;
    text-align: center;
  }

  transition: ease-in-out 0.5s;

  opacity: 0.5;

  &.active {
    opacity: 1;
  }

  p {
    display: none;
  }

  .icon {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;

    img {
      width: min(100%, 72px);
      height: min(100%, 72px);
      object-fit: contain;
    }
  }

  @mixin media 1025 {
    opacity: 1;

    p {
      display: block;
    }

    .icon {
      width: 72px;
      height: 72px;
      flex-shrink: 0;
      margin-right: 30px;
    }
  }
}

.specialisms_text {
  position: absolute;
  text-align: center;
  p {
    font-size: ac(22px, 16px);
  }
}
                        
                            function isInViewport(el) {
  const rect = el.getBoundingClientRect();
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <=
      (window.innerHeight || document.documentElement.clientHeight) &&
    rect.right <= (window.innerWidth || document.documentElement.clientWidth)
  );
}

// Specialisms Swiper

const specialismsSlider = document.getElementsByClassName(`specialisms-slider`);
if (document.getElementsByClassName(`specialisms-slider`)[0]) {
  // const specialismsArr = Array.from(specialismsSlider.querySelectorAll('.swiper-slide'));

  MetaSwiper(".specialisms-slider", {
    spaceBetween: 50,
    observer: true,
    speed: 600,
    autoplay: {
      delay: 5000,
      disableOnInteraction: false,
      pauseOnMouseEnter: true,
    },
    // Navigation
    navigation: {
      nextEl: ".slider-btn.next",
      prevEl: ".slider-btn.prev",
    },
    // Breakpoints
    breakpoints: {
      // when window width is >= 320px
      320: {
        // centeredSlides: false,
        slidesPerView: 2,
        spaceBetween: 20,
      },
      // when window width is >= 650px
      650: {
        centeredSlides: false,
        slidesPerView: 3,
        spaceBetween: 25,
      },
      769: {
        centeredSlides: false,
        slidesPerView: 4,
        loopedSlides: 2,
        spaceBetween: 30,
      },
      1441: {
        centeredSlides: false,
        slidesPerView: 5,
        spaceBetween: 40,
      },
    },
  });
}

// TEST CIRCLE
const specialismCircleBlock =
  document.getElementsByClassName(`specialisms-list`)[0];
if (specialismCircleBlock) {
  const container = specialismCircleBlock.querySelector(".container");
  const wrapArr = Array.from(
    specialismCircleBlock.querySelectorAll(`.specialisms-wrap`)
  );
  const itemArr = Array.from(
    specialismCircleBlock
      .querySelector(".specialisms-items")
      .querySelectorAll(`.specialism_item`)
  );
  const logo = specialismCircleBlock.querySelector(".logo");

  function rotateAnimation() {
    itemArr.forEach((elem) => elem.classList.remove("active"));
    logo.classList.add("active");

    let activeIndex = 1;
    itemArr[0].classList.add("active");
    textWrap.innerHTML = `<p>${wrapArr[0].querySelector("p").innerHTML}</p>`;

    setInterval(function () {
      let trueIndex = itemArr.length - (activeIndex % wrapArr.length);

      let previousActiveItem = itemArr[(trueIndex + 1) % itemArr.length];
      let activeItem = itemArr[trueIndex % itemArr.length];

      let activeWrap = wrapArr[trueIndex % wrapArr.length];

      textWrap.innerHTML = `<p>${activeWrap.querySelector("p").innerHTML}</p>`;

      previousActiveItem.classList.remove("active");
      activeItem.classList.add("active");

      wrapArr.forEach((elem, index) => {
        elem.style.transform = `rotate(${
          (activeIndex + index) * step + defaultTransform
        }deg)`;
        elem.children[0].style.transform = `rotate(${
          -1 * ((activeIndex + index) * step + defaultTransform)
        }deg) translateY(-50%)`;
      });

      activeIndex += 1;
    }, 3200);
  }

  itemArr.forEach((elem) => elem.classList.add("active"));

  const textWrap = specialismCircleBlock.querySelector(".specialisms_text");

  const step = 360 / wrapArr.length;
  let newStep = step * 2;

  const defaultTransform = +specialismCircleBlock
    .getAttribute("data-default-transform")
    .replace("deg", "");

  wrapArr.forEach((elem, index) => {
    elem.style.transform = `rotate(${index * step + defaultTransform}deg)`;
    elem.children[0].style.transform = `rotate(${
      -1 * (index * step + defaultTransform)
    }deg) translateY(-50%)`;
  });

  let scrollFlag = isInViewport(container);

  if (scrollFlag) rotateAnimation();

  document.addEventListener("scroll", function () {
    if (scrollFlag) return;

    scrollFlag = isInViewport(container);
    if (scrollFlag) rotateAnimation();
  });
}
                        

Коло, яке автоматично, кожні 3 секунди, обертається і міняється контент в середині. Айтеми автоматично розташовуються по всьому колу рівномірно.

Підходить добре для секцій з бенефітсами чи спеціалізацією.

Є можливість, завдяки дата-атрибуту data-default-transform, задати дефолтний поворот всього коло, якщо в дизайні воно трохи повернуто.

В цьому варіанті на розишерннях менше ніж 1025px секція стає слайдером.

1