.scrollHeight:
This property will round the value to an integer. If you need a fractional value, use
element.getBoundingClientRect()
.
Except... element.getBoundingClientRect()
does not return the scrollHeight. How would one get a fractional scrollHeight? Is it possible?
https://developer.mozilla/en-US/docs/Web/API/element.scrollHeight:
This property will round the value to an integer. If you need a fractional value, use
element.getBoundingClientRect()
.
Except... element.getBoundingClientRect()
does not return the scrollHeight. How would one get a fractional scrollHeight? Is it possible?
3 Answers
Reset to default 0Inside the scrollable outerEl
, have an innerEl
element contain all content, so the scrollHeight equals the element height. Then you can get scroll height in decimals using innerEl.getBoundingClientRect().height
.
Note that you need to make sure there is no margin between outerEl
and innerEl
. Set padding of outerEl
to 0, margin of innerEl
, first child of innerEl
, and last child of innerEl
to 0.
document.getElementById("scrollHeight").innerText = document.getElementById("outer").scrollHeight
document.getElementById("boundingRect").innerText = document.getElementById("inner").getBoundingClientRect().height
#outer {
height: 50px;
overflow-y: auto;
background-color: lightblue;
padding: 0px;
}
#inner {
margin: 0;
background-color: yellow;
}
.content {
margin: 0;
}
<div id="outer">
<div id="inner">
<div class="content">
outerEl.scrollHeight: <span id="scrollHeight">?</span>
</div>
<div class="content">
innerEl.getBoundingClientRect().height: <span id="boundingRect">?</span>
</div>
<div class="content">
You must make sure there is no margin between outer element and inner element.
</div>
</div>
</div>
This will get the diff between the integer and floating width by paring clientWidth to rect.width, and then applying that to scrollWidth. It also takes into account issues with subtracting floating point numbers in javascript, and if a scrollbar is present.
function getScrollWidth(el) {
return getScrollDimension(el, true);
}
function getScrollHeight(el) {
return getScrollDimension(el, false);
}
function getScrollDimension(el, isWidth) {
// https://stackoverflow./questions/21666892/fractional-scrollheight
// https://stackoverflow./questions/6027937/javascript-float-subtract
const rect = el.getBoundingClientRect();
const rectVal = isWidth ? rect.width : rect.height;
const clientVal = isWidth ? el.clientWidth : el.clientHeight;
const scrollVal = isWidth ? el.scrollWidth : el.scrollHeight;
const offsetVal = isWidth ? el.offsetWidth : el.offsetHeight;
const oppositeScrollbarVal = offsetVal - clientVal; // when measuring width, this is the vertical scrollbar width
const dimString = rectVal.toString();
const decimalIndex = dimString.indexOf(".");
let decimalPlaces = 0;
if (decimalIndex > -1) {
decimalPlaces = dimString.substr(decimalIndex + 1).length;
}
const multiplier = Math.pow(10, decimalPlaces); // get us out of floating point math to avoid rounding errors
// rect.width and e.clientWidth are the same measurement, but rect.width has more precision because el.clientWidth is rounded.
// Get the difference between those and apply it to the scrollWidth.
//
// If el.clientWidth was rounded down from 100.4 to 100, then we want to end up with 0.4.
// If el.clientWidth was rounded up from 100.5 to 101, then we want to end up with -0.5.
const diff = ((rectVal * multiplier) - (clientVal * multiplier)) ;
const finalScrollWidth = ((scrollVal * multiplier) + (diff)) / multiplier;
return finalScrollWidth - oppositeScrollbarVal;
}
I think I might have the solution:
var rect = element.getBoundingClientRect()
var scrollHeight = element.scrollHeight + (parseInt(rect.height) - rect.height)
var scrollWidth = element.scrollWidth + (parseInt(rect.width) - rect.width)