Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I would like to get the one element which is the most visible on the screen (takes up the most space). I have added an example picture below to understand my question a bit more.

example

The two black borders are the sides of a screen. As you can see, the green box (div2) is the most visible on the screen - I would like to know how I can get that element. The most visible element should not have to be fully visible.

I have done a quick (it wasn't THAT quick) seach but to no avail, if I have missed it - my apologies.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
163 views
Welcome To Ask or Share your Answers For Others

1 Answer

TLDR:

Inspired by this question and the necessity for similar functionality in my own projects, I've written a module/jQuery plugin based on the code below. If you're not interested in the 'how', just download that or install with your favourite package manager.

Original Answer:

The answer provided by exabyssus works well in most cases, apart from when neither of an element's top or bottom is visible e.g when the element height is greater than the window height.

Here's an updated version which takes that scenario into account and uses getBoundingClientRect which is supported right the way down to IE8:

// Usage: var $element = getMostVisible($('.elements' ));
function getMostVisible($elements) {
    var element,
        viewportHeight = $(window).height(),
        max = 0;

    $elements.each(function() {
        var visiblePx = getVisibleHeightPx($(this), viewportHeight);

        if (visiblePx > max) {
            max = visiblePx;
            element = this;
        }
    });

    return $elements.filter(element);
}

function getVisibleHeightPx($element, viewportHeight) {
    var rect = $element.get(0).getBoundingClientRect(),
        height = rect.bottom - rect.top,
        visible = {
            top: rect.top >= 0 && rect.top < viewportHeight,
            bottom: rect.bottom > 0 && rect.bottom < viewportHeight
        },
        visiblePx = 0;

    if (visible.top && visible.bottom) {
        // Whole element is visible
        visiblePx = height;
    } else if (visible.top) {
        visiblePx = viewportHeight - rect.top;
    } else if (visible.bottom) {
        visiblePx = rect.bottom;
    } else if (height > viewportHeight && rect.top < 0) {
        var absTop = Math.abs(rect.top);

        if (absTop < height) {
            // Part of the element is visible
            visiblePx = height - absTop;
        }
    }

    return visiblePx;
}

This returns the most visible element based on pixels rather than as a percentage of the height of the element, which was ideal for my use-case. It could easily be modified to return a percentage if desired.

You could also use this as a jQuery plugin so you can get the most visible element with $('.elements').mostVisible() rather than passing the elements to the function. To do that, you'd just need to include this with the two functions above:

$.fn.mostVisible = function() {
    return getMostVisible(this);
};

With that in place you can chain your method calls rather than having to save the element into a variable:

$('.elements').mostVisible().addClass('most-visible').html('I am most visible!');

Here's all of that wrapped up in a little demo you can try out right here on SO:

(function($) {
  'use strict';

  $(function() {
    $(window).on('scroll', function() {
      $('.the-divs div').html('').removeClass('most-visible').mostVisible().addClass('most-visible').html('I am most visible!');
    });
  });

  function getMostVisible($elements) {
    var element,
      viewportHeight = $(window).height(),
      max = 0;

    $elements.each(function() {
      var visiblePx = getVisibleHeightPx($(this), viewportHeight);

      if (visiblePx > max) {
        max = visiblePx;
        element = this;
      }
    });

    return $elements.filter(element);
  }

  function getVisibleHeightPx($element, viewportHeight) {
    var rect = $element.get(0).getBoundingClientRect(),
      height = rect.bottom - rect.top,
      visible = {
        top: rect.top >= 0 && rect.top < viewportHeight,
        bottom: rect.bottom > 0 && rect.bottom < viewportHeight
      },
      visiblePx = 0;

    if (visible.top && visible.bottom) {
      // Whole element is visible
      visiblePx = height;
    } else if (visible.top) {
      visiblePx = viewportHeight - rect.top;
    } else if (visible.bottom) {
      visiblePx = rect.bottom;
    } else if (height > viewportHeight && rect.top < 0) {
      var absTop = Math.abs(rect.top);

      if (absTop < height) {
        // Part of the element is visible
        visiblePx = height - absTop;
      }
    }

    return visiblePx;
  }



  $.fn.mostVisible = function() {
    return getMostVisible(this);
  }

})(jQuery);
.top {
  height: 900px;
  background-color: #999
}

.middle {
  height: 200px;
  background-color: #eee
}

.bottom {
  height: 600px;
  background-color: #666
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="the-divs">
  <div class="top"></div>
  <div class="middle"></div>
  <div class="bottom"></div>
</div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...