Wykryć, czy strona ma pionowy pasek przewijania?


121

Chcę tylko, aby jakiś prosty JQ / JS sprawdził, czy bieżąca strona / okno (a nie konkretny element) ma pionowy pasek przewijania.

Googlowanie daje mi rzeczy, które wydają się zbyt skomplikowane tylko w przypadku tej podstawowej funkcji.

Jak to zrobić?

Odpowiedzi:


97
$(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, ale ze względu na dokładność sprawdza tylko, czy treść rozszerza się dalej niż widoczny obszar. Jeśli overflowwłaściwość the bodyjest ustawiona hiddengdzieś wzdłuż linii, nie zadziała. Jednak ustawienie ukryte na ciele jest niezwykle rzadkie.
Pekka

4
Nie działa to, jeśli wysokość treści odpowiada wysokości okna, co ma miejsce, gdy wysokość dokumentu dokładnie odpowiada rzutni, a następnie dodawany jest poziomy pasek przewijania . To zmusi vert. pasek przewijania, ale wysokość dokumentu / treści / okna jest taka sama; NIE zaalarmuje "pionowego paska przewijania", nawet jeśli taki istnieje.
Przestań oczerniać Monikę Cellio

2
Pomyślałem, że wspomnę, że $(document)zamiast $("body")tego musiałem użyć , to działało dla mnie, gdy ciało nie działało (mam absolutnie ustawiony kontener ze współczynnikiem proporcji na szerokość / wysokość)
am_

1
Mam stronę raportu w przeglądarce Chrome, gdzie początkowo wyświetla pasek przewijania i znika w ciągu kilku milisekund, co wygląda jak zachowanie przeglądarki, ponieważ jej nie zaprogramowałem. Więc ta funkcja zawsze zwraca prawdę w moim przypadku ...
Dush,

@TiuTalk for me $ ("body"). Height () i $ (window) .height () daje tę samą wartość, zamiast tego używam $ (document) .height ()> $ (window) .height () to działa mnie.
SarangK

77

Spróbuj tego:

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

Dzięki temu dowiesz się tylko, czy wysokość przewijania w pionie jest większa niż wysokość widocznej zawartości. hasVScrollZmienna będzie zawierać prawdziwe, czy fałszywe.

Jeśli chcesz dokładniej sprawdzić, dodaj następujący kod do powyższego kodu:

// 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 Świetnie! I z koniecznym stylem obliczeniowym (w którym to momencie zdecydowałem się nie wplątywać w to pytanie;)
Pekka

lol tak, zastanawiałem się, czy włożyć dodatkowy wysiłek, aby to napisać, ponieważ w wielu przypadkach nie jest to potrzebne.
Andy E

1
Powoduje to, że hasVScroll ma wartość true, gdy overflowY jest „widoczne”, niezależnie od tego, czy scrollHeight jest większa niż clientHeight. Może miałeś na myśli cStyle.overflow === 'scroll'?
BT

5
Powyższy kod nie działa. Przeglądarka: Chrome 56. Url: news.greylock.com/…
Sebastien Lorber

1
@BT cStyle.overflow == "visible" może wyświetlać paski przewijania, gdy element jest document.body. Ale powinno być (hasVScroll && cStyle.overflow == "visible" && element.nodeName == "BODY"). Poza tym musi to sprawdzić, cStyle.overflow === 'scroll'jak wskazałeś.
mseifert

44

Wypróbowałem poprzednią odpowiedź i wygląda na to, że $ ("body") nie działa. Height () niekoniecznie reprezentuje całą wysokość html.

Poprawiłem rozwiązanie w następujący sposób:

// 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

Przywróćmy to pytanie z martwych;) Jest powód, dla którego Google nie daje prostego rozwiązania. Specjalne przypadki i dziwactwa przeglądarki wpływają na obliczenia i nie jest to tak banalne, jak się wydaje.

