Hello dear friend!

Sometimes there is a task of detect whether a block is in the viewing area on screen.

So, I want to show you a simple version of the script, which detects whether a block is in the viewport.

To begin with the markup.

Let’s create navigation in the form of a list and sections that will act as tracking blocks.

<nav>
  <ul>
    <li><a href="#section1" class="active">section 1</a></li>
    <li><a href="#section2">section 2</a></li>
    <li><a href="#section3">section 3</a></li>
    <li><a href="#section4">section 4</a></li>
  </ul>
</nav>
<main class="wrapper">
  <section id="section1" class="section">section 1</section>
  <section id="section2" class="section">section 2</section>
  <section id="section3" class="section">section 3</section>
  <section id="section4" class="section">section 4</section>
</main>

Let’s add some styles.

body {
  margin: 0;
  padding: 0;
}

a {
  text-decoration: none;
  color: white;
}

a.active,
a:hover {
  color: deepskyblue;
}

nav {
  position: fixed;
  right: 10px;
  top: 10px;
  padding: 16px;
  background: darkorchid;
}

nav ul {
  margin: 0;
  padding-left: 0;
  list-style-type: none;
}

.wrapper {
  display: flex;
  flex-direction: column;
}

.section {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  color: white;
  font-size: 40px;
  font-weight: bold;
  text-align: center;
  text-transform: uppercase;
}

.section#section1 {
  background: red;
}

.section#section2 {
  background: blue;
}

.section#section3 {
  background: green;
}

.section#section4 {
  background: orange;
}

This is what it looks like at the moment:
Detect an element is in the viewport

Now let’s go to work on the script.

First, we will monitor the “scroll” event and add the “active” class to the navigation elements if the block corresponds to its “href”.

jQuery(window).scroll(function() {
  var sectionsList = $('.section');
  sectionsList.each(function(i, el) {
    var topOffset = $(el).offset().top - 100,
        bottomPosition = topOffset + $(el).height(),
        scrollPosition = $(window).scrollTop(),
        elId = $(el).attr('id');

    if (scrollPosition > topOffset && scrollPosition < bottomPosition) {
      $('nav ul a.active').removeClass('active');
      $('nav ul a[href="#' + elId + '"]').addClass('active');
    }
  })
});

Next, let’s describe the event when you click on the navigation:

$('nav ul').on('click', 'a', function(e) {
  e.preventDefault();
  var linkId = $(this).attr('href'),
  	  elTopPosition = $(linkId).offset().top;
  $('body, html').animate({
    scrollTop: elTopPosition
  }, 800);
});

Now if we try to click on a link in the navigation, the page will scroll to the desired item. And also if we just scroll the page – the “active” class will be added to the navigation items.

Example on jsFiddle

This script is light and simple, which means that it can’t cover all the options related to determining the position of the block in the viewport. So I want to tell about the plugin, with more global and finer settings for different tasks.

One such plugin is – jQuery-viewport-checker.

I’ll drop the links for you to read:

Thank you for your read.

Keep it with you so you don’t lose it!