Sections

Progress Scroll Section

19 Sep 2022

Animated progress scroll section with informational blocks
HTML
SCSS
PostCSS
JS
                            <section class="progress-section">
  <div class="cont">
    <h2>Progress Section</h2>

    <div class="progress-chain">

      <div class="progress-line">
        <div class="fill"></div>
      </div>

      <div class="progress-items">
        <div class="progress-item" data-aos="progress-anim">
          <h4 class="progress_title">Inclusive</h4>
          <h6>Lorem ipsum dolor</h6>
          <p class="progress_desc">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
            eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus
            nisl tincidunt eget nullam non nisi.
          </p>
        </div>
        <div class="progress-item" data-aos="progress-anim">
          <h4 class="progress_title">Sustainable</h4>
          <h6>Lorem ipsum dolor</h6>
          <p class="progress_desc">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
            eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus
            nisl tincidunt eget nullam non nisi.
          </p>
        </div>
        <div class="progress-item" data-aos="progress-anim">
          <h4 class="progress_title">Attentive</h4>
          <h6>Lorem ipsum dolor</h6>
          <p class="progress_desc">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
            eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus
            nisl tincidunt eget nullam non nisi.
          </p>
        </div>
        <div class="progress-item" data-aos="progress-anim">
          <h4 class="progress_title">Authentic</h4>
          <h6>Lorem ipsum dolor</h6>
          <p class="progress_desc">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
            eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus
            nisl tincidunt eget nullam non nisi.
          </p>
        </div>
        <div class="progress-item" data-aos="progress-anim">
          <h4 class="progress_title">Considerate</h4>
          <h6>Lorem ipsum dolor</h6>
          <p class="progress_desc">
            Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
            eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus
            nisl tincidunt eget nullam non nisi.
          </p>
        </div>
      </div>

    </div>
  </div>
</section>

                        
                            .progress {
  &-section {
    padding: 80px 0;

    h2 {
      text-align: center;
      margin-bottom: 64px;
    }
  }

  &-chain {
    position: relative;
    max-width: 964px;
    margin: 0 auto;
  }

  &-item {
    max-width: ac(376px, 290px, 768, 1440);

    h4 {
      margin: 0;
    }

    p {
      padding: 0;
    }

    &:not(:last-of-type) {
      margin-bottom: ac(12px, 60px);
    }

    &:nth-child(odd) {
      text-align: right;
      transform: translateX(-100%);
    }

    &:nth-child(even) {
      margin-left: auto;
      transform: translateX(100%);
    }

    @include media(769) {
      max-width: 100%;

      &:nth-child(odd),
      &:nth-child(even) {
        margin-left: ac(75px, 30px, 375, 769);
        text-align: left;
        transform: translateX(50%);
      }
    }
  }

  &-line {
    width: 4px;
    height: 100%;
    position: absolute;
    background: #c2c2c2;
    top: 0;
    left: 50%;
    transform: translateX(-25%);
    overflow: hidden;

    .fill {
      width: 100%;
      height: 10%;
      background: var(--primary);
    }

    @include media(769) {
      left: 0;
      transform: none;
    }
  }
}

/* Container */
.cont {
  margin: 0 auto;
  max-width: 1280px;
  width: perc(1280);

  @include media(901) {
    width: 89%;
  }
}

/* AOS */
[data-aos="progress-anim"] {
  opacity: 0;
  transition: transform 0.3s ease-in-out, opacity 0.5s ease;

  &.aos-animate {
    opacity: 1;
    transform: translateX(0);
  }
}
                        
                            /* Mixin */
@define-mixin media $width {
  @media only screen and (max-width: $(width)px) {
    @mixin-content;
  }
}

.progress {
  &-section {
    padding: 80px 0;

    h2 {
      text-align: center;
      margin-bottom: 64px;
    }
  }

  &-chain {
    position: relative;
    max-width: 964px;
    margin: 0 auto;
  }

  &-item {
    max-width: ac(376px, 290px, 768, 1440);

    h4 {
      margin: 0;
    }

    p {
      padding: 0;
    }

    &:not(:last-of-type) {
      margin-bottom: ac(12px, 60px);
    }

    &:nth-child(odd) {
      text-align: right;
      transform: translateX(-100%);
    }

    &:nth-child(even) {
      margin-left: auto;
      transform: translateX(100%);
    }

    @mixin media 769 {
      max-width: 100%;

      &:nth-child(odd),
      &:nth-child(even) {
        margin-left: ac(75px, 30px, 375, 769);
        text-align: left;
        transform: translateX(50%);
      }
    }
  }

  &-line {
    width: 4px;
    height: 100%;
    position: absolute;
    background: #c2c2c2;
    top: 0;
    left: 50%;
    transform: translateX(-25%);
    overflow: hidden;

    .fill {
      width: 100%;
      height: 10%;
      background: var(--primary);
    }

    @mixin media 769 {
      left: 0;
      transform: none;
    }
  }
}

/* Container */
.cont {
  margin: 0 auto;
  max-width: 1280px;
  width: perc(1280);

  @mixin media 901 {
    width: 89%;
  }
}

/* AOS */
[data-aos="progress-anim"] {
  opacity: 0;
  transition: transform 0.3s ease-in-out, opacity 0.5s ease;

  &.aos-animate {
    opacity: 1;
    transform: translateX(0);
  }
}
                        
                            const progressSection = document.querySelector(".progress-section");
if (progressSection) {
  const scrollFillElement = progressSection.querySelector(".progress-line .fill");

  // Scroll progress function
  function scrollProgress(section, fillElement, startIndex = 0.25) {
    let sectionTopPosition = section.offsetTop - window.innerHeight + window.innerHeight * startIndex;
    const windowScroll = document.body.scrollTop || document.documentElement.scrollTop;
    const sectionHeight = section.scrollHeight;
    const scrolled = ((windowScroll - sectionTopPosition) / sectionHeight) * 100;

    let windowWidth = window.innerWidth;
    window.addEventListener("resize", function (e) {
      if (windowWidth === window.innerWidth) return;
      windowWidth = window.innerWidth;
      sectionTopPosition =
        section.offsetTop -
        window.innerHeight +
        window.innerHeight * startIndex;
    });

    scrollFillElement.style.height = scrolled + "%";

    window.onscroll = function () {
      scrollProgress(section, fillElement);
    };
  }

  scrollProgress(progressSection, scrollFillElement);
}

// AOS init

AOS.init({
   startEvent: "load",
   disableMutationObserver: false,
});
AOS.refresh(true);

// Functions for pcss
const maxWidth = 1440;
const minWidth = 768;

export function ac( startSize, endSize, minBreakpoint = minWidth, maxBreakpoint = maxWidth) {

const startSizeFormatted = startSize.replace("px", "");
const endSizeFormatted = endSize.replace("px", "");

const difference = startSizeFormatted - endSizeFormatted;

if (difference > 0) {
    return `min(max(calc(${endSize} + ${difference} * ((100vw - ${minBreakpoint}px) / ${maxBreakpoint - minBreakpoint})),${endSize}),${startSize})`; 
} else {
    return `min(max(calc(${endSize} + ${difference} * ((100vw - ${minBreakpoint}px) / ${maxBreakpoint - minBreakpoint})),${startSize}),${endSize})`;
  }
}

export const perc = (number1, number2 = maxWidth) =>`${(number1 * 100) / number2}%`;

                        

This progress section was made with Vanilla JS.

There is a function that takes 3 parameters:

section - DOM-element that defines the section where the content is located;

fillElement - DOM-element that fills up with scroll;

startIndex - visibility percentage

For animation we use popular AOS library

aos.min.zip

0