Кажется, <html>элемент похож на элемент псевдо окна или элемент контейнера представления? - PullRequest
1 голос
/ 09 января 2020

Если какая-либо веб-страница имеет высоту 3000px, я бы ожидал, что оба значения

document.body.offsetHeight
document.documentElement.offsetHeight

будут равны 3000px. Обратите внимание, что document.documentElement в точности совпадает с элементом <html>:

document.documentElement === document.querySelector("html")   // true

Однако document.documentElement.offsetHeight не является 3000px. Это просто 800px или 600px (как было проверено на текущей странице StackOverflow), и оно зависит только от того, насколько приблизительно окно области содержимого (или области просмотра) приблизительно равно.

На самом деле, document.documentElement.scrollTop изменяется при прокрутке веб-страницы. document.body.scrollTop остается 0 все время.

Это точно такое же поведение, как если бы существовал контейнер div из 200px × 200px, с overflow, установленным в auto или scroll, а затем содержимое div внутри контейнера div равно 2000px × 2000px. В этом случае контейнер div имеет небольшие значения clientHeight или offsetHeight (около 200px) и scrollTop изменяется при прокрутке содержимого вверх и вниз.

Так ли это изначально задумано быть? Может быть, в течение многих лет я думал, что элементы <html> и <body> имеют почти одно и то же: отображаемое пользователю содержимое одинаково (<head> не отображается), а их высота и ширина одинаковы, и это было ошибочным? Такое ощущение, что принцип дизайна в том, что <html> похож на контейнер представления или псевдоокно.

Даже CSS участвовал в этом:

getComputedStyle(document.documentElement)["height"]  // 600px or small number
getComputedStyle(document.body)["height"]             // 3000px

Но, возможно, одно странное поведение если я добавляю прослушиватель события прокрутки, я должен добавить его к document или window, но не к document.documentElement:

document.documentElement.addEventListener("scroll", ...  // won't work 

И он отличается, если это относится к 200px × 200px контейнер выше. Обработчик событий будет добавлен в этот контейнер 200px × 200px.

Пример, включающий document.documentElement.scrollTop и document.documentElement.scrollHeight (когда все прокручивается вверх, фон становится желтым):

document.addEventListener("scroll", ev => {
  // console.log(ev);
  document.body.style.background = document.documentElement.scrollTop + document.documentElement.clientHeight === document.documentElement.scrollHeight ? "yellow" : "white"; 
})
<div>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Dui sapien eget mi proin sed libero enim. Vel risus commodo viverra maecenas accumsan lacus vel. Magnis dis parturient montes nascetur. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Nullam non nisi est sit amet facilisis magna etiam. Porttitor leo a diam sollicitudin tempor id eu. Turpis egestas sed tempus urna et pharetra pharetra massa massa. Phasellus egestas tellus rutrum tellus pellentesque. Arcu odio ut sem nulla pharetra diam. Felis imperdiet proin fermentum leo vel orci. Id donec ultrices tincidunt arcu non. Egestas pretium aenean pharetra magna ac placerat. Amet risus nullam eget felis.

  Laoreet id donec ultrices tincidunt arcu non sodales neque. Dolor magna eget est lorem ipsum dolor. Interdum consectetur libero id faucibus nisl. Amet purus gravida quis blandit turpis cursus in hac habitasse. Ultrices gravida dictum fusce ut placerat. Tortor consequat id porta nibh venenatis cras sed felis. Sagittis eu volutpat odio facilisis mauris sit. Massa placerat duis ultricies lacus sed turpis tincidunt id aliquet. Vel quam elementum pulvinar etiam non quam lacus. Blandit turpis cursus in hac habitasse platea dictumst.

  Amet justo donec enim diam vulputate. Cursus mattis molestie a iaculis at. Massa massa ultricies mi quis hendrerit dolor. Est ultricies integer quis auctor elit. Id venenatis a condimentum vitae. Amet mauris commodo quis imperdiet. Pretium viverra suspendisse potenti nullam ac. Ultrices dui sapien eget mi. Mattis molestie a iaculis at erat pellentesque adipiscing. Commodo quis imperdiet massa tincidunt. Arcu non sodales neque sodales. Nibh tortor id aliquet lectus proin. Nam at lectus urna duis convallis convallis. Faucibus nisl tincidunt eget nullam non nisi.
</div>

Я получил очень разные результаты для следующих

console.log(document.body.offsetHeight);
console.log(document.documentElement.offsetHeight);

на текущей веб-странице StackOverflow (с помощью консоли разработчика Google Chrome) ). Но если я создаю очень длинный простой HTML файл и выполняю две вышеупомянутые строки в его <script> или в консоли разработчика, я получаю аналогичные числа для <body> и <html>. Поэтому я не понимаю, почему обычная страница и StackOverflow ведут себя по-разному. Кажется, <html> можно использовать как псевдоокно или не как одно.

