Tabs

Circle Animated Tabs

17 Oct 2022

Circle Animated Tabs
HTML
SCSS
PostCSS
JS
                            <section class="specialisms-list" data-default-transform="0deg">
  <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>
</section>
                        
                            .specialisms-list {
  padding-top: 200px;
  padding-bottom: 100px;
  width: 100%;

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

.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 0.3s ease;
    display: flex;
    justify-content: center;
    align-items: center;

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

  @include media(550) {
    width: 440px;
    height: 440px;
    margin-left: -160px;

    .logo {
      width: 180px;
    }
  }

  @include media(371) {
    width: 380px;
    height: 380px;

    .logo {
      margin-right: -100px;
    }
  }
}

.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 {
  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;
    }
  }
}

.specialisms_text {
  position: absolute;
  text-align: center;
  max-width: 80%;

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

  @include media(550) {
    width: 200px;
    margin-right: -50px;
    margin-top: 40px;
  }

  @include media(371) {
    margin-right: -100px;
    margin-top: 40px;
    width: 170px;
  }
}
                        
                            .specialisms-list {
  padding-top: 200px;
  padding-bottom: 100px;
  width: 100%;

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

.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 0.3s ease;
    display: flex;
    justify-content: center;
    align-items: center;

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

  @mixin media 550 {
    width: 440px;
    height: 440px;
    margin-left: -160px;

    .logo {
      width: 180px;
    }
  }

  @mixin media 371 {
    width: 380px;
    height: 380px;

    .logo {
      margin-right: -100px;
    }
  }
}

.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 {
  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;
    }
  }
}

.specialisms_text {
  position: absolute;
  text-align: center;
  max-width: 80%;
  p {
    font-size: ac(22px, 14px);
  }

  @mixin media 550 {
    width: 200px;
    margin-right: -50px;
    margin-top: 40px;
  }

  @mixin media 371 {
    margin-right: -100px;
    margin-top: 40px;
    width: 170px;
  }
}
                        
                            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)
  );
}

// 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, задати дефолтний поворот всього коло, якщо в дизайні воно трохи повернуто.

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

0