Определить, есть ли на странице вертикальная полоса прокрутки?

121

Мне просто нужен простой JQ / JS, чтобы проверить, есть ли у текущей страницы / окна (а не конкретного элемента) вертикальную полосу прокрутки.

Поиск в Google дает мне вещи, которые кажутся слишком сложными только для этой базовой функции.

Как это может быть сделано?

лесистый
источник

Ответы:

98
$(document).ready(function() {
    // Check if body height is higher than window height :)
    if ($("body").height() > $(window).height()) {
        alert("Vertical Scrollbar! D:");
    }

    // Check if body width is higher than window width :)
    if ($("body").width() > $(window).width()) {
        alert("Horizontal Scrollbar! D:<");
    }
});
Тьяго Белем
источник
14
+1, но для точности это только проверяет, расширяется ли контент дальше области просмотра. Если overflowсвойство bodyустановлено hiddenгде-то в строке, это не сработает. Однако скрытая установка на корпусе встречается крайне редко.
Pekka
4
Это не работает, если высота тела соответствует высоте окна. В этом случае, если высота документа точно соответствует области просмотра, добавляется горизонтальная полоса прокрутки . Это заставит верт. полоса прокрутки, но высота документа / тела / окна такая же; он НЕ будет предупреждать о «вертикальной полосе прокрутки», даже если она есть.
Хватит клеветать на Монику Челлио
2
Просто подумал, что упомянул, что мне пришлось использовать $(document)вместо этого $("body"), это сработало для меня, когда body не было (у меня абсолютный позиционированный контейнер с соотношением сторон по ширине / высоте)
am_
1
У меня есть страница отчета в браузере Chrome, где она изначально отображает полосу прокрутки и исчезает в течение миллисекунд, что выглядит как поведение браузера, поскольку я не программировал его. Так что в моем случае эта функция всегда возвращает true ..
Даш
@TiuTalk для меня $ ("body"). Height () & $ (window) .height () дает то же значение, вместо этого я использую $ (document) .height ()> $ (window) .height (), он работает для меня.
SarangK
77

попробуй это:

var hasVScroll = document.body.scrollHeight > document.body.clientHeight;

Это только скажет вам, если вертикальный scrollHeight больше, чем высота просматриваемого контента. hasVScrollПеременная будет содержать истинное или ложное.

Если вам нужно выполнить более тщательную проверку, добавьте в приведенный выше код следующее:

// Get the computed style of the body element
var cStyle = document.body.currentStyle||window.getComputedStyle(document.body, "");

// Check the overflow and overflowY properties for "auto" and "visible" values
hasVScroll = cStyle.overflow == "visible" 
             || cStyle.overflowY == "visible"
             || (hasVScroll && cStyle.overflow == "auto")
             || (hasVScroll && cStyle.overflowY == "auto");
Энди Э
источник
1
+1 Приятно! И с необходимым вычислительным стилем (именно в этот момент я решил не связываться с этим вопросом;)
Пекка
lol, да, я спорил, стоит ли прилагать дополнительные усилия, чтобы написать это, потому что во многих случаях это не нужно.
Andy E
1
Это приводит к тому, что hasVScroll имеет значение true всякий раз, когда overflowY «видим», независимо от того, больше ли scrollHeight, чем clientHeight. Может ты имел ввиду cStyle.overflow === 'scroll'?
BT
5
Приведенный выше код не работает. Браузер: Chrome 56. URL: news.greylock.com/…
Sebastien Lorber
1
@BT cStyle.overflow == "visible" может отображать полосы прокрутки, когда элементом является document.body. Но должно быть (hasVScroll && cStyle.overflow == "visible" && element.nodeName == "BODY"). Кроме того, это необходимо проверить, cStyle.overflow === 'scroll'как вы указываете.
mseifert
44

Я попробовал предыдущий ответ и, похоже, не работает с $ ("body"). Height () не обязательно представляет всю высоту html.

Я исправил решение следующим образом:

// Check if body height is higher than window height :) 
if ($(document).height() > $(window).height()) { 
    alert("Vertical Scrollbar! D:"); 
} 

// Check if body width is higher than window width :) 
if ($(document).width() > $(window).width()) { 
    alert("Horizontal Scrollbar! D:<"); 
} 
Бхарат
источник
18

Давайте вернем этот вопрос из мертвых;) Есть причина, по которой Google не дает вам простого решения. Особые случаи и особенности браузера влияют на расчет, и это не так тривиально, как кажется.