Niestety, pojawiają się problemy z przedstawionymi tutaj rozwiązaniami. Nie chcę ich wcale dyskredytować - są świetnymi punktami wyjścia i dotykają wszystkich kluczowych właściwości potrzebnych do bardziej solidnego podejścia. Ale nie polecałbym kopiowania i wklejania kodu z innych odpowiedzi, ponieważ

  • nie rejestrują efektu pozycjonowanej treści w sposób niezawodny dla różnych przeglądarek. Odpowiedzi oparte na rozmiarze ciała całkowicie to pomijają (treść nie jest przesuniętym elementem nadrzędnym takiej treści, chyba że jest pozycjonowana). A te odpowiedzi sprawdzają się $( document ).width()i .height()padają ofiarą błędnego wykrywania rozmiaru dokumentu przez jQuery .
  • Poleganie na window.innerWidth, jeśli przeglądarka to obsługuje, powoduje, że kod nie wykrywa pasków przewijania w przeglądarkach mobilnych, gdzie szerokość paska przewijania wynosi zwykle 0. Są one wyświetlane tylko tymczasowo jako nakładka i nie zajmują miejsca w dokumencie . Powiększanie na telefonie komórkowym również staje się w ten sposób problemem (długa historia).
  • Wykrywanie może zostać odrzucone, gdy ludzie jawnie ustawią przepełnienie zarówno elementu, jak htmli bodyna wartości inne niż domyślne (co się wtedy stanie jest trochę skomplikowane - zobacz ten opis ).
  • W większości odpowiedzi wypełnienie ciała, obramowanie lub marginesy nie są wykrywane i zniekształcają wyniki.

Spędziłem więcej czasu niż sobie wyobrażałem na znalezieniu rozwiązania, które „po prostu działa” (kaszel). Algorytm mam wymyślić jest teraz częścią wtyczki, jQuery.isInView , która naraża się .hasScrollbarmetodę . Jeśli chcesz, zajrzyj do źródła .

W scenariuszu, w którym masz pełną kontrolę nad stroną i nie musisz zajmować się nieznanym CSS, użycie wtyczki może być przesadą - w końcu wiesz, które przypadki skrajne mają zastosowanie, a które nie. Jeśli jednak potrzebujesz wiarygodnych wyników w nieznanym środowisku, to nie sądzę, aby przedstawione tutaj rozwiązania były wystarczające. Lepiej jest używać dobrze przetestowanej wtyczki - mojej lub kogoś innego.


Dzięki. Dość skomplikowane! Jeśli nie chcesz / nie musisz być kompatybilny wstecz, czy jest może łatwiejsze rozwiązanie dla przeglądarek HTML5? Chodzi mi o to, że być może kodery przeglądarki / w3c były na tyle miłe, aby po prostu powiedzieć nam, czy na elemencie są paski przewijania, czy nie? ;-)
Leo

1
@Leo Nie jestem tego świadomy. Cóż, nie jest to window.scrollbarsobiekt , który ma jedną właściwość, visible. Brzmi obiecująco, ale tak nie jest. Nie jest obsługiwany w IE, w tym w IE11. I to właśnie mówi, że tam jest pasek przewijania - ale nie których jeden. Zobacz stronę testową tutaj .
hashchange

Dzięki @hashchange. To brzmi niesamowicie głupio, że po prostu mówi, czy jest jakiś pasek przewijania, więc myślę, że to jeszcze jakiś test. Choć trochę obiecujące. ;-)
Leo

1
@BT Ok, świetnie. Teraz pozwól, że poprowadzę cię do wejścia do króliczej nory;) Oto demo, w którym zawartość nie wystarczy do wypełnienia okna. Twoje wykrywanie działa w FF, ale kończy się niepowodzeniem w Chrome. A oto kolejne demo, w którym pozycjonowany element jest umieszczony daleko w dół strony. Twoje wykrywanie działa w Chrome, ale kończy się niepowodzeniem w FF.
zmiana hash

