web-dev-qa-db-de.com

Prüfen Sie, ob der Inhalt eines Elements überläuft.

Wie lässt sich am einfachsten erkennen, ob ein Element übergelaufen ist?

Mein Anwendungsfall ist, ich möchte ein bestimmtes Inhaltsfeld auf eine Höhe von 300px beschränken. Wenn der innere Inhalt höher ist, schneide ich ihn mit einem Überlauf ab. Wenn es jedoch überläuft, möchte ich eine Schaltfläche "Mehr" anzeigen, aber wenn nicht, möchte ich diese Schaltfläche nicht anzeigen.

Gibt es eine einfache Möglichkeit, Überlauf zu erkennen, oder gibt es eine bessere Methode?

92
Harry

Diese Funktion gibt Ihren booleschen Wert zurück, wenn das DOM-Element überläuft:

function isOverflown(element) {
    return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}

Das Element kann vertikal oder horizontal oder beide überlaufen

136
micnic

Wenn Sie nur einen Bezeichner für mehr Inhalt anzeigen möchten, können Sie dies mit reinem CSS tun. Ich verwende dafür reine Scrolling-Schatten. Der Trick ist die Verwendung von background-attachment: local;. Ihre CSS sieht so aus:

.scrollbox {
  overflow: auto;
  width: 200px;
  max-height: 200px;
  margin: 50px auto;

  background:
    /* Shadow covers */
    linear-gradient(white 30%, rgba(255,255,255,0)),
    linear-gradient(rgba(255,255,255,0), white 70%) 0 100%,

    /* Shadows */
    radial-gradient(50% 0, farthest-side, rgba(0,0,0,.2), rgba(0,0,0,0)),
    radial-gradient(50% 100%,farthest-side, rgba(0,0,0,.2), rgba(0,0,0,0)) 0 100%;
  background:
    /* Shadow covers */
    linear-gradient(white 30%, rgba(255,255,255,0)),
    linear-gradient(rgba(255,255,255,0), white 70%) 0 100%,

    /* Shadows */
    radial-gradient(farthest-side at 50% 0, rgba(0,0,0,.2), rgba(0,0,0,0)),
    radial-gradient(farthest-side at 50% 100%, rgba(0,0,0,.2), rgba(0,0,0,0)) 0 100%;
  background-repeat: no-repeat;
  background-color: white;
  background-size: 100% 40px, 100% 40px, 100% 14px, 100% 14px;

  /* Opera doesn't support this in the shorthand */
  background-attachment: local, local, scroll, scroll;
}

Den Code und ein Beispiel finden Sie auf http://dabblet.com/Gist/2462915

Eine Erklärung finden Sie hier: http://lea.verou.me/2012/04/background-attachment-local/ .

30
RWAM

Der Vergleich von element.scrollHeight mit element.clientHeight sollte die Aufgabe erfüllen.

Nachfolgend sind die Bilder von MDN aufgeführt, die Element.scrollHeight und Element.clientHeight erläutern.

 Scroll Height

 Client Height

9
Bergi

Würde so etwas wie: http://jsfiddle.net/Skooljester/jWRRA/1/ funktionieren? Es prüft nur die Höhe des Inhalts und vergleicht sie mit der Höhe des Containers. Wenn es größer ist, können Sie den Code einfügen, um eine Schaltfläche "Mehr anzeigen" anzufügen.

Update: Fügte den Code hinzu, um eine Schaltfläche "Mehr anzeigen" oben im Container zu erstellen.

4
jezza-tan

Wenn Sie jQuery verwenden, versuchen Sie möglicherweise einen Trick: Machen Sie ein äußeres div mit overflow: hiddenund ein inneres div mit Inhalt. Verwenden Sie dann die Funktion .height(), um zu überprüfen, ob die Höhe des inneren Bereichs größer ist als die Höhe des äußeren Bereichs. Ich bin nicht sicher, ob es funktioniert, aber probieren Sie es aus.

3
TMS

Ich erstellte ein mehrteiliges Codepen, um die obigen Antworten zu demonstrieren (z. B. mit ausgeblendetem Überlauf und Höhe), aber auch, wie Sie übergelaufene Elemente erweitern/reduzieren

Beispiel 1: https://codepen.io/Kagerjay/pen/rraKLB (Wirklich einfaches Beispiel, kein Javascript, nur um übergelaufene Artikel zu schneiden)

Beispiel 2: https://codepen.io/Kagerjay/pen/LBErJL (Einzelner Event-Handler zeigt mehr/showless bei übergelaufenen Elementen)

Beispiel 3: https://codepen.io/Kagerjay/pen/MBYBoJ (Multi-Event-Handler für viele zeigen mehr bzw. weniger für übergelaufene Elemente)

Ich habe als Beispiel 3 beigefügt, ich verwende Jade/Mops, so dass es ein bisschen verbose sein könnte. Ich schlage vor, die Codepens auszuprobieren, die ich einfacher zu verstehen habe.

// Overflow boolean checker
function isOverflown(element){
  return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}

// Jquery Toggle Text Plugin
$.fn.toggleText = function(t1, t2){
  if (this.text() == t1) this.text(t2);
  else                   this.text(t1);
  return this;
};

// Toggle Overflow
function toggleOverflow(e){
  e.target.parentElement.classList.toggle("grid-parent--showall");
  $(e.target).toggleText("Show More", "Show LESS");
}

// Where stuff happens
var parents = document.querySelectorAll(".grid-parent");

parents.forEach(parent => {
  if(isOverflown(parent)){
    parent.lastElementChild.classList.add("btn-show");
    parent.lastElementChild.addEventListener('click', toggleOverflow);
  }
})
body {
  background-color: #EEF0ED;
  margin-bottom: 300px;
}

