检查元素是否在屏幕上可见

可能的复制品:
JQuery-在滚动 之后检查元素是否可见

我试图确定一个元素是否在屏幕上可见。为此,我尝试使用 offsetTop 查找元素的垂直位置,但返回的值不正确。在这种情况下,除非向下滚动,否则元素不可见。尽管如此,当屏幕高度为703时,offsetTop 返回一个值618,因此根据 offsetTop,元素应该是可见的。

我使用的代码如下:

function posY(obj)
{
var curtop = 0;


if( obj.offsetParent )
{
while(1)
{
curtop += obj.offsetTop;


if( !obj.offsetParent )
{
break;
}


obj = obj.offsetParent;
}
} else if( obj.y )
{
curtop += obj.y;
}


return curtop;
}

先谢谢你!

196153 次浏览

Could you use jQuery, since it's cross-browser compatible?

function isOnScreen(element)
{
var curPos = element.offset();
var curTop = curPos.top;
var screenHeight = $(window).height();
return (curTop > screenHeight) ? false : true;
}

And then call the function using something like:

if(isOnScreen($('#myDivId'))) { /* Code here... */ };

--- Shameless plug ---
I have added this function to a library I created vanillajs-browser-helpers: https://github.com/Tokimon/vanillajs-browser-helpers/blob/master/inView.js
-------------------------------

Well BenM stated, you need to detect the height of the viewport + the scroll position to match up with your top position. The function you are using is ok and does the job, though its a bit more complex than it needs to be.

If you don't use jQuery then the script would be something like this:

function posY(elm) {
var test = elm, top = 0;


while(!!test && test.tagName.toLowerCase() !== "body") {
top += test.offsetTop;
test = test.offsetParent;
}


return top;
}


function viewPortHeight() {
var de = document.documentElement;


if(!!window.innerWidth)
{ return window.innerHeight; }
else if( de && !isNaN(de.clientHeight) )
{ return de.clientHeight; }
    

return 0;
}


function scrollY() {
if( window.pageYOffset ) { return window.pageYOffset; }
return Math.max(document.documentElement.scrollTop, document.body.scrollTop);
}


function checkvisible( elm ) {
var vpH = viewPortHeight(), // Viewport Height
st = scrollY(), // Scroll Top
y = posY(elm);
    

return (y > (vpH + st));
}

Using jQuery is a lot easier:

function checkVisible( elm, evalType ) {
evalType = evalType || "visible";


var vpH = $(window).height(), // Viewport Height
st = $(window).scrollTop(), // Scroll Top
y = $(elm).offset().top,
elementHeight = $(elm).height();


if (evalType === "visible") return ((y < (vpH + st)) && (y > (st - elementHeight)));
if (evalType === "above") return ((y < (vpH + st)));
}

This even offers a second parameter. With "visible" (or no second parameter) it strictly checks whether an element is on screen. If it is set to "above" it will return true when the element in question is on or above the screen.

See in action: http://jsfiddle.net/RJX5N/2/

I hope this answers your question.

-- IMPROVED VERSION--

This is a lot shorter and should do it as well:

function checkVisible(elm) {
var rect = elm.getBoundingClientRect();
var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
return !(rect.bottom < 0 || rect.top - viewHeight >= 0);
}

with a fiddle to prove it: http://jsfiddle.net/t2L274ty/1/

And a version with threshold and mode included:

function checkVisible(elm, threshold, mode) {
threshold = threshold || 0;
mode = mode || 'visible';


var rect = elm.getBoundingClientRect();
var viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
var above = rect.bottom - threshold < 0;
var below = rect.top - viewHeight + threshold >= 0;


return mode === 'above' ? above : (mode === 'below' ? below : !above && !below);
}

and with a fiddle to prove it: http://jsfiddle.net/t2L274ty/2/