JSFiddle - React, Tailwind, and code Playground
HTML
<body>
<ul class="check_viewport">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</body>
CSS
ul {
margin: auto;
}
ul li {
width: 300px;
height: 50px;
background: #f5f5f5;
float: left;
margin: 5px;
list-style:none;
}
ul li.middleviewport {
background:red;
}
JavaScript
jQuery.fn.extend({
markInViewport: function (options) {
var that = this;
this.defaults = {
percentTop: 30,
percentBottom: 40,
cssClass: 'middleviewport',
event: 'scroll resize',
delay: 10
};
this.options = $.extend(that.defaults, options);
this.win = $(window);
this.delayChecking = null;
this.items = [];
this.checkItems = function (items) {
clearTimeout(that.delayChecking);
that.delayChecking = setTimeout(function () {
var thisWindowHeight = that.win.height();
var thisWindowScrollTop = that.win.scrollTop();
that.items.each(function (j) {
var thisItem = $(this);
var thisItemHeight = thisItem.outerHeight();
var thisItemPositionTop = thisItem.offset().top;
var currentPercentTop = (thisItemPositionTop - thisWindowScrollTop) / thisWindowHeight * 100;
var currentPercentBottom = (thisWindowScrollTop + thisWindowHeight - thisItemPositionTop - thisItemHeight) / thisWindowHeight * 100;
thisItem.toggleClass(that.options.cssClass, currentPercentTop >= that.options.percentTop && currentPercentBottom >= that.options.percentBottom);
});
}, that.options.delay);
};
return this.each(function () {
that.items = that.children();
$(window).on(that.options.event, that.checkItems);
that.checkItems();
});
}
});
$('.check_viewport').markInViewport();