Element.offsetHeight for Visibility
One of the (perceived) tricky tasks within front-end coding is checking if an element is visible or not. The very naive way of checking if an element is visible (i.e. has presence or takes up space on the page) is by checking its display style value:
var incorrectIsVisible = window.getComputedStyle(someElement, null).getPropertyValue('display'); // "inline", "inline-block", "block", etc.
Notice I'm not checking the opacity as well because an invisible element still takes up space on the screen. The problem with the code above is that you can gain the style of a child but that may not matter if its parent is set to display: none
. For example, if the child's display
style value is inline-block
, but the element's parent display
style is none
, the child element is still not visible. Oddly enough, checking the child element's offsetHeight
value will signal if the element is likely visible:
var correctIsVisible = someElement.offsetHeight; // 0 for hidden, more than 0 for displaying
If the element is a child of an element which is display: none
, the offsetHeight
will be 0 and thus you know the element is not visible despite its display
value. Again, remember that opacity is not considered and an element which is opacity: 0
is still technically visible, taking up space.
Unfortunately there are a lot of caveats to this.
First of all, it’s not just opacity that will render an element invisible but still taking up space.(filters and
visibility:hidden
)Another that comes to mind right away is checking elements that have no
padding
orborder
and have justfloating
/absolute
/fixed
children.Also, in some cases you could set an element’s
height
to0
and having overflowing children (don’t have a use case popping up though)Solution; somebody else probably figured that out. My first guess would be either setting height to 1px for the test or bubbling up and use the display none check..
What about checking for El.clientwidth === 0
and are there other way to check is an element is visible without triggering a reflow/repaint?
The best bet seems to me to check
Element.offsetParent
. If it returnsnull
, the element is not visible.What about SVG elements? They don’t have
offsetHeight
property, but they can be set todisplay:none;