What is offsetHeight, clientHeight, scrollHeight? - javascript

Thought of explaining what is the difference between offsetHeight, clientHeight and scrollHeight or offsetWidth, clientWidth and scrollWidth?
One must know this difference before working on the client side. Otherwise half of their life will be spent in fixing the UI.
Fiddle, or inline below:
function whatis(propType) {
var mainDiv = document.getElementById("MainDIV");
if (window.sampleDiv == null) {
var div = document.createElement("div");
window.sampleDiv = div;
}
div = window.sampleDiv;
var propTypeWidth = propType.toLowerCase() + "Width";
var propTypeHeight = propType + "Height";
var computedStyle = window.getComputedStyle(mainDiv, null);
var borderLeftWidth = computedStyle.getPropertyValue("border-left-width");
var borderTopWidth = computedStyle.getPropertyValue("border-top-width");
div.style.position = "absolute";
div.style.left = mainDiv.offsetLeft + Math.round(parseFloat((propType == "client") ? borderLeftWidth : 0)) + "px";
div.style.top = mainDiv.offsetTop + Math.round(parseFloat((propType == "client") ? borderTopWidth : 0)) + "px";
div.style.height = mainDiv[propTypeHeight] + "px";
div.style.lineHeight = mainDiv[propTypeHeight] + "px";
div.style.width = mainDiv[propTypeWidth] + "px";
div.style.textAlign = "center";
div.innerHTML = propTypeWidth + " X " + propTypeHeight + "( " +
mainDiv[propTypeWidth] + " x " + mainDiv[propTypeHeight] + " )";
div.style.background = "rgba(0,0,255,0.5)";
document.body.appendChild(div);
}
document.getElementById("offset").onclick = function() {
whatis('offset');
}
document.getElementById("client").onclick = function() {
whatis('client');
}
document.getElementById("scroll").onclick = function() {
whatis('scroll');
}
#MainDIV {
border: 5px solid red;
}
<button id="offset">offsetHeight & offsetWidth</button>
<button id="client">clientHeight & clientWidth</button>
<button id="scroll">scrollHeight & scrollWidth</button>
<div id="MainDIV" style="margin:auto; height:200px; width:400px; overflow:auto;">
<div style="height:400px; width:500px; overflow:hidden;">
</div>
</div>

To know the difference you have to understand the box model, but basically:
clientHeight:
returns the inner height of an element in pixels, including padding but not the horizontal scrollbar height, border, or margin
offsetHeight:
is a measurement which includes the element borders, the element vertical padding, the element horizontal scrollbar (if present, if rendered) and the element CSS height.
scrollHeight:
is a measurement of the height of an element's content including content not visible on the screen due to overflow
I will make it easier:
Consider:
<element>
<!-- *content*: child nodes: --> | content
A child node as text node | of
<div id="another_child_node"></div> | the
... and I am the 4th child node | element
</element>
scrollHeight: ENTIRE content & padding (visible or not)
Height of all content + paddings, despite of height of the element.
clientHeight: VISIBLE content & padding
Only visible height: content portion limited by explicitly defined height of the element.
offsetHeight: VISIBLE content & padding + border + scrollbar
Height occupied by the element on document.

* offsetHeight is a measurement in pixels of the element's CSS height, including border, padding and the element's horizontal scrollbar.
* clientHeight property returns the viewable height of an element in pixels, including padding, but not the border, scrollbar or margin.
* scrollHeight value is equal to the minimum height the element would require in order to fit all the content in the viewport without using a vertical scrollbar. The height is measured in the same way as clientHeight: it includes the element's padding, but not its border, margin or horizontal scrollbar.
Same is the case for all of these with width instead of height.

My descriptions for the three:
offsetHeight: How much of the parent's "relative positioning" space is taken up by the element. (ie. it ignores the element's position: absolute descendents)
clientHeight: Same as offset-height, except it excludes the element's own border, margin, and the height of its horizontal scroll-bar (if it has one).
scrollHeight: How much space is needed to see all of the element's content/descendents (including position: absolute ones) without scrolling.
Then there is also:
getBoundingClientRect().height: Same as scrollHeight, except that it's calculated after the element's css transforms are applied.

