Bug Tracker

Ticket #4374 (closed bug: fixed)

Opened 5 years ago

Last modified 2 years ago

: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:
Blocking: Blocked by:

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

comment:1 Changed 5 years ago by brandon

  • Status changed from new to closed
  • Resolution set to invalid

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 5 years ago by borgar

  • Status changed from closed to reopened
  • Resolution invalid deleted

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 5 years ago by brandon

  • Status changed from reopened to closed
  • Resolution set to fixed

Thanks for adding more details!

Fixed in r6282.

comment:4 Changed 5 years ago by brandon

  • Status changed from closed to reopened
  • Resolution fixed deleted

comment:5 Changed 5 years ago by brandon

  • Owner set to brandon
  • Status changed from reopened to new

comment:6 Changed 5 years ago by brandon

  • Status changed from new to closed
  • Resolution set to fixed
Note: See TracTickets for help on using tickets.