.grid-parent {
  margin: 20px;
  width: 250px;
  background-color: lightgrey;
  display: flex;
  flex-wrap: wrap;
  overflow: hidden;
  max-height: 100px;
  position: relative;
}
.grid-parent--showall {
  max-height: none;
}

.grid-item {
  background-color: blue;
  width: 50px;
  height: 50px;
  box-sizing: border-box;
  border: 1px solid red;
}
.grid-item:nth-of-type(even) {
  background-color: lightblue;
}

.btn-expand {
  display: none;
  z-index: 3;
  position: absolute;
  right: 0px;
  bottom: 0px;
  padding: 3px;
  background-color: red;
  color: white;
}

.btn-show {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section>
  <p>Any grid-parent over 10 child items has a "SHOW MORE" button to expand</p>
  <p>Click "SHOW MORE" to see the results</p>
</section>
<radio></radio>
<div class="wrapper">
  <h3>5 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>8 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>10 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>13 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>16 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
  <h3>19 child elements</h3>
  <div class="grid-parent">
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="grid-item"></div>
    <div class="btn-expand">Show More</div>
  </div>
</div>

2
Vincent Tang

Dies ist die jQuery-Lösung, die für mich funktioniert hat. clientWidth etc. hat nicht funktioniert.

function is_overflowing(element, extra_width) {
    return element.position().left + element.width() + extra_width > element.parent().width();
}

Wenn dies nicht funktioniert, stellen Sie sicher, dass das übergeordnete Element der Elemente die gewünschte Breite hat (persönlich musste ich parent().parent()) verwenden. position ist relativ zum übergeordneten Element. Ich habe auch extra_width aufgenommen, da meine Elemente ("Tags") Bilder enthalten, die Folgendes enthalten wenig Zeit zum Laden, aber während des Funktionsaufrufs haben sie eine Breite von Null, was die Berechnung beeinträchtigt. Um das zu umgehen, verwende ich den folgenden Aufrufcode:

var extra_width = 0;
$(".tag:visible").each(function() {
    if (!$(this).find("img:visible").width()) {
        // tag image might not be visible at this point,
        // so we add its future width to the overflow calculation
        // the goal is to hide tags that do not fit one line
        extra_width += 28;
    }
    if (is_overflowing($(this), extra_width)) {
        $(this).hide();
    }
});

Hoffe das hilft.

1

Hier eine Geige, um festzustellen, ob ein Element mit einem Wrapperdiv mit Überlauf übergelaufen ist: hidden und JQuery height (), um die Differenz zwischen dem Wrapper und einem inneren Inhaltsdifferenz zu messen.

outers.each(function () {
    var inner_h = $(this).find('.inner').height();
    console.log(inner_h);
    var outer_h = $(this).height();
    console.log(outer_h);
    var overflowed = (inner_h > outer_h) ? true : false;
    console.log("overflowed = ", overflowed);
});

Source:Frameworks & Erweiterungen auf jsfiddle.net

1
user1295799

Ein anderes Problem, das Sie in Betracht ziehen sollten, ist die Nichtverfügbarkeit von JS. Denken Sie an progressive Verzauberung oder grazile Erniedrigung. Ich würde vorschlagen:

  • hinzufügen von "Weitere Schaltfläche" standardmäßig
  • hinzufügen von Überlaufregeln standardmäßig
  • schaltflächen und ggf. CSS-Änderungen in JS ausblenden, nachdem element.scrollHeight mit element.clientHeight verglichen wurde 
1
MFix

verwenden Sie js, um zu prüfen, ob die offsetHeight des Kindes mehr als die der Eltern ist. Wenn dies der Fall ist, lassen Sie die scroll/hidden/auto der Eltern überfluten, je nachdem, was Sie möchten, und display:block für die mehr div .. 

1
Vivek Chandra

Die Jquery-Alternative zur Antwort ist die Verwendung der Taste [0], um auf das rohe Element wie folgt zuzugreifen:

if ($('#elem')[0].scrollHeight > $('#elem')[0].clientHeight){
0
Antony

Sie können die Grenzen relativ zum übergeordneten Offset überprüfen.

// Position of left Edge relative to frame left courtesy
// http://www.quirksmode.org/js/findpos.html
function absleft(el) {
  var x = 0;
  for (; el; el = el.offsetParent) {
    x += el.offsetLeft;
  }
  return x;
}

// Position of top Edge relative to top of frame.
function abstop(el) {
  var y = 0;
  for (; el; el = el.offsetParent) {
    y += el.offsetTop;
  }
  return y;
}

// True iff el's bounding rectangle includes a non-zero area
// the container's bounding rectangle.
function overflows(el, opt_container) {
  var cont = opt_container || el.offsetParent;
  var left = absleft(el), right = left + el.offsetWidth,
      top = abstop(el), bottom = top + el.offsetHeight;
  var cleft = absleft(cont), cright = cleft + cont.offsetWidth,
      ctop = abstop(cont), cbottom = ctop + cont.offsetHeight;
  return left < cleft || top < ctop
      || right > cright || bottom > cbottom;
}

Wenn Sie dieses Element übergeben, wird Ihnen mitgeteilt, ob sich seine Grenzen vollständig in einem Container befinden. Wenn kein expliziter Container bereitgestellt wird, wird standardmäßig der übergeordnete Versatz des Elements verwendet. Es verwendet

0
Mike Samuel
setTimeout(function(){
    isOverflowed(element)           
},500)

function isOverflowed(element){
    return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}

Das hat für mich gearbeitet. Vielen Dank.

0
Krunal