Offset Means "the amount or distance by which something is out of line". Margin or Borders are something which makes the actual height or width of an HTML element "out of line". It will help you to remember that :
offsetHeight is a measurement in pixels of the element's CSS
height, including border, padding and the element's horizontal
scrollbar.
On the other hand, clientHeight is something which is you can say kind of the opposite of OffsetHeight. It doesn't include the border or margins. It does include the padding because it is something that resides inside of the HTML container, so it doesn't count as extra measurements like margin or border. So :
clientHeight property returns the viewable height of an element in
pixels, including padding, but not the border, scrollbar or margin.
ScrollHeight is all the scrollable area, so your scroll will never run over your margin or border, so that's why scrollHeight doesn't include margin or borders but yeah padding does. So:
scrollHeight value is equal to the minimum height the element would require in order to fit all the content in the viewport without using
a vertical scrollbar. The height is measured in the same way as
clientHeight: it includes the element's padding, but not its border,
margin or horizontal scrollbar.

Related

jQuery outerHeight() & height change flicker/fail on window resize to odd pixels

I have two side-by-side elements on a page. One elements has a fixed size (100vh) – .hero-half – and the other is fluid with text of varying lengths – .project-details. When the fluid text container extends to be taller than the image container, I want to apply a class to it that restricts the height of one of its child elements to bing the total text container height back to equal with the image height.
HTML:
<div class="project-details left">
<h1 class="project">Title</h1>
<div class="project-summary">
<div class="summary-container">
<p>A bunch of paragraphs here</p>
</div>
<a class="more" href="#">More</a>
<a class="less" href="#">Less</a>
</div>
</div>
<div class="hero hero-half right" style="background-image: url('/img/placeholder-vert1.jpg')"></div>
The relevant CSS:
.hero-half {
width: 50%;
height: 100vh;
}
.project-details {
width: 50%;
height: auto;
}
.project-summary .summary-container {
overflow: hidden;
&.restrict-height {
.summary-container {
// set max height
max-height: calc(100vh - 615px);
}
}
}
Here is my JS code:
$(function () {
var bpTab = 1024;
resize = function() {
var winWidth = $(window).width();
var heroHeight = $(".hero-half").outerHeight();
var boxHeight = $(".project-details").outerHeight();
var $box = $(".project-summary");
if ( boxHeight > heroHeight && winWidth > bpTab) {
// if on desktop layout AND if text is pusing box too big, restrict box height
$box.addClass("restrict-height");
} else {
// if not on desktop or text is not pushing box too big
$box.removeClass("restrict-height");
$box.removeClass("is-expanded");
};
};
// resize on window resize
$(window).bind("resize orientationchange", function(){
resize();
});
// resize on page load
resize();
});
So when the project-details div reaches a height taller than .hero-half, it adds a class that sets a max-height on one of the children, which brings the total height of .project-details back to equal or less than .hero-half.
However when I resize my window to force the the text to push the project-details height too tall and trigger the restrict-height class, it only works when the screen width and height add up to even numbers (either both width and height are even, or both odd). If it's an odd total the outerHeight of project-details seems to calculate incorrectly.
The problem, I think, is that the outerHeight of .project-details is sometimes being calculated at it's natural height before the text height it restricted, and sometimes it's being calculates after that class is applied and after the text height it restricted, which therefor decreases the .project-details height back into an acceptable range.
I've tried adding a timeout delay for the addition of the class hoping that the extra time would mean the outerHeight calculation was always correct, but it didn't make a difference.
How should I alter this JS code to make sure the .project-details outerHeight is always reading the height before the restrict-height class is applied?
And related: why would the odd pixel dimensions have any effect here?
The solution was at add a reset before the if/else loop to standardise the div height be removing the extra classes that may alter its height first.
var $box = $(".project-summary");
// reset
$box.removeClass("restrict-height");
$box.removeClass("is-expanded");
var winWidth = $(window).width();
var heroHeight = $(".hero-half").outerHeight();
var boxHeight = $(".project-details").outerHeight();

