2016-03-11 7 views
19

Ich habe diese Situation, in der ich ein Element in das Ansichtsfenster scrollen muss. Das Problem ist, dass ich nicht weiß, welches Element scrollbar ist. In Portrait ist der Körper zum Beispiel scrollbar und in Landscape ist ein anderes Element (und es gibt mehr Situationen, die das scrollbare Element verändern)Suchen erste rollbare Eltern

Jetzt ist die Frage, ein Element, das in den Viewport gescrollt werden muss, was ist der beste Weg, um seinen ersten scrollbaren Elternteil zu finden?

Ich habe eine Demo here eingerichtet. Mit der Taste können Sie zwischen zwei verschiedenen Situationen wechseln

<div class="outer"> 
    <div class="inner"> 
     <div class="content"> 
      ... 
      <span>Scroll me into view</span> 
     </div> 
    </div> 
</div> 

Der Körper scrollbaren oder .outer

Irgendwelche Vorschläge?

Antwort

22

Überprüfen Sie einfach, ob die Scrollbar sichtbar ist, wenn nicht auf die Eltern suchen.

function getScrollParent(node) { 
    if (node == null) { 
    return null; 
    } 

    if (node.scrollHeight > node.clientHeight) { 
    return node; 
    } else { 
    return getScrollParent(node.parentNode); 
    } 
} 
+0

Wenn der Knoten ein 'inline' Elternteil hat,' clientHeight' 0 sein wird, und es wird zurückgegeben Hier. Besser zu ignorieren Knoten mit 'clientHeight' von 0. –

+2

Das ist schön, aber funktioniert nicht für Knoten, die nach wie vor überfüllt sind, kann aber nicht bewegen. Wenn Sie eine Überprüfung für den Wert [overflowY] hinzufügen (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Determine_if_an_element_has_been_totally_scrolled), scheint es gut zu funktionieren. 'lassen overflowY = window.getComputedStyle (Knoten) .overflowY;' ' lassen isScrollable = overflowY == 'sichtbar' && overflowY == 'versteckt';!' ' if (isScrollable && node.scrollHeight> node.clientHeight) {' – RustyToms

+0

Laut @RustyToms und OP, schreibe ich diesen um: https://gist.github.com/twxia/bb20843c495a49644be6ea3804c0d775 – twxia

1

Ich denke, dass Sie das wollen.

$('button').click(function() { 
 
    $("body").addClass("body"); 
 
    $('.outer').toggleClass('scroller'); 
 
    check($(".content")); 
 
}); 
 

 
function check(el) { 
 
    var overflowY = el.css("overflow-y"); 
 
    if (overflowY == "scroll") { 
 
    alert(el.attr("class") + " has"); 
 
    } else { 
 
    if(el.parent().length > 0) 
 
    \t check(el.parent()); 
 
    else 
 
     return false; 
 
    } 
 
}
body { 
 
    height: 450px; 
 
    overflow-y: scroll; 
 
} 
 

 
div.inner { 
 
    width: 200px; 
 
    height: 400px; 
 
    border: 1px solid #000; 
 
} 
 

 
div.outer { 
 
    width: 200px; 
 
    height: 200px; 
 
} 
 

 
div.outer.scroller { 
 
    overflow-y: scroll; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<button> 
 
    toggle 
 
</button> 
 
<div class="outer"> 
 
    <div class="inner"> 
 
    <div class="content"> 
 
     "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor 
 
     in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." adipiscing elit, sed do eiusmod tempor incididunt ut 
 
     labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur 
 
     sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum." 
 
    </div> 
 
    </div> 
 
</div>

8

Wenn Sie jQuery UI verwenden, können Sie die scrollParent Methode verwenden. Schauen Sie sich die API oder die source an.

Von der API:

.scrollParent(): die nächste Vorfahrenelement erhalten, die

Diese Methode keine Argumente akzeptiert keine scrollbaren ist. Diese Methode findet den nächsten Vorfahren, der Scrollen erlaubt. Mit anderen Worten, die .scrollParent() Methode findet das Element, das das aktuell ausgewählte Element innerhalb von scrollen wird.

Hinweis: Diese Methode funktioniert nur bei jQuery-Objekten, die ein Element enthalten.

Wenn Sie nicht jQuery UI verwenden, aber jQuery verwenden, dann gibt es alternative unabhängige Bibliotheken ähnliche Funktionalität bereitstellt, wie zum Beispiel:

jquery-scrollparent

+1

Ich portierte dies zu Vanille JS hier: http://Stackoverflow.com/questions/35939886/ find-first-scrollable-parent # 42543908 –

16

Dies ist ein reiner JS-Port des jQuery UI scrollParent Methode, die cweston spoke of. Ich ging mit dieser Lösung und nicht mit der Lösung der akzeptierten Antwort, die das Scroll-Elternelement nicht findet, wenn noch kein Inhaltsüberlauf vorhanden ist.

Der einzige Unterschied mit meinem Port ist, dass, wenn kein Elternteil mit dem richtigen Wert für die CSS overflow Eigenschaft gefunden wird, ich das <body> Element zurückgeben. JQuery UI gab stattdessen das Objekt document zurück. Dies ist ungerade, da Werte wie .scrollTop aus der <body>, nicht aber der document abgerufen werden können.

function getScrollParent(element, includeHidden) { 
    var style = getComputedStyle(element); 
    var excludeStaticParent = style.position === "absolute"; 
    var overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/; 

    if (style.position === "fixed") return document.body; 
    for (var parent = element; (parent = parent.parentElement);) { 
     style = getComputedStyle(parent); 
     if (excludeStaticParent && style.position === "static") { 
      continue; 
     } 
     if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) return parent; 
    } 

    return document.body; 
} 
0

die Antwort mit den meisten Stimmen funktionieren nicht in allen Fällen scrollHeight > clientHeight die true selbst sein kann, wenn keine Scrollbar haben, fand ich diesen Kern Lösung https://github.com/olahol/scrollparent.js/blob/master/scrollparent.js#L13

^Gesamt-Credit von https://github.com/olahol wer hat den Code geschrieben?

ich Refactoring es es6:

export const getScrollParent = (node) => { 
    const regex = /(auto|scroll)/; 
    const parents = (_node, ps) => { 
    if (_node.parentNode === null) { return ps; } 
    return parents(_node.parentNode, ps.concat([_node])); 
    }; 

    const style = (_node, prop) => getComputedStyle(_node, null).getPropertyValue(prop); 
    const overflow = _node => style(_node, 'overflow') + style(_node, 'overflow-y') + style(_node, 'overflow-x'); 
    const scroll = _node => regex.test(overflow(_node)); 

    /* eslint-disable consistent-return */ 
    const scrollParent = (_node) => { 
    if (!(_node instanceof HTMLElement || _node instanceof SVGElement)) { 
     return; 
    } 

    const ps = parents(_node.parentNode, []); 

    for (let i = 0; i < ps.length; i += 1) { 
     if (scroll(ps[i])) { 
     return ps[i]; 
     } 
    } 

    return document.scrollingElement || document.documentElement; 
    }; 

    return scrollParent(node); 
    /* eslint-enable consistent-return */ 
}; 

Sie können es gerne verwenden:

const $yourElement = document.querySelector('.your-class-or-selector'); 
getScrollParent($yourElement); 
Verwandte Themen