:visible/:hidden selectors unreliable
See original GitHub issueIssue
This issue is present in both version 1 and 2 of jQuery.
It is happening on inline elements wrapping block elements, which is valid in HTML5, such as a header and an image wrapped in a single anchor.
Two issues arise:
- Different browsers report offsetWidth/Height of the anchor differently. For example Firefox would report one visible anchor in the example below, and Chrome will report 0. This also highly depends on the CSS styles applied, as on the page where this issue was discovered missing images are not displayed at all instead of the common missing image icon.
- While a browser may report an anchor as invisible, child elements are still visible and clickable as they inherit anchor properties.
Example
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
</head>
<body>
<a href=#>
<h1>Header</h1>
</a>
<script>
$(function () {
alert('Visible anchors: ' + $('a:visible').length);
})
</script>
</body>
</html>
Solution
There are 2 potential solutions that come to mind, but each has flaws
- Loop through child elements and check each for visibility. Potentially harmful for performance, although the selector is already marked as such in the documentation.
- Check parent for visibility. Probably not enough on its own, as it will report incorrectly, if anchor doesn’t have visible children.
Issue Analytics
- State:
- Created 8 years ago
- Comments:22 (17 by maintainers)
Top Results From Across the Web
The `hidden` Attribute is Visibly Weak - CSS-Tricks
It's extremely weak. Literally any change to the display property other than the none value on the element with any strength selector will ......
Read more >Difference between :hidden and :not(:visible) in jQuery
The :hidden selector is the opposite of the :visible selector. So, every element selected by :hidden isn't selected by :visible and vice versa....
Read more >visibility - CSS: Cascading Style Sheets - MDN Web Docs
The visibility CSS property shows or hides an element without changing the layout of a document. The property can also hide rows or...
Read more >jQuery Basics: Is Element Hidden or Visible?
The “:visible” selector will match an elements that are essentially Visible to the user within the page. This is determined by inspecting the ......
Read more >Selecting Elements - jQuery Learning Center
Note: When using the :visible and :hidden pseudo-selectors, jQuery tests the actual visibility of the element, not its CSS visibility or ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Thank you for opening an issue. While you are correct that the behavior may be unexpected, the selector is working as documented. While the behavior differs between Firefox and Chrome, Chrome reports zero width and zero height, which technically means it is not visible according to our docs…
The fact the hidden elements can have visible content can seem strange, but it’s the way it is in Chrome. But more importantly, the cost of working around this would be far greater than we are willing to deal with. I don’t think this is the only edge case where the
:visible
selector behaves in a way that can be unexpected, but I would prefer to keep the selector as simple as possible and let the edge cases be covered by other means.My apologies for commenting on a closed issue, but I believe this case warrants review.
Using ClientRectList.prototype.length an anchor tag with no text is “visible”, not to mention one with child elements which have no dimension either.
Please consider https://github.com/FesterCluck/jquery/blob/master/src/css/hiddenVisibleSelectors.js
If this is not part of the new intended behavior, my apologies.