Scroll if element is not visible

前端 未结 9 707
旧时难觅i
旧时难觅i 2020-12-14 17:57

how to determine, using jquery, if the element is visible on the current page view. I\'d like to add a comment functionality, which works like in facebook, where you only sc

相关标签:
9条回答
  • 2020-12-14 18:05

    The following code helped me achieve the result

    function scroll_to_element_if_not_inside_view(element){
      if($(window).scrollTop() > element.offset().top){
        $('html, body').animate( { scrollTop: element.offset().top }, {duration: 400 } );
      }
    }
    
    0 讨论(0)
  • 2020-12-14 18:07

    There is a jQuery plugin which allows us to quickly check if a whole element (or also only part of it) is within the browsers visual viewport regardless of the window scroll position. You need to download it from its GitHub repository:

    Suppose to have the following HTML and you want to alert when footer is visible:

    <section id="container">
        <aside id="sidebar">
            <p>
                Scroll up and down to alert the footer visibility by color:
            </p>
            <ul>
                <li><span class="blue">Blue</span> = footer <u>not visible</u>;</li>
                <li><span class="yellow">Yellow</span> = footer <u>visible</u>;</li>
            </ul>
            <span id="alert"></span>
        </aside>
        <section id="main_content"></section>
    </section>
    <footer id="page_footer"></footer>
    

    So, add the plugin before the close of body tag:

    <script type="text/javascript" src="js/jquery-1.12.0.min.js"></script>
    <script type="text/javascript" src="js/jquery_visible/examples/js/jq.visible.js"></script>
    

    After that you can use it in a simple way like this:

    <script type="text/javascript">
    jQuery( document ).ready(function ( $ ) {
      if ($("footer#page_footer").visible(true, false, "both")) {
        $("#main_content").css({"background-color":"#ffeb3b"});
        $("span#alert").html("Footer visible");
      } else {
        $("#main_content").css({"background-color":"#4aafba"});
        $("span#alert").html("Footer not visible");
      }
    
      $(window).scroll(function() {
        if ($("footer#page_footer").visible(true, false, "both")) {
          $("#main_content").css({"background-color":"#ffeb3b"});
          $("span#alert").html("Footer visible");
        } else {
          $("#main_content").css({"background-color":"#4aafba"});
          $("span#alert").html("Footer not visible");
        }
      });
    });
    </script>
    

    Here a demo

    0 讨论(0)
  • 2020-12-14 18:10

    After trying all these solutions and many more besides, none of them satisfied my requirement for running old web portal software (10 years old) inside IE11 (in some compatibility mode). They all failed to correctly determine if the element was visible. However I found this solution. I hope it helps.

    function scrollIntoViewIfOutOfView(el) {
        var topOfPage = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
        var heightOfPage = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
        var elY = 0;
        var elH = 0;
        if (document.layers) { // NS4
            elY = el.y;
            elH = el.height;
        }
        else {
            for(var p=el; p&&p.tagName!='BODY'; p=p.offsetParent){
                elY += p.offsetTop;
            }
            elH = el.offsetHeight;
        }
        if ((topOfPage + heightOfPage) < (elY + elH)) {
            el.scrollIntoView(false);
        }
        else if (elY < topOfPage) {
            el.scrollIntoView(true);
        }
    }
    
    0 讨论(0)
  • 2020-12-14 18:10

    You can take a look at his awesome link from the jQuery Cookbook:

    Determining Whether an Element Is Within the Viewport

    Test if Element is contained in the Viewport

    jQuery(document).ready(function() {
        var viewportWidth = jQuery(window).width(),
            viewportHeight = jQuery(window).height(),
            documentScrollTop = jQuery(document).scrollTop(),
            documentScrollLeft = jQuery(document).scrollLeft(),
    
            $myElement = jQuery('#myElement'),
    
            elementOffset = $myElement.offset(),
            elementHeight = $myElement.height(),
            elementWidth = $myElement.width(),
    
            minTop = documentScrollTop,
            maxTop = documentScrollTop + viewportHeight,
            minLeft = documentScrollLeft,
            maxLeft = documentScrollLeft + viewportWidth;
    
        if (
            (elementOffset.top > minTop && elementOffset.top + elementHeight < maxTop) &&
            (elementOffset.left > minLeft && elementOffset.left + elementWidth < maxLeft)
        ) {
            alert('entire element is visible');
        } else {
            alert('entire element is not visible');
        }
    });
    

    Test how much of the element is visible

    jQuery(document).ready(function() {
    
    var viewportWidth = jQuery(window).width(),
        viewportHeight = jQuery(window).height(),
    
        documentScrollTop = jQuery(document).scrollTop(),
        documentScrollLeft = jQuery(document).scrollLeft(),
    
        $myElement = jQuery('#myElement'),
    
        verticalVisible, horizontalVisible,
    
        elementOffset = $myElement.offset(),
        elementHeight = $myElement.height(),
        elementWidth = $myElement.width(),
    
        minTop = documentScrollTop,
        maxTop = documentScrollTop + viewportHeight,
        minLeft = documentScrollLeft,
        maxLeft = documentScrollLeft + viewportWidth;
    
    function scrollToPosition(position) {
        jQuery('html,body').animate({
            scrollTop : position.top,
            scrollLeft : position.left
        }, 300);
    }
    
    if (
        ((elementOffset.top > minTop && elementOffset.top < maxTop) ||
        (elementOffset.top + elementHeight > minTop && elementOffset.top + 
    elementHeight < maxTop))
    &&  ((elementOffset.left > minLeft && elementOffset.left < maxLeft) ||
        (elementOffset.left + elementWidth > minLeft && elementOffset.left +
    elementWidth < maxLeft)))
    {
        alert('some portion of the element is visible');
    
        if (elementOffset.top >= minTop && elementOffset.top + elementHeight 
    <= maxTop) {
            verticalVisible = elementHeight;
        } else if (elementOffset.top < minTop) {
            verticalVisible = elementHeight - (minTop - elementOffset.top);
        } else {
            verticalVisible = maxTop - elementOffset.top;
        }
    
        if (elementOffset.left >= minLeft && elementOffset.left + elementWidth 
    <= maxLeft) {
            horizontalVisible = elementWidth;
        } else if (elementOffset.left < minLeft) {
            horizontalVisible = elementWidth - (minLeft - elementOffset.left);
        } else {
            horizontalVisible = maxLeft - elementOffset.left;
        }
    
        var percentVerticalVisible = (verticalVisible / elementHeight) * 100;
        var percentHorizontalVisible = (horizontalVisible / elementWidth) * 100;
    
        if (percentVerticalVisible < 50 || percentHorizontalVisible < 50) {
            alert('less than 50% of element visible; scrolling');
            scrollToPosition(elementOffset);
        } else {
            alert('enough of the element is visible that there is no need to scroll');
        }
    
    } else {
        // element is not visible; scroll to it
        alert('element is not visible; scrolling');
        scrollToPosition(elementOffset);
    }
    
    0 讨论(0)
  • 2020-12-14 18:15

    I think this is the complete answer. An elevator must be able to go both up and down ;)

    function ensureVisible(elementId, top = 0 /* set to "top-nav" Height (if you have)*/) {
      let elem = $('#elementId');
      if (elem) {
        let offset = elem.offset().top - $(window).scrollTop();
        if (offset > window.innerHeight) { // Not in view
          $('html,body').animate({ scrollTop: offset + top }, 1000);
        } else if (offset < top) { // Should go to top
          $('html,body').animate({ scrollTop: $(window).scrollTop() - (top - offset) }, 1000);
        }
      }
    }
    
    0 讨论(0)
  • 2020-12-14 18:25

    No-JQuery version.

    The particular case here is where the scroll container is the body (TBODY, table.body) of a TABLE (scrolling independently of THEAD). But it could be adapted to any situation, some simpler.

    const row = table.body.children[ ... ];
    ...
    
    const bottomOfRow = row.offsetHeight + row.offsetTop ;
    // if the bottom of the row is in the viewport...
    if( bottomOfRow - table.body.scrollTop < table.body.clientHeight ){
        // ... if the top of the row is in the viewport
        if( row.offsetTop - table.body.scrollTop > 0 ){
            console.log( 'row is entirely visible' );
        }
        else if( row.offsetTop - table.body.scrollTop + row.offsetHeight > 0 ){
            console.log( 'row is partly visible at top')
            row.scrollIntoView();
        }
        else {
            console.log( 'top of row out of view above viewport')
            row.scrollIntoView();
        }
    }
    else if( row.offsetTop  - table.body.scrollTop < table.body.clientHeight ){
        console.log( 'row is partly visible at bottom')
        row.scrollIntoView();
    }
    else {
        console.log( 'row is out of view beneath viewport')
        row.scrollIntoView();
    }
    
    0 讨论(0)
提交回复
热议问题