Question

I am dealing with a strange issue where jQuery's .is(':hidden') returns true for an element surrounding plainly visible content. See the problem in this fiddle.

The :hidden pseudo checks offsetWidth and offsetHeight, which actually report as 0 in this case.

The root cause seems to be bad markup: DIV nested inside a SPAN. Unfortunately, this example is reduced from markup on several large sites where the script needs to operate. There is no opportunity to change the markup.

Any ideas on how to get a reliable :hidden implementation given markup abuse in the real world? This question is not about fixing jQuery but about the logic of a robust visibility check, given that real-world HTML is often broken.

Update:

Per the accepted answer, adding a getBoundingClientRect check would make .is(':hidden') more robust in the cases where CSS is not used for radically altered positioning, e.g.,

function isHiddenSubtree($node) {
  if ($node.is(':hidden')) {
    var rect = $node.get(0).getBoundingClientRect();
    return rect.width === 0 && rect.height === 0;
  } else {
    return false;
  }
}

However, this would fail in the case of floated or positioned elements as shown in this fiddle.

Was it helpful?

Solution

That's all right, it's hidden:

Element div not allowed as child of element span in this context. (Suppressing further errors from this subtree.)

Span is inline element. In HTML5 parser markup is not broke than you set block element into inline element. But computation engine is not HTML5 parser. It works right for right markup.

What is computation engine? Open timeline in devtool bar of any big site and get the computation layers message on any ajax action, for example. That is it, this engine calculate/recalculate DOM offsets and sizes.

Edit:

getBoundingClientRect() return none zero sizes. But it works like this:

  • Clone the node to abstract sandbox
  • Calculate all styles which needs to apply the node
  • Apply then
  • Calculate the sizes

So getBoundingClientRect make many unnecessary operations.

OTHER TIPS

jquery reports :hidden if the elements width and height is 0, which is the case for your <span>

It means that if your element’s CSS display is “none”, or any of its parent/ancestor element’s display is “none”, or if the element’s width is 0 and the element’s height is 0 then an element will be reported as hidden.

See jQuery Release Notes for v1.3.2

You should check the visibility of the <div> and remove the surrounding <span> (see Pinal's answer)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top