К сожалению, пока есть проблемы с решениями, изложенными здесь. Я вовсе не хочу их принижать - они являются отличной отправной точкой и затрагивают все ключевые свойства, необходимые для более надежного подхода. Но я бы не рекомендовал копировать и вставлять код из любого другого ответа, потому что

  • они не улавливают эффект позиционирования контента надежным кроссбраузерным способом. В ответах, основанных на размере тела, это полностью отсутствует (тело не является родительским элементом смещения для такого содержимого, если оно не позиционируется само). И эти ответы проверяют $( document ).width()и .height()становятся жертвой ошибочного определения размера документа jQuery .
  • Если полагаться на него window.innerWidth, если браузер поддерживает это, ваш код не сможет обнаруживать полосы прокрутки в мобильных браузерах, где ширина полосы прокрутки обычно равна 0. Они просто временно отображаются как наложение и не занимают места в документе. , Масштабирование на мобильных устройствах также становится проблемой (долгая история).
  • Обнаружение можно скинуться , когда люди явно установить переполнение как htmlи bodyэлемент значений не по умолчанию (то , что происходит потом немного Приглашена - см это описание ).
  • В большинстве ответов внутренние отступы, границы или поля не обнаруживаются и искажают результаты.

Я потратил больше времени, чем мог бы себе представить, на поиск решения, которое «просто работает» (кашель). Алгоритм я придумал теперь является частью плагина, jQuery.isInView , который выставляет на .hasScrollbarметод . Если хотите, посмотрите исходник .

В сценарии, когда вы полностью контролируете страницу и не имеете дело с неизвестным CSS, использование плагина может быть излишним - в конце концов, вы знаете, какие крайние случаи применяются, а какие нет. Однако, если вам нужны надежные результаты в неизвестной среде, я не думаю, что описанных здесь решений будет достаточно. Лучше использовать проверенный плагин - мой или любой другой.

hashchange
источник
Спасибо. Довольно сложно! Если вы не хотите / не нуждаетесь в обратной совместимости, возможно, есть более простое решение для браузеров html5? Я имею в виду, что, возможно, кодеры браузера / w3c были достаточно хороши, чтобы просто сказать нам, есть ли полосы прокрутки или нет на элементе? ;-)
Лев
1
@Leo Я не знаю. Ну, есть window.scrollbarsобъект , который имеет одно свойство, visible. Звучит многообещающе, но это не так. Он не поддерживается в IE, включая IE11. И это просто говорит вам , что есть полоса прокрутки - но не один , который. См. Тестовую страницу здесь .
hashchange
Спасибо @hashchange. Звучит невероятно глупо, что он просто сообщает, есть ли полоса прокрутки, так что я предполагаю, что это всего лишь какой-то тест. Хотя немного многообещающе. ;-)
Leo
1
@BT Хорошо, отлично. А теперь позвольте мне провести вас ко входу в кроличью нору;) Вот демонстрация, в которой содержимого недостаточно, чтобы заполнить окно. Ваше обнаружение работает в FF, но не работает в Chrome. А вот еще одна демонстрация, в которой позиционированный элемент помещается далеко вниз по странице. Ваше обнаружение работает в Chrome, но не работает в FF.
hashchange
1
@BT И я думаю, мы можем попасть в кучу странных режимов отказа, когда начнем играть с настройками переполнения, потому что их поведение немного странное , но я остановился прямо здесь.
hashchange 05
15

Это сработало для меня:

function hasVerticalScroll(node){
    if(node == undefined){
        if(window.innerHeight){
            return document.body.offsetHeight> window.innerHeight;
        }
        else {
            return  document.documentElement.scrollHeight > 
                document.documentElement.offsetHeight ||
                document.body.scrollHeight>document.body.offsetHeight;
        }
    }
    else {
        return node.scrollHeight> node.offsetHeight;
    }
}

Для тела просто используйте hasVerticalScroll().

Кис К. Баккер
источник
Это единственный ответ в этой ветке, который работает на моем Chrome
Нертан Лучиан
clientHeightздесь предпочтительнее offsetHeight. В противном случае у вас может быть толстая граница и возврат, что нет полосы прокрутки, когда есть.
theicfire
12
var hasScrollbar = window.innerWidth > document.documentElement.clientWidth;
Роман Зайковский
источник
Это сработало, спасибо.
Vignesh Chinnaiyan
3

Как ни странно, ни одно из этих решений не сообщает вам, есть ли на странице вертикальная полоса прокрутки.