Но внутри длинной простой страницы HTML, если я сделаю:

console.log(document.body.clientHeight);
console.log(document.documentElement.clientHeight); 

, я смог получить 2400px для и 680px для <html>. Похоже, что он все еще использует <html> в качестве псевдо-окна или контейнера для просмотра. Но я думал, что clientHeight и offsetHeight очень близки, но в offsetHeight включен только размер полосы прокрутки. Интересно, почему в этом случае они такие разные?

Пример:

console.log(document.body.clientHeight);
console.log(document.documentElement.clientHeight); 
body { font-size: 36px; }
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. At quis risus sed vulputate odio ut enim blandit. Dolor sed viverra ipsum nunc aliquet bibendum enim facilisis gravida. Sit amet purus gravida quis blandit. Et ultrices neque ornare aenean euismod elementum. Varius duis at consectetur lorem donec massa sapien faucibus et. In iaculis nunc sed augue. Platea dictumst quisque sagittis purus sit amet. Tortor at risus viverra adipiscing at in tellus. Mauris commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Rhoncus est pellentesque elit ullamcorper dignissim cras. Porttitor lacus luctus accumsan tortor posuere. Velit sed ullamcorper morbi tincidunt ornare massa eget egestas. Sed nisi lacus sed viverra tellus. Et ligula ullamcorper malesuada proin libero. Velit scelerisque in dictum non consectetur a erat nam. Non tellus orci ac auctor augue mauris augue neque gravida. Proin libero nunc consequat interdum varius sit. Hac habitasse platea dictumst quisque sagittis purus sit amet.

Dolor morbi non arcu risus. Elit duis tristique sollicitudin nibh sit amet commodo nulla. Tincidunt praesent semper feugiat nibh sed pulvinar. Amet consectetur adipiscing elit pellentesque habitant morbi tristique. Feugiat scelerisque varius morbi enim nunc faucibus a pellentesque sit. Lectus mauris ultrices eros in cursus turpis massa tincidunt dui. Sit amet nisl suscipit adipiscing. Amet nulla facilisi morbi tempus iaculis. Suspendisse sed nisi lacus sed viverra. Nullam ac tortor vitae purus. Risus quis varius quam quisque id diam vel quam. Enim ut sem viverra aliquet eget. Ridiculus mus mauris vitae ultricies leo integer malesuada nunc vel. Dictum varius duis at consectetur lorem donec massa. Eu feugiat pretium nibh ipsum consequat nisl vel. Amet risus nullam eget felis eget nunc lobortis. Egestas purus viverra accumsan in nisl.

Dignissim diam quis enim lobortis. Eget duis at tellus at urna condimentum mattis pellentesque. Eu nisl nunc mi ipsum faucibus vitae aliquet nec. Lectus urna duis convallis convallis tellus id interdum velit laoreet. Velit ut tortor pretium viverra suspendisse. Euismod in pellentesque massa placerat duis ultricies lacus sed turpis. Et sollicitudin ac orci phasellus egestas tellus rutrum tellus pellentesque. Id faucibus nisl tincidunt eget nullam non nisi est. Ut venenatis tellus in metus vulputate. Lectus proin nibh nisl condimentum. Bibendum at varius vel pharetra vel. Quam vulputate dignissim suspendisse in. Ut etiam sit amet nisl purus in mollis nunc. Blandit volutpat maecenas volutpat blandit aliquam etiam erat velit scelerisque.

