Разница между offsetHeight и clientHeight

В javascript dom - в чем разница между offsetHeight и clientHeight элемента?

4 ответа

clientHeight:

Возвращает высоту видимой области для объекта в пикселях. Значение содержит высоту с отступом, но не включает scrollBar, border и margin.

offsetHeight:

Возвращает высоту видимой области для объекта в пикселях. Значение содержит высоту с отступом, полосой прокрутки и границей, но не включает поле.

Так, offsetHeight включает полосу прокрутки и границу, clientHeight не делает.

Ответ от Одеда - теория. Но теория и реальность не всегда одинаковы, по крайней мере, не для элементов или , которые могут быть важны для операций прокрутки в javascript.

У Microsoft хорошая картинка в MSDN:

ClientHeight, OffsetHeight, ScrollHeight

Если у вас есть HTML-страница, на которой показана вертикальная полоса прокрутки, можно ожидать, что элемент или имеет элемент ScrollHeight, а не OffsetHeight, как показано на этом изображении. Это верно для всех старых версий Internet Explorer.

Но это не так для Internet Explorer 11 и не для Firefox 36. По крайней мере, в этих браузерах OffsetHeight почти такой же, как ScrollHeight, что неправильно.

И хотя OffsetHeight может быть неправильным, ClientHeight всегда корректен.

Попробуйте следующий код в разных браузерах, и вы увидите:

<!DOCTYPE html>
<html>
<body>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<script>
    document.write("Body off: " + document.body.offsetHeight 
             + "<br>Body cli: " + document.body.clientHeight
             + "<br>Html off: " + document.body.parentElement.offsetHeight               
             + "<br>Html cli: " + document.body.parentElement.clientHeight);
</script>
</body>
</html>

В то время как старый Internet Explorer показывает правильно:

Body off: 1197
Body cli: 1197
Html off: 878
Html cli: 874  

Вывод из Firefox и Internet Explorer 11:

Body off: 1260
Body cli: 1260
Html off: 1276   // this is completely wrong
Html cli: 889

который ясно показывает, что offsetHeight здесь не так. OffsetHeight и ClientHeight должны отличаться только на несколько пикселей или быть одинаковыми.


Обратите внимание, что ClientHeight и OffsetHeight также могут сильно отличаться для элементов, которые не видны, например,

, где OffsetHeight может быть реальным размером FORM, а ClientHeight может быть нулевым.

clientHeight = высота элемента + отступ по вертикали.

offsetHeight = высота элемента + вертикальный отступ + верхняя и нижняя границы + горизонтальная полоса прокрутки (если она доступна).

Добавить еще :

scrollHeight = высота содержимого элемента (включая содержимое, которое не отображается на экране) + вертикальный отступ.

кодовый ключ

Порядок расположения элементов от внутреннего к внешнему: [(содержимое → отступы) → полоса прокрутки → граница] → поле.

(..) область относится к области, называемой client, а область [..] относится к offset.

Маржа считается вне элементов и никогда не участвует в каком-либо API макета JS.


Исчерпывающий список JS API для получения макета элемента:

  • Для Element класс (включая элементы HTML и элементы svg):

    • getBoundingClientRect().{left,top,right,bottom,x,y,width,height}

    • client{Height,Width,Left,Top}

    • scroll{Height,Width,Left,Top,LeftMax,TopMax}

  • Для HTMLElement класс (не включать элементы svg): offset{Height,Width,Left,Top}.

  • для window объект: scroll{X,Y}, page{X,Y}Offset, inner{Height,Width}, outer{Height,Width}, screen{Left,X,Top,Y}.

  • для screen объект: avail{Top,Left,Height,Width}, height, width, left, top.


Поскольку корневой элемент не может получить полосу прокрутки (полоса прокрутки браузера остается за границей корневого элемента). См. .

Согласно спецификациям, есть специальные определения для а также Codepenscroll{Left,Top}client{Height,Width} когда элемент является корневым элементом.


client* и т.п. игнорировать преобразования и округлять значение до целого числа, в то время как getClientRects()/ getClientBoundingRect() задействовать преобразование и вернуть плавающее значение.

Есть много других аспектов , которые не могут поместиться этим ответом, поэтому я кратко и сделал запись в блоге здесь .

Другие вопросы по тегам