Як визначити ширину та висоту вікна браузера? Як отримати повну ширину та висоту документа, включаючи прокручену частину? Як можна прокрутити сторінку за допомогою JavaScript?
Для цього ми можемо використовувати кореневий елемент документа document.documentElement
, який відповідає тегу <html>
. Але є додаткові методи та особливості, які слід враховувати.
Ширина/висота вікна
Щоб отримати ширину та висоту вікна, ми можемо використовувати clientWidth/clientHeight
із document.documentElement
:
Наприклад, ця кнопка показує висоту вашого вікна:
window.innerWidth/innerHeight
Браузери також підтримують властивості window.innerWidth/innerHeight
. Здається, це те, що нам потрібно, то чому б їх не використати?
Якщо є смуга прокрутки, і вона займає деякий простір, то властивості clientWidth/clientHeight
нададуть ширину/висоту без прокрутки (віднявши її). Інакше кажучи, вони повертають ширину/висоту видимої частини документа, доступної для вмісту.
window.innerWidth/innerHeight
включає смугу прокрутки.
Якщо є смуга прокрутки, і вона займає деякий простір, то ці два рядки покажуть різні значення:
alert( window.innerWidth ); // повна ширина вікна
alert( document.documentElement.clientWidth ); // ширина вікна мінус смуга прокрутки
У більшості випадків нам потрібна доступна ширина вікна, щоб намалювати або розташувати щось у межах смуг прокрутки (якщо такі є), тому ми повинні використовувати documentElement.clientHeight/clientWidth
.
DOCTYPE
важливийЗверніть увагу: геометричні властивості верхнього рівня можуть працювати дещо інакше, якщо в HTML немає <!DOCTYPE HTML>
. Можливі дивні речі.
У сучасному HTML ми завжди повинні прописувати DOCTYPE
.
Ширина/висота документа
Теоретично, оскільки кореневим елементом документа є document.documentElement
, і він охоплює весь вміст, ми можемо виміряти повний розмір документа як document.documentElement.scrollWidth/scrollHeight
.
Але для цього елемента для всієї сторінки ці властивості не працюють належним чином. У Chrome/Safari/Opera, якщо немає прокрутки, то documentElement.scrollHeight
може бути навіть меншим, ніж documentElement.clientHeight
! Дивно, правда?
Щоб надійно отримати повну висоту документа, ми повинні взяти максимум з цих властивостей:
let scrollHeight = Math.max(
document.body.scrollHeight, document.documentElement.scrollHeight,
document.body.offsetHeight, document.documentElement.offsetHeight,
document.body.clientHeight, document.documentElement.clientHeight
);
alert('Повна висота документа з прокрученою частиною: ' + scrollHeight);
Чому так? Краще не питати. Ці невідповідності походять із давніх часів, це не “логічно”.
Отримання поточної позиції прокрутки
Елементи DOM містять свій поточний стан прокрутки у властивостях scrollLeft/scrollTop
.
Стан прокрутки документа міститься в document.documentElement.scrollLeft/scrollTop
, та працює в більшості браузерів, за винятком старіших веб-переглядачів створених на WebKit, таких як Safari (помилка 5991), де ми повинні використовувати document.body
замість document.documentElement
.
На щастя, нам не потрібно пам’ятати про ці особливості, оскільки прокрутка доступна у спеціальних властивостях window.pageXOffset/pageYOffset
:
alert('Поточна прокрутка зверху: ' + window.pageYOffset);
alert('Поточна прокрутка зліва: ' + window.pageXOffset);
Ці властивості доступні лише для читання.
window
scrollX
та scrollY
З історичних причин обидві властивості існують, але вони однакові:
window.pageXOffset
є псевдонімомwindow.scrollX
.window.pageYOffset
є псевдонімомwindow.scrollY
.
Прокрутка: scrollTo, scrollBy, scrollIntoView
Щоб прокручувати сторінку за допомогою JavaScript, її DOM має бути повністю створено.
Наприклад, якщо ми спробуємо прокрутити сторінку за допомогою сценарію в <head>
, це не спрацює.
Звичайні елементи можна прокручувати, змінюючи scrollTop/scrollLeft
.
Ми можемо зробити те ж саме для сторінки, використовуючи document.documentElement.scrollTop/scrollLeft
(крім Safari, де замість цього слід використовувати document.body.scrollTop/Left
).
Крім того, є більш просте та універсальне рішення: спеціальні методи window.scrollBy(x,y) і window.scrollTo(pageX,pageY).
-
Метод
scrollBy(x,y)
прокручує сторінку відносно її поточної позиції. Наприклад,scrollBy(0,10)
прокручує сторінку на10px
вниз.Кнопка нижче це демонструє:
-
Метод
scrollTo(pageX,pageY)
прокручує сторінку до абсолютних координат, так що верхній лівий кут видимої частини має координати(pageX, pageY)
відносно верхнього лівого кута документа. Це те ж саме, що призначитиscrollLeft/scrollTop
.Щоб прокрутити до самого початку, ми можемо використовувати
scrollTo(0,0)
.
Ці методи працюють для всіх браузерів однаково.
scrollIntoView
Для повноти розглянемо ще один метод: elem.scrollIntoView(top).
Виклик elem.scrollIntoView(top)
прокручує сторінку таким чином, щоб зробити elem
видимим. Він має один аргумент:
- Якщо
top=true
(це значення за замовчуванням), то сторінка буде прокручена так, щобelem
з’явився у верхній частині вікна. Верхній край елемента буде вирівняний з верхньою частиною вікна. - Якщо
top=false
, то сторінка прокручується так, щобelem
з’явився внизу. Нижній край елемента буде вирівняний з нижньою частиною вікна.
Кнопка нижче прокручує сторінку, щоб розмістити себе у верхній частині вікна:
А ця кнопка прокручує сторінку, щоб розмістити себе у нижній частині вікна:
Заборона прокручування
Іноді нам потрібно зробити документ «непрокручуваним». Наприклад, коли нам потрібно закрити сторінку великим повідомленням, яке вимагає негайної уваги, і ми хочемо, щоб відвідувач взаємодіяв з цим повідомленням, а не з документом.
Щоб зробити документ недоступним для прокручування, достатньо встановити document.body.style.overflow = "hidden"
. Сторінка «завмере» у поточній позиції прокручування.
Спробуй:
Перша кнопка зупиняє прокрутку, а друга відновлює.
Ми можемо використовувати ту саму техніку, щоб заморозити прокрутку для інших елементів, а не лише для document.body
.
Недоліком цього методу є те, що смуга прокрутки зникає. Якщо вона займала деякий простір, то це місце звільняється, і вміст «стрибає», щоб заповнити його.
Це виглядає трохи дивно, але це можна обійти, якщо порівняти clientWidth
до і після заборони прокручування. Якщо ширина збільшилась (смуга прокрутки зникла), додайте padding
до document.body
замість смуги прокрутки, щоб зберегти ширину вмісту такою ж.
Підсумки
Геометрія:
-
Ширина/висота видимої частини документа (ширина/висота області вмісту):
document.documentElement.clientWidth/clientHeight
-
Ширина/висота всього документа з прокрученою частиною:
let scrollHeight = Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight );
Прокрутка:
-
Прочитати поточну прокрутку:
window.pageYOffset/pageXOffset
. -
Змінити поточну прокрутку:
window.scrollTo(pageX,pageY)
– абсолютні координати,window.scrollBy(x,y)
– прокрутити відносно поточного місця,elem.scrollIntoView(top)
– прокрутити, щоб зробитиelem
видимим (вирівняти з верхньою/нижньою частиною вікна).
Коментарі
<code>
, для кількох рядків – обгорніть їх тегом<pre>
, для понад 10 рядків – використовуйте пісочницю (plnkr, jsbin, codepen…)