Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert vh units to px in JS

Unfortunately 100vh is not always the same as 100% browser height as can be shown in the following example.

html,
body {
    height: 100%;
}

body {
    overflow: scroll;
}

.vh {
    background-color: blue;
    float: left;
    height: 50vh;
    width: 100px;
}

.pc {
    background-color: green;
    float: left;
    height: 50%;
    width: 100px;
}
<div class="vh"></div>
<div class="pc"></div>

The issue is more pronounced on iPhone 6+ with how the upper location bar and lower navigation bar expand and contract on scroll, but are not included in the calculation for 100vh.

The actual value of 100% height can be acquired by using window.innerHeight in JS.

Is there a convenient way to calculate the current conversion of 100vh to pixels in JS?

I'm trying to avoid needing to generate dummy elements with inline styles just to calculate 100vh.

For purposes of this question, assume a hostile environment where max-width or max-height may be producing incorrect values, and there isn't an existing element with 100vh anywhere on the page. Basically, assume that anything that can go wrong has with the exception of native browser functions, which are guaranteed to be clean.

The best I've come up with so far is:

function vh() {
    var div,
        h;
    div = document.createElement('div');
    div.style.height = '100vh';
    div.style.maxHeight = 'none';
    div.style.boxSizing = 'content-box';
    document.body.appendChild(div);
    h = div.clientHeight;
    document.body.removeChild(div);
    return h;
}

but it seems far too verbose for calculating the current value for 100vh, and I'm not sure if there are other issues with it.

like image 761
zzzzBov Avatar asked Dec 08 '15 21:12

zzzzBov


1 Answers

How about:

function viewportToPixels(value) {
  var parts = value.match(/([0-9\.]+)(vh|vw)/)
  var q = Number(parts[1])
  var side = window[['innerHeight', 'innerWidth'][['vh', 'vw'].indexOf(parts[2])]]
  return side * (q/100)
}

Usage:

viewportToPixels('100vh') // window.innerHeight
viewportToPixels('50vw') // window.innerWidth / 2
like image 82
fixmycode Avatar answered Oct 28 '22 13:10

fixmycode