Skip to main content

Bug Tracker

Side navigation

#4374 closed bug (fixed)

Opened March 18, 2009 10:47AM UTC

Closed May 16, 2009 04:20PM UTC

Last modified March 14, 2012 02:34PM UTC

:hidden != :not(:visible)

Reported by: borgar Owned by: brandon
Priority: minor Milestone: 1.4
Component: core Version: 1.3.2
Keywords: hidden visible selector Cc:
Blocked by: Blocking:
Description

:hidden fails on elements that have width but no height.

Shouldn't jQuery(':hidden').length == jQuery(':not(:visible)').length for pages that have hidden elements?

The bug causes problems for containers that don't clear their floats. They have 0 height and yet are visible (or at least their contents). Animate won't, for example, fade them out because animate uses jQuery(this).is(":hidden") internally to test if an element is already hidden.

The test (jQuery 1.3.2, line 2369):

Sizzle.selectors.filters.hidden = function(elem){
  return elem.offsetWidth === 0 || elem.offsetHeight === 0;
};

Should probably be:

Sizzle.selectors.filters.hidden = function(elem){
  return elem.offsetWidth === 0 && elem.offsetHeight === 0;
};
Attachments (0)
Change History (6)

Changed March 18, 2009 02:03PM UTC by brandon comment:1

resolution: → invalid
status: newclosed

I believe the logic is correct. The element is not visible if either its width or height is 0. The solution here is to use make sure the parent is able to clear the floated children. There are several good techniques for this cross-browser now.

Changed March 18, 2009 04:05PM UTC by borgar comment:2

resolution: invalid
status: closedreopened

How is this logic correct? How is it acceptable that elements can be both visible and hidden at the same time? Either :hidden is broken or :visible is broken.

The following is the logic currently within jQuery:

  • An element is hidden if has either no width or no height.
  • An element is visible if has width or height.

Therefore:

height=0, width=0, visible=false, hidden=true
height=0, width=1, visible=true, hidden=true
height=1, width=0, visible=true, hidden=true
height=1, width=1, visible=true, hidden=false

Clearing the floats is not always what I want to do. I should not need to do this. CSS does not work that way. Height and width do not affect the ''visibility'' of children while overflow is set to visible.

The docs state:

Element assumed as hidden if it or its parents consumes no space in document.

This is clarified in the release notes for 1.3.2:

In jQuery 1.3.2 an element is visible if its browser-reported offsetWidth or offsetHeight is greater than 0.

Which means that the logic for :visible is correct:

return elem.offsetWidth > 0 || elem.offsetHeight > 0;

More from the same release notes:

if the element's width is 0 and the element's height is 0 then an element will be reported as hidden

But no it won't because the logic is bugged! (see ticket)

Changed March 18, 2009 05:57PM UTC by brandon comment:3

resolution: → fixed
status: reopenedclosed

Thanks for adding more details!

Fixed in r6282.

Changed May 16, 2009 04:19PM UTC by brandon comment:4

resolution: fixed
status: closedreopened

Changed May 16, 2009 04:20PM UTC by brandon comment:5

owner: → brandon
status: reopenednew

Changed May 16, 2009 04:20PM UTC by brandon comment:6

resolution: → fixed
status: newclosed