Bug Tracker

Opened 15 years ago

Closed 14 years ago

Last modified 12 years ago

#4374 closed bug (fixed)

: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;
};

Change History (6)

comment:1 Changed 15 years ago by brandon

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.

comment:2 Changed 15 years ago by borgar

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)

comment:3 Changed 15 years ago by brandon

Resolution: fixed
Status: reopenedclosed

Thanks for adding more details!

Fixed in r6282.

comment:4 Changed 14 years ago by brandon

Resolution: fixed
Status: closedreopened

comment:5 Changed 14 years ago by brandon

Owner: set to brandon
Status: reopenednew

comment:6 Changed 14 years ago by brandon

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.