Ac ut consequat semper viverra nam libero justo. Lacus vel facilisis volutpat est velit egestas. Amet aliquam id diam maecenas ultricies. Enim tortor at auctor urna. Magna etiam tempor orci eu. Sollicitudin tempor id eu nisl nunc mi ipsum. Etiam tempor orci eu lobortis elementum nibh tellus. Velit ut tortor pretium viverra suspendisse potenti nullam ac tortor. Nulla facilisi cras fermentum odio eu feugiat pretium nibh. Eu tincidunt tortor aliquam nulla facilisi cras fermentum. Proin libero nunc consequat interdum varius sit amet mattis. Semper risus in hendrerit gravida rutrum quisque non tellus orci. Risus nullam eget felis eget nunc lobortis.

Risus sed vulputate odio ut enim blandit volutpat maecenas volutpat. In nulla posuere sollicitudin aliquam. Sagittis nisl rhoncus mattis rhoncus urna neque viverra. Sit amet justo donec enim diam vulputate. Ut faucibus pulvinar elementum integer. Interdum posuere lorem ipsum dolor sit amet consectetur adipiscing elit. A condimentum vitae sapien pellentesque habitant morbi tristique. Vel fringilla est ullamcorper eget nulla facilisi. Vitae purus faucibus ornare suspendisse sed nisi lacus sed viverra. Aenean vel elit scelerisque mauris pellentesque pulvinar pellentesque. Ultricies integer quis auctor elit sed vulputate mi. Euismod quis viverra nibh cras pulvinar mattis. Sapien pellentesque habitant morbi tristique senectus et netus et malesuada. Mi tempus imperdiet nulla malesuada pellentesque elit eget.

Tincidunt augue interdum velit euismod in pellentesque massa placerat duis. Nam libero justo laoreet sit amet. Feugiat pretium nibh ipsum consequat nisl vel pretium lectus. Facilisi etiam dignissim diam quis enim. Augue lacus viverra vitae congue eu. Velit scelerisque in dictum non consectetur a erat nam. Amet purus gravida quis blandit turpis cursus in. Tortor pretium viverra suspendisse potenti nullam ac. Dolor sit amet consectetur adipiscing elit ut. Proin sed libero enim sed faucibus turpis in eu. Amet nulla facilisi morbi tempus iaculis urna id volutpat. Ut pharetra sit amet aliquam id diam maecenas ultricies mi. At in tellus integer feugiat. Vestibulum lectus mauris ultrices eros in cursus turpis massa. Dui nunc mattis enim ut tellus. Elit duis tristique sollicitudin nibh. Ac odio tempor orci dapibus ultrices in. Netus et malesuada fames ac turpis egestas sed. Quam lacus suspendisse faucibus interdum posuere lorem ipsum. A lacus vestibulum sed arcu non odio euismod lacinia.
</div>

Одна вещь, к которой мы также должны быть осторожны, это как указано в JavaScript Полное руководство, 6-е издание, с.395 и с.903, и в спецификациях clientWidth и clientHeight ведет себя по-разному, если он находится на элементе <html>, который должен давать ширину и высоту области просмотра, исключая любую полосу прокрутки . Поэтому, когда страница изучается, об этом нужно помнить.

Аналогично, есть даже такое исключение для scrollTop для <html>. Это прокрутка окна в таком случае. .

Я думаю, что один вывод пока, кажется, <html> как-то трактуется как псевдо-окно или область просмотра программно а как его свойства указаны в спецификации.

1 Ответ

2 голосов
/ 09 января 2020

Во-первых, если здесь, на странице Stack Overflow, вы получаете .offsetHeight и getComputedStyle()['height'] размером с область просмотра , то это потому, что есть правило, заявляющее html { height: 100%; }.

Без этого правила у вас будет тот же размер, что и у тела:

console.log( "height:auto" );
console.log( "offsetHeight", document.documentElement.offsetHeight );
document.documentElement.classList.add( "SO" );
console.log( "height:100%" );
console.log( "offsetHeight", document.documentElement.offsetHeight ); 
body {
  height: 1000vh;
}
html.SO {
  height: 100%;
}

Теперь для значений, связанных с прокруткой, элемент document.documentElement является де-факто document.scrollingElement на обычной веб-странице:

console.log( document.scrollingElement === document.documentElement );

, и это document.body в режиме причуд.

Учитывая этот особый статус, связанные с прокруткой значения scrollingElement фактически возвращает ноды root, в которых содержит блок , размеры установлены в размеры viewport на обычных веб-страницах.

...