最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Check if element is in viewport based on horizontal scroll - Stack Overflow

programmeradmin1浏览0评论

I've got a side scrolling / horizontal layout site I'm building. I use a function to test whether or not an element is in the viewport on "normal" vertical layout sites in order to add classes, animations, etc. once it es into view.

I'm trying to get the same effect for the horizontal layout, but to no avail.

Here is the regular version of the function -

 $.fn.isInViewport = function() {
    if ( $(this).length ) {
        var elementTop = $(this).offset().top;
    }
    var elementBottom = elementTop + $(this).outerHeight();
    var viewportTop = $(window).scrollTop();
    var viewportBottom = viewportTop + $(window).height();
    return elementBottom > viewportTop && elementTop < viewportBottom;
};

And here is the way I tried it for horizontal layouts, which didn't work.

 $.fn.isInViewport = function() {
    if ( $(this).length ) {
        var elementLeft = $(this).offset().left;
    }
    var elementRight = elementLeft + $(this).outerWidth();
    var viewportLeft = $(window).scrollLeft();
    var viewportRight = viewportLeft + $(window).width();
    return elementRight > viewportLeft && elementLeft < viewportRight;
};

You call the function like so

 $(".element").each(function() {
    if ( $(this).isInViewport() ) {
        $(this).addClass("animate-element");
    }
});

I've got a side scrolling / horizontal layout site I'm building. I use a function to test whether or not an element is in the viewport on "normal" vertical layout sites in order to add classes, animations, etc. once it es into view.

I'm trying to get the same effect for the horizontal layout, but to no avail.

Here is the regular version of the function -

 $.fn.isInViewport = function() {
    if ( $(this).length ) {
        var elementTop = $(this).offset().top;
    }
    var elementBottom = elementTop + $(this).outerHeight();
    var viewportTop = $(window).scrollTop();
    var viewportBottom = viewportTop + $(window).height();
    return elementBottom > viewportTop && elementTop < viewportBottom;
};

And here is the way I tried it for horizontal layouts, which didn't work.

 $.fn.isInViewport = function() {
    if ( $(this).length ) {
        var elementLeft = $(this).offset().left;
    }
    var elementRight = elementLeft + $(this).outerWidth();
    var viewportLeft = $(window).scrollLeft();
    var viewportRight = viewportLeft + $(window).width();
    return elementRight > viewportLeft && elementLeft < viewportRight;
};

You call the function like so

 $(".element").each(function() {
    if ( $(this).isInViewport() ) {
        $(this).addClass("animate-element");
    }
});
Share Improve this question asked Jan 8, 2021 at 18:09 yermeyerme 8558 silver badges16 bronze badges 3
  • 6 Check out the Intersection Observer API as long as you don't need IE patibility. – D M Commented Jan 8, 2021 at 18:13
  • 1 The implementation for horizontal check is working fine jsfiddle/taLzu8er/1 . Only issue looks like is the variable elementLeft is defined inside if statement's scope. The declaration should be before the if statement. – the Hutt Commented Jan 17, 2022 at 16:18
  • @onkarruikar that would be correct if let was being used, but since it's var and there's only one function here, the scope is the same whether declared inside or outside the if. (I agree it's still better declared outside though, since then the actual scope matches ones visual perceptions better.) – Robin Zigmond Commented Jan 17, 2022 at 20:19
Add a ment  | 

2 Answers 2

Reset to default 4 +25

Using jquery its pretty easy, All yo have to do is $(element).on('scroll',(--function--)) and then you can use $(this).offset().left to get the pixel on its left and when you get the offset of left, you can just do whatever you want. Check the snippet below for an working example. (if possible run in smaller screen like mobile)

$("#timeline").on('scroll', function() {

    $("#timeline .each").each(function(){
        let left = $(this).offset().left;

        if(left >-50 && left< (window.innerWidth - 100)){
            $(this).addClass('mvisible')
        }
        else{
            if($(this).hasClass('mvisible')){
                $(this).removeClass('mvisible')
            }
        }
    });

});
.timeline{overflow-x:auto;width:100%}

.timeline .warp{display:flex;width:1600px;padding:50px 100px 50px 30px;}
.timeline .each{width:185px;}
.timeline .desc{padding:15px;border-radius:4px;background:#08f;color:#fff;width:100%;transform:translateY(50px);opacity:0;transition:0.4s}
.timeline .mvisible .desc{transform:translateY(0);opacity:1}
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="timeline" id="timeline">
    <div class="warp">
        <div class="each mvisible">
            <div class="desc">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </div>
        </div>
        <div class="each">
            <div class="desc">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </div>
        </div>
        <div class="each">
            <div class="desc">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </div>
        </div>
        <div class="each" >
            <div class="desc">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </div>
        </div>
        <div class="each" >
            <div class="desc">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </div>
        </div>
        <div class="each">
            <div class="desc">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </div>
        </div>
        <div class="each">
            <div class="desc">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </div>
        </div>
        <div class="each">
            <div class="desc">
                Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </div>
        </div>
    </div>
</div>

As mentioned in the ments IntersectionObserver is a good place to start

const inViewObserver = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      // do stuff when in view
      entry.target.classList.add('in-view')
      document.body.dataset.log = 'Element in view - well done 
发布评论

评论列表(0)

  1. 暂无评论