15

With a div element in a parent div that is hidden with display:none.

  • I'm dumping the jQuery textarea element to the console. I see that the scrollHeight property of the 0th element is 88.
  • I try to read this property to a var (using $(element)[0].scrollHeight or $(element).prop('scrollHeight') and I'm getting 0.

I also tried to set the textarea to position: absolute and display: block with jQuery, before the read, with the same result.

How can I read the property correctly?

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
RolandG
  • 1,269
  • 4
  • 14
  • 21

4 Answers4

8

What is the size of an element when display:none? 0px by 0px

The element hasn't been rendered or painted anywhere on the screen, and so it truly occupies zero pixels worth of space. The question of if it was visible, how much space it would consume is tricky to answer, because answering it accurately means turning the hypothetical into a reality. We would need to actually render it to get a reliable measure of its size.

Generally speaking, this involves either:

  1. Toggling - Quickly making the element visible, checking the height, and restore back

    When toggling, you might be able to make visible and undo in between paint cycles, but there's no guarantee. Especially if the element you're looking to measure is deeply nested inside a hidden parent.

  2. Cloning - Emulate the element's properties as best you can & rendering off screen

    When cloning, an element's dimensions are based on a large number of other elements and properties surrounding it. Depending on the complexity of your page, there's also no guarantee that creating an element offscreen will yield the same exact dimensions that the original would.

There are several solutions laid out in the following questions, but most follow that basic pattern:

There's also a library called jQuery.Actual (2.4KB) which abstracts away some of that work:

Here's their own Demo Page and also a Stack Snippet:

console.log("width: ", $("#inner").actual("width"))
console.log("height: ", $("#inner").actual("height"))
#outer, #inner {
  margin: 10px;
  padding: 10px;
}
#outer {
  background: #d1e3ef;
}
#inner {
  background: #9ebae9;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.actual/1.0.19/jquery.actual.min.js"></script>

<div id="outer" style="display:none">
  <code>#outer</code>
  <div id="inner">
    <code>#inner</code>
  </div>
</div>

Example

KyleMit
  • 30,350
  • 66
  • 462
  • 664
  • 4
    don't understand, it's a almost 6 years old question, you offer the bounty and you answer it? – Alex Angelico Jan 03 '19 at 23:32
  • 4
    @AlexAngelico, offered a bounty because I was looking for an answer, and then kept searching around and thought I'd share what I pieced together. You can't really recall a bounty, but thought it was still valuable to update with info. – KyleMit Jan 04 '19 at 00:45
3

You need to set dispaly:block property for parent div. And after getting scrollheight by using $(element)[0].scrollHeight you can set display:none to main div.

So your code will be

$('#mainDiv').show();
// Dump html to div
// Read height
var heightOfDiv = $('#mainDiv')[0].scrollHeight
// Hide the div
$('#mainDiv').hide();
mujaffars
  • 1,395
  • 2
  • 15
  • 35
  • I believe this works, and momentarily showing the control and almost instantaneously hiding it again is not going to be visible to the user. In fact the browse may not even actually try to update what the user sees until the function block completes, thus in effect the control was always hidden while getting you the measurement you need. – John Fantastico Jan 08 '19 at 14:06
2

An element with display: none not only will not be displayed, but also will not be processed by the DOM tree. That's why the scrollHeight will be 0.

Otherwise, with visibility: hidden, the element won't be visible, however it will have his space reserved in the DOM. So it will have a scrollHeight different to 0.

Then, to read the property and keep the element hidden you could use $('#elementId').prop('visibility','hidden'); $('#elementId').prop('scrollHeight').

Byron Rodríguez
  • 191
  • 2
  • 10
  • Setting `visibility: hidden;` to an element that is already `display: none;` wont give you the value of scroll height, since `display: none;` would take preference, isn't it? – surajck Jan 10 '19 at 14:39
  • `display: none;` takes precedence because it affects the DOM structure. `visibility: hidden;` does not affect the DOM structure, is like setting properties like color or opacity. – Byron Rodríguez Jan 10 '19 at 16:11
1

No it is unfortunately not possible.

I suggest you read these links: MDN | Display or Article from nomensa , that evoke the notion of DOM accessibility and visibility. In fact, if you put an element to "display: none", it will not be visible and will exit the DOM accessibility tree. However, there are some techniques that will allow you to make an DOM element completely invisible and no longer considered to exist on the DOM.

Then there are obviously techniques that you should surely know

The first if you want to completely mask your parent div without worrying about its dimensions, I propose the code below. The clip property is depreciating but without it, it's still going to hide our item.

console.log(document.getElementById('child').scrollHeight);
.hidden {
 border: 0;
 clip: rect(0 0 0 0);
 height: 1px;
 margin: -1px;
 overflow: hidden;
 padding: 0;
 position: absolute;
 white-space: nowrap;
 width: 1px;
  z-index: -1;
}
<div class="hidden parent" href="#main">
  I am ignored by the DOM
  <div id="child">I am child</div>
</div>
<span style="color:red">I am the N°1</span>

Otherwise, if you want to keep the dimensions of your parent div, you can float it out of the DOM stream.

console.log(document.getElementById('child').scrollHeight);
.hidden {
 height: auto;
  width: auto;
  visibility: hidden;
 position: absolute;
  z-index: -1;
}
<div class="hidden parent" href="#main">
  I am ignored by the DOM
  <div id="child">I am child</div>
</div>
<span style="color:red">I am the N°1</span>

I hope this answer will be helpful.

soumare
  • 394
  • 5
  • 9