dynamic width of textarea with no-wrap

How can I make a textarea which does not force line wrapping and extends its size to match the contents instead of showing a scroll-bar?
I need a textarea with dynamic width. The width should be the widest line of the textarea. I mean there should be no wrapping and the width should be changed the long a line gets.
Assign an input listener function which compares the scroll width and height against the outer width and height of the element. If they are different then set them as necessary.
For CSS you need white-space:nowrap to stop the lines from wrapping and overflow:hidden to get rid of the scroll bars.
$('.demo').on('input', function(e){
this.style.width = '';
this.style.height = '';
if(this.scrollWidth > this.clientWidth) this.style.width = this.scrollWidth + 'px';
if(this.scrollHeight > this.clientHeight) this.style.height = this.scrollHeight + 'px';
})
.demo {
white-space: nowrap;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea class="demo"></textarea>

div box size css show the value of auto

Help is really wanted here, I have a div surrounding a textarea, the div is auto sized, height and width, and I need to know what that auto value is. tried a little javascript, please see below:
function textAreaChange() {
var textboundary = document.getElementById("textarea");
textboundary.style.height = document.getElementById("heightx").innerHTML;
textboundary.style.width = document.getElementById("widthy").innerHTML;
}
fairly new to all this javascript so please be patient?
Thanks.
If you are looking at obtaining the height and width, based on wrapping of the text area, try one of the following:
var h = document.getElementById('someDiv').clientHeight;
var h = document.getElementById('someDiv').offsetHeight;
var h = document.getElementById('someDiv').scrollHeight;
clientHeight includes the height and vertical padding.
offsetHeight includes the height, vertical padding, and vertical borders.
scrollHeight includes the height of the contained document (would be greater than just height in case of scrolling), vertical padding, and vertical borders.
There are Widths that correspond to each Height.
You can do it like this :)
function textAreaChange() {
var textboundary = document.getElementById("textarea");
document.getElementById("heightx").innerHTML = textboundary.offsetHeight;
document.getElementById("widthy").innerHTML = textboundary.offsetWidth;
}
textAreaChange();
<textarea id="textarea" ></textarea>
<div id="heightx"></div>
<div id="widthy"></div>

CSS -calc() or JQuery calc() not working for top

I have four absolute positioned divs on the screen which need to maintain their positions in a ratio at all the resolutions.
div1 - height 150px, top 0px
div2 - height 30%, top 150px
div3 - height 50px, top (30% + 150px)
div 4 - height (70% - 200px), top (30% + 200px)
Working
var calcHeight;
calcHeight = attr["#value"].split('+');
$CompFrame.css('height', calcHeight[0].trim()).css('height', "+=" + calcHeight[1].trim());
Not Working
var calcTop;
calcTop = attr["#value"].split('+');
$CompFrame.css('top', calcTop[0].trim()).css('top', "+=" + calcTop[1].trim());
Code for "-" is also present
I can't use floats due to design reasons
Actually it does work. The jquery calc() implementation

Handling negative-position images with overflow:auto

Consider the following markup: http://jsfiddle.net/gbWgH/. Because the list overflows its container and overlaps with the text below, I'd like it to be scrollable instead, so I set it to overflow:auto. However, this cuts off parts of the image: http://jsfiddle.net/gbWgH/1/. Removing this rule make the image appear properly.
How can I make the text scrollable without cutting off the image? Is the simplest option to just calculate the coordinates manually using Javascript, as suggested in this answer?
img {position:relative; top : 20px; left : 20px;}
I ended up just resorting to Javascript. Here, an image is positioned 50 pixels to the left and 40 pixels above a li with id "myli", inside a ul with id "myul", by calculating an offset from the li's absolute position within the page body. Note that you have to account for the amount the ul has been scrolled.
var img = document.createElement("img");
img.src = ...
var li = document.getElementById("myli");
var scrollTop = document.getElementById("myul").scrollTop;
img.style.left = li.offsetLeft - 50 + 'px';
img.style.top = li.offsetTop - 40 - scrollTop + 'px';
img.style.position = 'absolute';
document.body.appendChild(img);

Categories

Resources