Преобразование единиц vh в px в JS

К сожалению, 100vh не всегда совпадает с высотой браузера 100%, как показано в следующем примере.

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>

Проблема более заметна на iPhone 6+ из-за того, как верхняя панель местоположения и нижняя панель навигации расширяются и сжимаются при прокрутке, но не учитываются при расчете 100vh.

Фактическое значение высоты 100% можно получить, используя window.innerHeight в JS.

Есть ли удобный способ рассчитать текущее преобразование 100vh в пиксели в JS?

Я пытаюсь избежать создания фиктивных элементов со встроенными стилями только для вычисления 100vh.

Для целей этого вопроса предположим, что во враждебной среде max-width или max-height могут давать неверные значения, а на странице нет элемента с 100vh. По сути, предположим, что все, что может пойти не так, случилось, за исключением нативных функций браузера, которые гарантированно будут чистыми.

Лучшее, что я придумал до сих пор, это:

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;
}

но это кажется слишком подробным для вычисления текущего значения для 100vh, и я не уверен, есть ли с ним другие проблемы.


person zzzzBov    schedule 08.12.2015    source источник
comment
Почему вам все равно нужно получить эквивалент 100vh в пикселях?   -  person Charlie    schedule 12.07.2019


Ответы (2)


Как насчет:

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)
}

Применение:

viewportToPixels('100vh') // window.innerHeight
viewportToPixels('50vw') // window.innerWidth / 2
person fixmycode    schedule 08.12.2015
comment
Неправильно, innerHeight не 100vh на iOS output.jsbin.com/diwoyevive/quiet - person yckart; 30.05.2016
comment
@yckart вы правы, но может быть полезно решить эту проблему: medium.com/@susiekim9/ ; таким образом, заменив 100vh на innerHeight, это решение, используемое компонентом react-div-100vh - person Marcel Falliere; 13.03.2019

Разница заключается в полосе прокрутки полосы прокрутки.

Вам нужно будет добавить высоту полосы прокрутки к window.innerHeight. Кажется, не существует супер надежного способа сделать это по этому другому вопросу:

Получение ширины полосы прокрутки с помощью JavaScript

person Charlie    schedule 12.07.2019
comment
В дополнение к полосам прокрутки существует множество других функций браузера, из-за которых высота 100vh значительно отличается от высоты 100%. - person zzzzBov; 12.07.2019
comment
что еще там? - person Charlie; 12.07.2019
comment
Я рассмотрел пару в вопросе. В частности, местоположение iPhone и панели навигации, которые уменьшают высоту на 100%, но не влияют на 100vh. - person zzzzBov; 12.07.2019