indigopear.com 0 Newbie Poster

Hi,

I have a resizable container div with overflow:hidden. If an element within the container doesn't fit completely, we want to set its visibility to hidden (rather than letting it crop). I have a function that checks offsetTop and offsetHeight to determine if an element is within the bounds of its container's visible area.

The problem I am having is that in IE, I'm getting the wrong offsetTop values on some elements that wrap. There are 4 image links in the container. If the browser is large enough, they appear on one line. As the browser shrinks, 1 or 2 of them will wrap to the 2nd line. The first element that wraps has a smaller offsetTop value than elements on the 1st line. If 2 elements wrap, the 2nd one has a correct offsetTop.

(btw, I'm also seeing an incorrect offsetHeight in mozilla, but it seems to be working anyway?!)

Can anyone shed some light on this? Is there some better way to determine if an element is completely within the visible area of its container, or am I just doing something wrong? :confused:

Thanks!
-Ann

A test page is here: Portfolio.php

And here is the pertinent bit of code:

//
// Set height of contentPanel
//
var y = y-196-50;
var panel=document.getElementById('contentPanel');
panel.style.height = y + 'px';
//
//
// Set visibility of child elements in contentPanel
//
function findPosY(obj)  // Get full top offset
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}
function setVisibility(node, y, panel) {
   var children=node.childNodes;
   for (var i=0; i < children.length; i++) {
 	if (children[i].className && (children[i].className == 'toggle' || children[i].className.search('toggle'))) {
		var top=findPosY(children[i])
	   	var height = children[i].offsetHeight;
		var panelTop = findPosY(panel);
		//alert("offsetTop = " + top + " offsetHeight = " + height);
	   	if ( (top+height) > (y+panelTop) )
	       		children[i].style.visibility = 'hidden';
	   	else
	      		children[i].style.visibility = 'visible';
        }
	else
	   	setVisibility(children[i], y, panel);
   }
}
if (panel.className == 'noScroll') {
   panel.style.overflow = 'hidden';
   setVisibility(panel, y, panel);
}

Dani AI

Generated

For your case , avoid summing offsetTop values across offsetParents. IE’s offsetParent/offsetTop behavior can vary when elements are inline, floated, or inside differently positioned ancestors. A simpler, more reliable check is to compare bounding rectangles: get the child’s getBoundingClientRect() and the panel’s getBoundingClientRect() and test whether the child’s top and bottom lie inside the panel’s top and bottom.

function isFullyVisible(el, panel) {
  var rEl = el.getBoundingClientRect();
  var rPanel = panel.getBoundingClientRect();
  return rEl.top >= rPanel.top && rEl.bottom <= rPanel.bottom;
}

If you need to include/exclude panel padding or borders, use panel.clientHeight (or compute rPanel.top + panel.clientHeight) instead of rPanel.bottom. This approach avoids offsetParent chain surprises and works even when items wrap to a new line.

Quick debugging tips:

  • Log the offsetParent chain to see which ancestor each element is using:
    for (var n = node; n; n = n.offsetParent) {
    console.log(n.tagName + (n.id ? '#'+n.id : ''), 'offsetTop=', n.offsetTop);
    }
  • Ensure the panel is a positioned ancestor (e.g., position: relative) if you prefer working with offsetTop values.
  • Debounce resize handlers (use requestAnimationFrame or a short setTimeout) to avoid layout thrashing when calling these checks repeatedly.

References: Element.getBoundingClientRect and HTMLElement.offsetTop.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.