views:

1011

answers:

6

Hi!

In the past we used the CSS attribute "display" to show and hide DOM elements. To check if an element is visible, we could just use:

element.offsetWidth > 0

Since we had some problems with Flash and Java Applets (they stop when they get display:none) we switched to the CSS attribute "visibility".

I am now looking for a fast and easy way to check if an element is not visible.

I have tried the following:

  • Checking the attribute itself on the element and and all parents => too slow
  • Checking the calculated style directly from the browser (element.currentStyle or window.getComputedStyle() plus getPropertyValue(style property)) => also too slow

Do you know any other way or shortcut to see if an element is visible?

A: 

Toggling Element Visibility by Kent is an unobtrusive, semantically valid way of presenting content that will degrade nicely for non-CSS-aware browsers.

  • After the page loads completely, we crawl through the entire document tree and look for block-level elements styled with class name toggle. If we find one that says toggle closed, we immediately hide its next sibling element, by styling it with class name hidden.
  • When we find one, we tell it to listen for mouse clicks.
  • When one of our pet elements hears a click, it leaps into action, hiding (or showing) its next available sibling, the same way we did it during the initial crawl.
  • All three class names (toggle, closed, and hidden) are fed in at the bottom in the init call, and may be changed to any valid class name.

Also look at this DevX article which compares the Display and Visibility properties.

Kevin Boyd
Though the links you provided are appropriate, I think some SO voters don't like mere 'forwarding' answers...
xtofl
My aim is to provide help to the one who needs answers, and if links can do that, I don't mind getting negative votes... at the expense of providing help.
Kevin Boyd
+1 - Alright then. I think the "Toggling Element Visibility" JS library is the highlight of the post. Nice one.
Jenko
+1  A: 

use JQuery and the you can do this

var isVisible = $('#foo').is(':visible');
Eoin
Here is my test setup:<div id="father" style="visibility:hidden;"> <div id="son">test</div></div>$('#son').is(':visible'); --> true$('#son').css("visibility") --> "hidden"The interesting part is HOW jQuery gets this value. If it uses one of my trials, it's not helping, since they are too slow...
Jonathan Weiß
That's the fastest method you can fathom?
J-P
No, look at the "Toggling Element Visibility" library below.
Jenko
A: 

CSS selectors are optimised to find sets of matching elements. There are several libraries implementing this functionality. JQuery, ExtJS Core to name a couple.

Using Ext Core, I could write a javascript function that checks for visibility as follows:

// Checks whether the element is currently visible using 
//     both visibility and display properties
if(Ext.get(el).isVisible()){
    alert('it\'s visible');
};

see http://extjs.com/products/extcore/docs/?class=Ext.Element for more Ext Core Ext.Element functionality.

Joshua
+1  A: 

Remember that visibility:hidden makes an element hidden, but that element still occupies its space, which may have some unexpected consequences on the layout (it may be an advantage as well if you are aware of this).

I would use absolute positioning to move the element far to the left, outside possible screen width. This gets the element out of the flow so the hidden element has no impact on layout, makes the element practically invisible, and it doesn't have the disatvantages of display:none.

.hide {
    position:absolute;
    left:-3000px;
}

Then to determine if an element is hidden you can use its offsetLeft property:

if( myElement.offsetLeft < 0 ){ /* it's hidden */ }

If you need to determine if a child element is off the screen (you don't know if it's the hidden element or its child) you can use .offsetParent and a while loop, as described in PPK's Find Position article.

pawel
Thank you Pawel, this is the best answer by now.Problem is: all our DOM elements have inline styles for absolute positioning, so that the "left" value from the class would not be applied. But you answer is getting close to what I'm looking for!
Jonathan Weiß
The trouble with this solution is that it doesn't hide it from non-CSS-aware browsers like screen readers. This can be an advantage if you want text to only be available for screen readers, but in this case it seems like a disadvantage.
Daniel Roseman
A: 
function isVisible(elem) {
  return elem.style.visibility !== "hidden";
}
Eli Grey
This won't work if the element itself has no visibility attribute, but inherits the value from its parent.
Jonathan Weiß
A: 

Checking the focus would work, either parent is visible or not.

var isVisible = true;
try{
    document.getElementById("target").focus();
}catch(err){
    isVisible = false;
}

It obviously should work on input or link, but for other element, I'm not sure.

I have studied the same problem before using jQuery, but that time my aim is to focus the first availabe field on a form. The resulting code is like:

$(":text:visible:enabled").filter(function(){
    return $(this).parents.filter(function(){
        return this.style.display == "none"; 
    }).size()==0;
}).slice(0,1).focus();

It would also work for hidden/invisble parent.

jackysee