skip to Main Content

I’m trying to create a vertical timeline with a line that is filling based on your scroll, for example the content timeline by Getwid (https://motopress.com/blog/getwid-wordpress-blocks-timeline-gutenberg-block/). I don’t want to install a plugin just for one element. I’m stuck at how to animate the progress and how to add active classes when the element is in the middle of the screen.. Using jQuery I was able to create a on scroll event and progress bar that is filling based on scrollTop(), but that didn’t worked because when we reach the end of the timeline the progress bar is continuing to fill.. Looked over the Getwid JS file I saw that they are using getBoundingClientRect(), but honestly I have never used this and I’m not sure how to implement it in my case. Tried to create a progress bar using GSAP timeline, but I’m failing to attach the active classes when the timeline item is in the middle of the screen.. Here is a CodePen of what I have -> https://codepen.io/tsvetko-krastev/pen/jOGGpyB

$(document).ready(() => {
  //add a listener for scroll
  $(window).scroll(() => {
    //get article's height
    let docHeight = $('.timeline-block').height();
    //get window height
    // let winHeight = $(window).height();

    //calculate the view port
    let viewport = docHeight;

    //get current scroll position
    let scrollPos = $(window).scrollTop();

    //get current scroll percent
    let scrollPercent = (scrollPos / viewport) * 100;

    //add the percent to the top progress bar
    $('.timeline-block__line--bar').css('height', scrollPercent + "%");
    $('.timeline-block__line--bar').css('max-height', '100%');
  });
});
.timeline-block {
  position: relative;

  &__line {
    position: absolute;
    top: 10%;
    left: 50%;
    width: 3px;
    height: 100%;
    max-height: 80%;
    transform: translateX(-50%);
    background-color: lighten(#000, 95%);

    &--bar {
      width: 100%;
      height: 0%;
    }
  }

  .timeline-item {
    width: 100%;
    margin-bottom: 30px;
    
    &__inner {
      display: flex;
      flex-flow: row nowrap;
      align-items: center;
      width: 100%;
    }
    
    &__card {
      width: 45%;
      position: relative;
      padding: 30px;
      border-radius: 6px;
      background-color: #fff;
      box-shadow: 3px 3px 15px rgb(56, 115, 185, 0.2);
      filter: drop-shadow(0 0 5px rgba(0, 0, 0, 0.1));

      &::after {
        content: '';
        position: absolute;
        top: 50%;
        left: 100%;
        display: block;
        width: 25px;
        height: 25px;
        background-color: inherit;
        transform: translate(-50%, -50%) rotate(-45deg);
      }
    }

    &__dot {
      width: 10%;
      display: flex;
      align-items: center;
      justify-content: center;

      &--content {
        z-index: 1;
        width: 70px;
        height: 70px;
        border: 2px solid lighten(#000, 95%);
        border-radius: 50%;
        background-color: #fff;
      }
    }

    &__meta {
      min-width: 45%;
      display: flex;
      flex-direction: row;
      align-items: center;
      justify-content: flex-start;
      
      p {
        position: absolute;
        left: 50%;
        z-index: 1;
        width: 70px;
        margin: 0;
        color: #1187ff;
        font-weight: bold;
        font-size: 20px;
        text-align: center;
        transform: translateX(-50%);
      }
    }

    // When is auto aligned every 2nd item is on right
    &:nth-of-type(2n) {

      .timeline-item__inner {
        flex-direction: row-reverse;
      }

      .timeline-item__card {

        &::after {
          left: 0;
        }
      }

      .timeline-item__meta {
        justify-content: flex-end;
      }
    }
    
    &:last-of-type {
      margin-bottom: 0;
    }

    // When is left aligned
    &.align-item-left {

      .timeline-item__inner {
        flex-direction: row;
      }

      .timeline-item__card {

        &::after {
          left: 100%;
        }
      }

      .timeline-item__meta {
        justify-content: flex-start;
      }
    }

    // When is right aligned
    &.align-item-right {

      .timeline-item__inner {
        flex-direction: row-reverse;
      }

      .timeline-item__card {

        &::after {
          left: 0;
        }
      }

      .timeline-item__meta {
        justify-content: flex-end;
      }
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="timeline-block" data-v-space="80px">
  <div class="timeline-block__line-container">
    <div class="timeline-block__line">
      <div class="timeline-block__line--bar" style="background-color: lime;">
      </div>
    </div>
  </div>

  <div class="timeline-block__inner">
    <div class="wp-block-hlwp-timeline-item timeline-item align-item-auto" style="margin-bottom: 80px;">
      <div class="timeline-item__inner">
        <div class="timeline-item__card">
          <div class="wp-block-group timeline-item__card--content">
            <div class="wp-block-group__inner-container">
              <h4>Timeline Item 1</h4>
              <p>Nam at nisl ut erat scelerisque sollicitudin ut et tellus. Vestibulum ante ipsum primis in faucibus
                orci luctus et ultrices posuere cubilia curae; Sed pretium purus augue, non suscipit dolor pellentesque
                ut. Nulla sit amet diam porta, porttitor lacus ac, auctor ex. In purus orci, lacinia sit amet gravida
                laoreet, placerat ac leo. Curabitur diam justo, consequat eu dui in, egestas volutpat risus. Integer vel
                sapien eget quam tempus tempus. Phasellus elementum in quam eget lobortis. Nam tincidunt, leo ut egestas
                sagittis, nisi nibh sagittis eros, eget tincidunt risus purus ut libero. Donec a ante felis. Cras mattis
                eget arcu ac congue. Curabitur interdum dolor dolor, vel euismod lorem interdum blandit. Etiam placerat
                iaculis augue, nec porttitor lacus rhoncus id.</p>
            </div>
          </div>
        </div>

        <div class="timeline-item__dot">
          <div class="timeline-item__dot--content"></div>
        </div>

        <div class="timeline-item__meta">
          <p>2021</p>
        </div>
      </div>
    </div>

    <div class="wp-block-hlwp-timeline-item timeline-item align-item-right" style="margin-bottom: 80px;">
      <div class="timeline-item__inner">
        <div class="timeline-item__card">
          <div class="wp-block-group timeline-item__card--content">
            <div class="wp-block-group__inner-container">
              <h4>Timeline Item 2</h4>
              <p>Nam at nisl ut erat scelerisque sollicitudin ut et tellus. Vestibulum ante ipsum primis in faucibus
                orci luctus et ultrices posuere cubilia curae; Sed pretium purus augue, non suscipit dolor pellentesque
                ut. Nulla sit amet diam porta, porttitor lacus ac, auctor ex. In purus orci, lacinia sit amet gravida
                laoreet, placerat ac leo. Curabitur diam justo, consequat eu dui in, egestas volutpat risus. Integer vel
                sapien eget quam tempus tempus. Phasellus elementum in quam eget lobortis. Nam tincidunt, leo ut egestas
                sagittis, nisi nibh sagittis eros, eget tincidunt risus purus ut libero. Donec a ante felis. Cras mattis
                eget arcu ac congue. Curabitur interdum dolor dolor, vel euismod lorem interdum blandit. Etiam placerat
                iaculis augue, nec porttitor lacus rhoncus id.</p>
            </div>
          </div>
        </div>

        <div class="timeline-item__dot">
          <div class="timeline-item__dot--content"></div>
        </div>

        <div class="timeline-item__meta">
          <p>2022</p>
        </div>
      </div>
    </div>



    <div class="wp-block-hlwp-timeline-item timeline-item align-item-left" style="margin-bottom: 80px;">
      <div class="timeline-item__inner">
        <div class="timeline-item__card">
          <div class="wp-block-group timeline-item__card--content">
            <div class="wp-block-group__inner-container">
              <h4>Timeline Item 3</h4>
              <p>
                Nam at nisl ut erat scelerisque sollicitudin ut et tellus. Vestibulum ante ipsum primis in faucibus
                orci luctus et ultrices posuere cubilia curae; Sed pretium purus augue, non suscipit dolor pellentesque
                ut. Nulla sit amet diam porta, porttitor lacus ac, auctor ex. In purus orci, lacinia sit amet gravida
                laoreet, placerat ac leo. Curabitur diam justo, consequat eu dui in, egestas volutpat risus. Integer vel
                sapien eget quam tempus tempus. Phasellus elementum in quam eget lobortis. Nam tincidunt, leo ut egestas
                sagittis, nisi nibh sagittis eros, eget tincidunt risus purus ut libero. Donec a ante felis. Cras mattis
                eget arcu ac congue. Curabitur interdum dolor dolor, vel euismod lorem interdum blandit. Etiam placerat
                iaculis augue, nec porttitor lacus rhoncus id.
              </p>
            </div>
          </div>
        </div>

        <div class="timeline-item__dot">
          <div class="timeline-item__dot--content"></div>
        </div>

        <div class="timeline-item__meta">
          <p>2222</p>
        </div>
      </div>
    </div>

    <div class="wp-block-hlwp-timeline-item timeline-item align-item-left" style="margin-bottom: 80px;">
      <div class="timeline-item__inner">
        <div class="timeline-item__card">
          <div class="wp-block-group timeline-item__card--content">
            <div class="wp-block-group__inner-container">
              <h4>Timeline Item 4</h4>
              <p>
                Nam at nisl ut erat scelerisque sollicitudin ut et tellus. Vestibulum ante ipsum primis in faucibus
                orci luctus et ultrices posuere cubilia curae; Sed pretium purus augue, non suscipit dolor pellentesque
                ut. Nulla sit amet diam porta, porttitor lacus ac, auctor ex. In purus orci, lacinia sit amet gravida
                laoreet, placerat ac leo. Curabitur diam justo, consequat eu dui in, egestas volutpat risus. Integer vel
                sapien eget quam tempus tempus. Phasellus elementum in quam eget lobortis. Nam tincidunt, leo ut egestas
                sagittis, nisi nibh sagittis eros, eget tincidunt risus purus ut libero. Donec a ante felis. Cras mattis
                eget arcu ac congue. Curabitur interdum dolor dolor, vel euismod lorem interdum blandit. Etiam placerat
                iaculis augue, nec porttitor lacus rhoncus id.
              </p>
            </div>
          </div>
        </div>

        <div class="timeline-item__dot">
          <div class="timeline-item__dot--content"></div>
        </div>

        <div class="timeline-item__meta">
          <p>2223</p>
        </div>
      </div>
    </div>

    <div class="wp-block-hlwp-timeline-item timeline-item align-item-right" style="margin-bottom: 80px;">
      <div class="timeline-item__inner">
        <div class="timeline-item__card">
          <div class="wp-block-group timeline-item__card--content">
            <div class="wp-block-group__inner-container">
              <h4>Timeline Item 5</h4>
              <p>
                Nam at nisl ut erat scelerisque sollicitudin ut et tellus. Vestibulum ante ipsum primis in faucibus
                orci luctus et ultrices posuere cubilia curae; Sed pretium purus augue, non suscipit dolor pellentesque
                ut. Nulla sit amet diam porta, porttitor lacus ac, auctor ex. In purus orci, lacinia sit amet gravida
                laoreet, placerat ac leo. Curabitur diam justo, consequat eu dui in, egestas volutpat risus. Integer vel
                sapien eget quam tempus tempus. Phasellus elementum in quam eget lobortis. Nam tincidunt, leo ut egestas
                sagittis, nisi nibh sagittis eros, eget tincidunt risus purus ut libero. Donec a ante felis. Cras mattis
                eget arcu ac congue. Curabitur interdum dolor dolor, vel euismod lorem interdum blandit. Etiam placerat
                iaculis augue, nec porttitor lacus rhoncus id.
              </p>
            </div>
          </div>
        </div>

        <div class="timeline-item__dot">
          <div class="timeline-item__dot--content"></div>
        </div>

        <div class="timeline-item__meta">
          <p>2023</p>
        </div>
      </div>
    </div>

    <div class="wp-block-hlwp-timeline-item timeline-item align-item-left" style="margin-bottom: 80px;">
      <div class="timeline-item__inner">
        <div class="timeline-item__card">
          <div class="wp-block-group timeline-item__card--content">
            <div class="wp-block-group__inner-container">
              <h4>Timeline Item 6</h4>
              <p>
                Nam at nisl ut erat scelerisque sollicitudin ut et tellus. Vestibulum ante ipsum primis in faucibus
                orci luctus et ultrices posuere cubilia curae; Sed pretium purus augue, non suscipit dolor pellentesque
                ut. Nulla sit amet diam porta, porttitor lacus ac, auctor ex. In purus orci, lacinia sit amet gravida
                laoreet, placerat ac leo. Curabitur diam justo, consequat eu dui in, egestas volutpat risus. Integer vel
                sapien eget quam tempus tempus. Phasellus elementum in quam eget lobortis. Nam tincidunt, leo ut egestas
                sagittis, nisi nibh sagittis eros, eget tincidunt risus purus ut libero. Donec a ante felis. Cras mattis
                eget arcu ac congue. Curabitur interdum dolor dolor, vel euismod lorem interdum blandit. Etiam placerat
                iaculis augue, nec porttitor lacus rhoncus id.
              </p>
            </div>
          </div>
        </div>

        <div class="timeline-item__dot">
          <div class="timeline-item__dot--content"></div>
        </div>
        
        <div class="timeline-item__meta">
          <p>2024</p>
        </div>
      </div>
    </div>
  </div>
</div>

2

Answers


  1. Chosen as BEST ANSWER

    After a couple of days of trying, I managed to make it work as I need it to. I didn't made that Intersection observer work in my case, so I went back to the white board and actually using getBoundClientRect() I made it work. Thanks anyway :)


  2. use Intersection observer.

    const timeline_cb = target => {
      const io = new IntersectionObserver((entries, observer) => {
        entries.forEach(entry => {
    
        if (entry.isIntersecting) {
          entry.classList.add('show')
    
          observer.disconnect();
        }
        });
      });
    
      io.observe(target)
    };
    
    const targets = document.querySelectorAll('.timeline-item');
    targets.forEach(timeline_cb);

    do rest of your animation with css.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search