window.innerWidth - document.body.clientWidthдаст вам ширину полосы прокрутки. Это должно работать в любом IE9 + (не тестировалось в меньших браузерах). (Или, чтобы строго ответить на вопрос,!!(window.innerWidth - document.body.clientWidth)

Зачем? Допустим, у вас есть страница, содержимое которой выше, чем высота окна, и пользователь может прокручивать вверх / вниз. Если вы используете Chrome на Mac без подключенной мыши, пользователь не увидит полосу прокрутки. Подключите мышь, и появится полоса прокрутки. (Обратите внимание, что это поведение можно переопределить, но это AFAIK по умолчанию).

Дэвид Гилбертсон
источник
Объяснение поведения Chrome-Mouse помогло мне понять, что я считал непоследовательным поведением. Спасибо!
theisof
2

Я нашел ванильный раствор

var hasScrollbar = function() {
  // The Modern solution
  if (typeof window.innerWidth === 'number')
    return window.innerWidth > document.documentElement.clientWidth

  // rootElem for quirksmode
  var rootElem = document.documentElement || document.body

  // Check overflow style property on body for fauxscrollbars
  var overflowStyle

  if (typeof rootElem.currentStyle !== 'undefined')
    overflowStyle = rootElem.currentStyle.overflow

  overflowStyle = overflowStyle || window.getComputedStyle(rootElem, '').overflow

    // Also need to check the Y axis overflow
  var overflowYStyle

  if (typeof rootElem.currentStyle !== 'undefined')
    overflowYStyle = rootElem.currentStyle.overflowY

  overflowYStyle = overflowYStyle || window.getComputedStyle(rootElem, '').overflowY

  var contentOverflows = rootElem.scrollHeight > rootElem.clientHeight
  var overflowShown    = /^(visible|auto)$/.test(overflowStyle) || /^(visible|auto)$/.test(overflowYStyle)
  var alwaysShowScroll = overflowStyle === 'scroll' || overflowYStyle === 'scroll'

  return (contentOverflows && overflowShown) || (alwaysShowScroll)
}

Сергей Швагер
источник
1
Не работает в IE 11. window.innerWidth и document.documentElement.clientWidth всегда одинаковы.
NLV
Починил это. Эта же функция работает и в IE 11. Проблема заключалась в следующем - stackoverflow.com/questions/17045132/…
NLV,
Я тестировал это в Chrome 65, и он работает. Но когда я адаптирую его для горизонтальных полос прокрутки, результат получается странным: если отображаются и горизонтальная, и вертикальная полосы прокрутки, window.innerWidth > document.documentElement.clientWidthэто правда, но window.innerHeight > document.documentElement.clientHeightнет. Похоже, что в данном случае все было наоборот. Я не JS-разработчик, мне он нужен только для тестов Selenium. Благодарен за подсказки.
kriegaex
2
    <script>
    var scrollHeight = document.body.scrollHeight;
    var clientHeight = document.documentElement.clientHeight;
    var hasVerticalScrollbar = scrollHeight > clientHeight;

    alert(scrollHeight + " and " + clientHeight); //for checking / debugging.
    alert("hasVerticalScrollbar is " + hasVerticalScrollbar + "."); //for checking / debugging.
    </script>

Он скажет вам, есть ли у вас полоса прокрутки или нет. Я включил некоторую информацию, которая может помочь в отладке, которая будет отображаться как предупреждение JavaScript.

Поместите это в тег скрипта после закрывающего тега тела.

Дон Д.
источник
1

Я написал обновленную версию ответа Киса К. Баккера:

const hasVerticalScroll = (node) => {
  if (!node) {
    if (window.innerHeight) {
      return document.body.offsetHeight > window.innerHeight
    }
    return (document.documentElement.scrollHeight > document.documentElement.offsetHeight)
      || (document.body.scrollHeight > document.body.offsetHeight)
  }
  return node.scrollHeight > node.offsetHeight
}

if (hasVerticalScroll(document.querySelector('body'))) {
  this.props.handleDisableDownScrollerButton()
}

Функция возвращает true или false в зависимости от того, есть ли на странице вертикальная полоса прокрутки или нет.

Например:

const hasVScroll = hasVerticalScroll(document.querySelector('body'))

if (hasVScroll) {
  console.log('HAS SCROLL', hasVScroll)
}
agm1984
источник
1

я использую

public windowHasScroll()
{
    return document.body.clientHeight > document.documentElement.clientHeight;
}
амосс
источник
1

Просто сравните ширину корневого элемента документа (т.е. элемента html) с внутренней частью окна:

if ((window.innerWidth - document.documentElement.clientWidth) >0) console.log('V-scrollbar active')

Если вам также нужно знать ширину полосы прокрутки:

vScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
Бабак
источник
0

Другие решения не работали в одном из моих проектов, и я закончил проверку свойства переполнения css

function haveScrollbar() {
    var style = window.getComputedStyle(document.body);
    return style["overflow-y"] != "hidden";
}

но он будет работать только в том случае, если появится полоса прокрутки, исчезнет, ​​изменив опору, она не будет работать, если содержимое равно или меньше окна.

jcubic
источник