1
@BT I wydaje mi się, że możemy dostać się do kilku dziwnych trybów awarii, kiedy zaczynamy bawić się ustawieniami przepełnienia, ponieważ ich zachowanie jest trochę dziwne , ale na tym się zatrzymałem.
zmiana hash

15

Ten zadziałał dla mnie:

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;
    }
}

Do ciała po prostu użyj hasVerticalScroll().


To jedyna odpowiedź w tym wątku, która działa na moim Chrome
Nertan Lucian

clientHeightjest lepsze offsetHeighttutaj. W przeciwnym razie możesz mieć grubą ramkę i wrócić, gdy jest, nie ma paska przewijania.
ogień


3

Co dziwne, żadne z tych rozwiązań nie informuje, czy strona ma pionowy pasek przewijania.

window.innerWidth - document.body.clientWidthpoda szerokość paska przewijania. To powinno działać w każdej przeglądarce IE9 + (nie testowane w mniejszych przeglądarkach). (Lub, aby ściśle odpowiedzieć na pytanie,!!(window.innerWidth - document.body.clientWidth)

Czemu? Załóżmy, że masz stronę, na której zawartość jest wyższa niż wysokość okna, a użytkownik może przewijać w górę / w dół. Jeśli używasz Chrome na komputerze Mac bez podłączonej myszy, użytkownik nie zobaczy paska przewijania. Podłącz mysz, a pojawi się pasek przewijania. (Zwróć uwagę, że to zachowanie można zastąpić, ale jest to domyślny AFAIK).


Wyjaśnienie zachowania Chrome-Mouse pomogło mi zorientować się, co uważam za niespójne zachowanie. Dzięki!
rozprawa z

2

Znalazłem rozwiązanie waniliowe

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
Nie działa w IE 11. window.innerWidth i document.documentElement.clientWidth są zawsze takie same.
NLV

Naprawione. Ta sama funkcja działa również w IE 11. Problem był następujący - stackoverflow.com/questions/17045132/ ...
NLV

Przetestowałem to w Chrome 65 i działa. Ale kiedy dostosuję go do poziomych pasków przewijania, wynik jest dziwny: jeśli są wyświetlane zarówno poziomy, jak i pionowy pasek przewijania, window.innerWidth > document.documentElement.clientWidthjest to prawda, ale window.innerHeight > document.documentElement.clientHeighttak nie jest. Wygląda na to, że w tym przypadku było odwrotnie. Nie jestem programistą JS, potrzebuję go tylko do testów Selenium. Jestem wdzięczny za podpowiedzi.
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>

Ten powie ci, czy masz pasek przewijania, czy nie. Dołączyłem kilka informacji, które mogą pomóc w debugowaniu, które będą wyświetlane jako alert JavaScript.

Umieść to w tagu script, po zamykającym tagu body.


1

Napisałem zaktualizowaną wersję odpowiedzi Keesa C. Bakkera:

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()
}

Funkcja zwraca prawdę lub fałsz w zależności od tego, czy strona ma pionowy pasek przewijania, czy nie.

Na przykład:

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

if (hasVScroll) {
  console.log('HAS SCROLL', hasVScroll)
}

1

używam

public windowHasScroll()
{
    return document.body.clientHeight > document.documentElement.clientHeight;
}

1

Wystarczy porównać szerokość elementu głównego dokumentu (tj. Elementu html) z wewnętrzną częścią okna:

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

Jeśli potrzebujesz również znać szerokość paska przewijania:

vScrollbarWidth = window.innerWidth - document.documentElement.clientWidth;

0

Inne rozwiązania nie działały w jednym z moich projektów i skończyło się sprawdzaniem właściwości overflow css

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

ale zadziała tylko wtedy, gdy pasek przewijania zniknie przez zmianę właściwości, nie zadziała, jeśli zawartość jest równa lub mniejsza niż okno.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.