Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between :hidden and :not(:visible) in jQuery

I know that both jQuery selectors match elements that are not visible (width or height equal to 0, display: none, parent with display: none), and I believe it is implied they should yield the same result in the docs.

For readability reasons, I would rather use :hidden but I want to know:

  • Are there any potential pitfalls that I should consider?
  • Will I always get the exact same result?
  • Which option has better performance?
like image 854
Meryovi Avatar asked Jul 02 '13 12:07

Meryovi


People also ask

How check element is hidden or not in jQuery?

Answer: Use the jQuery :visible Selector You can use the jQuery :visible selector to check whether an element is visible in the layout or not. This selector will also select the elements with visibility: hidden; or opacity: 0; , because they preserve space in the layout even they are not visible to the eye.

What is the difference between visibility hidden and display?

visibility:hidden- It is not visible but gets up it's original space whereas, display:none- It is hidden and takes no space.

How do you make a Div visible in jQuery?

To toggle a div visibility in jQuery, use the toggle() method. It checks the div element for visibility i.e. the show() method if div is hidden. And hide() id the div element is visible. This eventually creates a toggle effect.

What is visible jQuery?

version added: 1.0jQuery( ":visible" )Elements are considered visible if they consume space in the document. Visible elements have a width or height that is greater than zero. Elements with visibility: hidden or opacity: 0 are considered visible, since they still consume space in the layout.


1 Answers

  • EDIT 3/22/2016: add to answer re: jQuery 1.12/2.2 and 3.0 (*see end of answer)
  • EDIT 3/8/2016: enhance answer

Elements can be considered hidden for several reasons:

  • They have a CSS display value of none.
  • They are form elements with type="hidden".
  • Their width and height are explicitly set to 0.
  • An ancestor element is hidden, so the element is not shown on the page.

Elements with visibility: hidden or opacity: 0 are considered to be visible, since they still consume space in the layout. During animations that hide an element, the element is considered to be visible until the end of the animation.

Elements that are not in a document are not considered to be visible; jQuery does not have a way to know if they will be visible when appended to a document since it depends on the applicable styles.

The :hidden selector is the opposite of the :visible selector. So, every element selected by :hidden isn't selected by :visible and vice versa.

During animations to show an element, the element is considered to be visible at the start of the animation.

How :hidden is determined was changed in jQuery 1.3.2. An element is assumed to be hidden if it or any of its parents consumes no space in the document. CSS visibility isn't taken into account


Clarification "width or height equal to 0," - not strictly true as some browsers (opera) reports less than 0 in some instances so jQuery uses <=0 internally.

  1. Are there any potential pitfalls that I should consider?
  2. Will I always get the exact same result?
  3. Which option has better performance?

1: "Pitfalls" other than obvious of which I am unaware of any, is somewhat subjective. I say this as I try to avoid "negative" tests in code (not x or !x type checks) as equality checks are more intuitive for my brain to understand.

2: Yes, the result should be the same

3: Re: Performance Difference between: RE: 1.10.1 version

Visible condition check uses the not hidden internally:

jQuery.expr.filters.visible = function( elem ) {     return !jQuery.expr.filters.hidden( elem ); }; 

So it could be said that strictly speaking "hidden" should be more efficient avoiding the "not" condition.

Internally, jQuery uses a "right to left" selector so the selector will make more of difference in some cases.

For performance, use

$(selector).filter(':hidden') 

or

$(selector).not(':visible')  

rather than either

$('selector:not(:visible)')  

or

$('selector:hidden') 

Why is this? :hidden is a jQuery extension and therefore cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. (see the right to left parsing of the Sizzle engine for how it will occur)

Forms/format of the selector

This is because for the $('selector:hidden') form, it will select (walking the DOM)

  1. all hidden elements first,
  2. then select those matching the selector from that set. It would be preferred to match the selector first, then filter those in that set that are hidden.

internal "isHidden" function: (jQuery 1.10.1)

function isHidden( elem, el ) {     // isHidden might be called from jQuery#filter function;     // in that case, element will be second argument     elem = el || elem;     return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); } 

Used for example in the .showHide internally such as:

if ( elem.style.display === "" && isHidden( elem ) ) { 

Worth noting that the "hidden" attribute in defaultPrefilter is:

hidden = elem.nodeType && isHidden( elem ), 

Special note on style:

Setting an elements CSS as:

document.getElementById("hide-me").style.visibility = "hidden"; 

is very fast.

You can also detect this very fast:

document.getElementById("hide-me").style.visibility  === "hidden"; 

Remember though that the element still takes up space whereas document.getElementById("hide-me").style.display = "block"; does seem to make it visible but keep in mind that some PARENT might NOT be visible thus the element might still be considered "hidden" - and jQuery does detect this (see above)

Additional reference: https://api.jquery.com/hidden-selector/

Additional information re: jQuery 1.12/2.2 and 3.0 3/22/2016 edit

There have been some significant speed improvements in these versions.

  • Reference this post: https://github.com/jquery/jquery/issues/2042
  • Related reference: https://github.com/jquery/sizzle/issues/315#issuecomment-74336936

This change can yield up to 1600% speed improvements wow! By taking advantage of caching when possible - which from what I have observed often occurs with these selectors. Test your pages with both if you have need for improvement or concerns in this area and use cases if heavily utilized within your pages.

You should see improved performance with .show() and .hide() as a result.

jQuery 1.12+ and 2.2.0+ and 3.0 modify the meaning of the :visible and :hidden filters. Elements will be considered :visible if they have layout boxes. This includes those with zero width and/or height. For your selectors beware of the count. Examples: inline elements with no content and br elements will now be selected by the :visible filter.

Page Markup examples:

<div> </div> <span></span> <br /> <p> </p> 

With the following sector:

var visibleElementCount = $('body').find(':visible').length; 
  • In jQuery 1.11.1 and 2.1.4 return value 2 for visibleElementCount
  • In jQuery 1.12+ and 2.2.0+ and 3.0 you’ll obtain 4 for visibleElementCount. Test when you rely upon this fact as it may be a breaking change for your pages.
like image 144
Mark Schultheiss Avatar answered Oct 01 '22 02:10

Mark Schultheiss