Как определить, есть ли полосы прокрутки в окне браузера?

Мне нужно иметь возможность определить, есть ли полосы прокрутки (как вертикальные, так и горизонтальные) в окне браузера. Я использовал этот код, но он не работает надежно в Firefox 5.

JFL.GetScrollbarState = function () {
    var myWidth = 0;
    var myHeight = 0;
    if (document.documentElement && document.documentElement.clientWidth) {
        myWidth = document.documentElement.clientWidth;
        myHeight = document.documentElement.clientHeight;
    } else {
        myWidth = document.body.clientWidth;
        myHeight = document.body.clientHeight;
    }
    return ({
        vScrollbar: document.body.scrollHeight > myHeight,
        hScrollbar: document.body.scrollWidth > myWidth
    });
}

Есть ли лучший способ сделать это, который будет работать в кросс-браузере. Мои цели браузера: Firefox 4-5, Chrome, Safari 4+, Opera 10+.

Если вам интересно, зачем мне знать, есть ли полосы прокрутки, это потому, что у меня есть вращающиеся переходы CSS3, которые (из-за характера их вращения) могут временно выходить за границы текущего размера документа (таким образом делая документ временно больше). Если изначально полосы прокрутки не присутствовали, переход CSS3 может привести к тому, что полосы прокрутки появятся во время перехода, а затем исчезнут, когда переход завершится, что приведет к уродливому миганию полосы прокрутки. Если я знаю, что полос прокрутки нет, я могу временно добавить класс, который сделает overflow-x или overflow-y скрытыми и, таким образом, предотвратит мигание полосы прокрутки во время перехода CSS3. Если полосы прокрутки уже присутствуют, мне не нужно ничего делать, потому что они могут немного двигаться, но они не будут включаться/выключаться во время перехода.

Бонусные баллы, если можно на самом деле сказать не только, нужны ли вообще полосы прокрутки, но и есть ли они на самом деле или нет.


person jfriend00    schedule 07.07.2011    source источник
comment
Вы пробовали offsetHeight вместо clientHeight?   -  person dpp    schedule 07.07.2011


Ответы (3)


Столкнувшись с проблемами мерцания с версией прокрутки, предложенной Дэвидом в некоторых браузерах (Safari и IE), я остановился на этом коде, в котором нет проблемы мерцания:

function getScrollBarState() {
    var result = {vScrollbar: true, hScrollbar: true};
    try {
        var root = document.compatMode=='BackCompat'? document.body : document.documentElement;
        result.vScrollbar = root.scrollHeight > root.clientHeight;
        result.hScrollbar = root.scrollWidth > root.clientWidth;
    } catch(e) {}
    return(result);
}

Это производная от того, что я использовал, и общая техника была упомянута в посте, опубликованном fanfavorite. Кажется, он работает во всех браузерах, которые я пробовал, даже в IE6. Для моих целей я хотел, чтобы любой сбой возвращал наличие полосы прокрутки, поэтому я закодировал условие сбоя таким образом.

Примечание. Этот код не определяет, была ли полоса прокрутки принудительно включена или выключена с помощью CSS. Этот код определяет, вызывается ли полоса автопрокрутки или нет. Если на вашей странице могут быть настройки CSS, управляющие полосой прокрутки, вы можете сначала получить CSS и проверить его.

person jfriend00    schedule 10.07.2011
comment
Я нашел несколько случаев, когда это не работает. В Chrome 15 есть несколько странных макетов, где document.documentElement намного больше, чем document.body, вызывая полосу прокрутки, и этот код смотрит только на document.body. Итак, я снова ищу решение общего назначения, которое работает везде. - person jfriend00; 30.11.2011
comment
Этот код не определяет наличие полосы прокрутки. Полоса прокрутки может быть явно установлена: body { overflow: scroll; } или явно скрыта body { overflow: hidden; }, и в этом случае ваш код сообщает о ложном положительном/отрицательном результате... - person Šime Vidas; 28.03.2012
comment
@ŠimeVidas — этот код не пытается определить, установлена ​​ли полоса прокрутки вручную. Если это так или возможно в вашем случае, просто получите CSS и сначала проверьте его. Этот код пытается определить, есть ли триггер размера для автоматической полосы прокрутки или нет. Если у вас есть лучший способ, пожалуйста, не стесняйтесь публиковать его. - person jfriend00; 29.03.2012
comment
Я обнаружил, что вертикальную полосу прокрутки можно обнаружить, оценив выражение window.innerWidth - document.documentElement.clientWidth - если полоса прокрутки присутствует, значение будет 17, иначе будет 0. Однако window.innerWidth не реализовано в IE7/8, и, похоже, нет никакого способа получить это значение в этих двух браузерах... :( - person Šime Vidas; 29.03.2012
comment
@ŠimeVidas - если вы явно установили, что полоса прокрутки всегда включена в вашем CSS, то ваше javascript-определение того, включена ли полоса прокрутки, становится еще проще: if (true){ /* of course it's on...you set it that way! */ } :) - person Jimbo Jonny; 15.10.2012

Вы смотрели на этот другой пост? Как определить наличие полосы прокрутки ( используя Javascript ) в HTML iFrame?

person fanfavorite    schedule 07.07.2011

На самом деле это довольно легко. Это будет работать в каждом современном браузере:

// try scrolling by 1 both vertically and horizontally
window.scrollTo(1,1);

// did we move vertically?
if (window.pageYOffset != 0) {
 console.log("houston, we have vertical scrollbars");
}

// did we move horizontally?
if (window.pageXOffset != 0) {
 console.log("houston, we have horizontal scrollbars");
}

// reset window to default scroll state
window.scrollTo(0,0);
person David Titarenco    schedule 07.07.2011
comment
Хороший! Мне пришлось адаптировать его на случай, если окно уже было прокручено, чтобы сохранить текущую позицию прокрутки и прокрутить ее на один пиксель. Я знаю, что не просил что-то, что работает в IE, но для других читателей это работает в IE9 и не работает в IE6 (я не пробовал IE7 и IE8). - person jfriend00; 07.07.2011
comment
jsFiddle, который я использовал для тестирования в разных местах: jsfiddle.net/jfriend00/4NhUQ - person jfriend00; 07.07.2011
comment
К вашему сведению, я искал, как заставить это работать во всех браузерах (просто из-за полноты), но оказалось, что этот метод никогда не будет работать в IE6, потому что IE6 будет прокручивать документ с помощью scrollTo или scrollBy, даже если прокрутки нет полосы, поэтому этот метод всегда думает, что в IE6 есть полосы прокрутки. - person jfriend00; 07.07.2011
comment
Да, этот метод не будет работать ни в одном IE старше v9. Я не думаю, что это возможно сделать в более старых версиях IE вообще. - person David Titarenco; 07.07.2011
comment
Итак, получается, что у этой техники есть проблема в Safari. Последовательность window.scrollTo(1,1) и window.scrollTo(0,0) приводит к фактическому перемещению окна в Safari. Я не обнаруживаю движения в других браузерах, но оно движется в Safari. Это проблема, так как я не хочу, чтобы содержимое окна дрожало каждый раз, когда я спрашиваю, есть ли полоса прокрутки. Я вернулся к эпицентру в поисках хорошей техники. Дерьмо. Я хотел бы отменить принятый ответ, но SO не позволит мне. - person jfriend00; 10.07.2011
comment
Этот метод также имеет проблему, если окно не прокручивается вверх. - person jfriend00; 10.07.2011