Periksa apakah konten elemen meluap?

154

Apa cara termudah untuk mendeteksi jika suatu elemen telah meluap?

Kasus penggunaan saya adalah, saya ingin membatasi kotak konten tertentu memiliki ketinggian 300px. Jika konten dalam lebih tinggi dari itu, saya memotongnya dengan melimpah. Tetapi jika itu meluap saya ingin menunjukkan tombol 'lebih', tetapi jika tidak saya tidak ingin menunjukkan tombol itu.

Apakah ada cara mudah untuk mendeteksi kelebihan, atau adakah metode yang lebih baik?

Harry
sumber

Jawaban:

86

Jika Anda hanya ingin menunjukkan pengidentifikasi untuk lebih banyak konten, maka Anda dapat melakukannya dengan CSS murni. Saya menggunakan bayangan bergulir murni untuk ini. Kuncinya adalah penggunaan background-attachment: local;. Css Anda terlihat seperti ini:

.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;
}
<div class="scrollbox">
  <ul>
    <li>Not enough content to scroll</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
  </ul>
</div>


<div class="scrollbox">
  <ul>
    <li>Ah! Scroll below!</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>The end!</li>
    <li>No shadow there.</li>
  </ul>
</div>

Kode dan contohnya dapat Anda temukan di http://dabblet.com/gist/2462915

Dan penjelasannya dapat Anda temukan di sini: http://lea.verou.me/2012/04/background-attachment-local/ .

RWAM
sumber
1
Ide bagus tetapi dalam contoh Anda latar belakang (bayangan) akan berada di belakang teks!
DreamTeK
Trik luar biasa, namun di Chrome itu hanya menampilkan bayangan statis di bagian bawah, tidak pernah menghilang dan bayangan atas tidak pernah muncul
Jared
214

Elemen dapat dilimpahi secara vertikal, horizontal atau keduanya. Fungsi ini akan mengembalikan Anda nilai boolean jika elemen DOM terlalu banyak:

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

Contoh ES6:

const isOverflown = ({ clientWidth, clientHeight, scrollWidth, scrollHeight }) => {
    return scrollHeight > clientHeight || scrollWidth > clientWidth;
}
mikro
sumber
41
Solusi bagus! Inilah varian jQuery (untuk digunakan bersama $("#element").overflown()):$.fn.overflown=function(){var e=this[0];return e.scrollHeight>e.clientHeight||e.scrollWidth>e.clientWidth;}
Sygmoral
@micnic hai, saya menggunakan ionic2 dan mencoba melakukan hal yang sama ... tetapi fungsi mengembalikan true selalu ... apakah ada cara berbeda untuk melakukan hal-hal dalam sudut 2
Yasir
@DavidBracoly, fungsi ini untuk API DOM murni, saya tidak punya pengalaman dengan Ionic / Angular, saya kira Anda harus mendapatkan Elemen DOM asli dan menggunakan fungsi ini
micnic
3
Hanya untuk Firefox: element.addEventListener ("overflow", () => log( "overflow" ), false);Referensi: acara melimpah
Reza
18

Dibandingkan element.scrollHeightdengan element.clientHeightharus melakukan tugas.

Di bawah ini adalah gambar dari MDN menjelaskan Element.scrollHeight dan Element.clientHeight.

Tinggi Gulir

Tinggi klien

Bergi
sumber
2
Ya, tetapi menurut quirksmode itu paling berhasil - dan jauh lebih sederhana daripada solusi yang diposting lainnya.
Bergi
@ Harry: Ini didukung di semua browser saat ini (setidaknya desktop yang), jadi tidak masalah bahwa itu secara resmi tidak standar.
Marat Tanalin
1
Di sini, properti ini selalu memiliki nilai yang sama.
koppor
7

Saya membuat codepen multi bagian yang menunjukkan jawaban di atas (misalnya menggunakan overflow tersembunyi dan tinggi) tetapi juga bagaimana Anda akan memperluas / menciutkan item yang meluap

Contoh 1: https://codepen.io/Kagerjay/pen/rraKLB (Contoh sederhana sebenarnya, tanpa javascript, hanya untuk klip item yang dilimpahi)

Contoh 2: https://codepen.io/Kagerjay/pen/LBErJL (Handler acara tunggal menunjukkan lebih banyak / tidak ditampilkan pada item yang meluap)

Contoh 3: https://codepen.io/Kagerjay/pen/MBYBoJ (Handler multi-event di banyak acara lebih banyak / lebih sedikit menunjukkan pada item-item yang meluap)

Saya telah melampirkan contoh 3 di bawah ini juga , saya menggunakan Jade / Pug sehingga mungkin sedikit lebih baik. Saya sarankan memeriksa codepens yang telah saya buat lebih mudah untuk dipahami.

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

Vincent Tang
sumber
4

Apakah sesuatu seperti ini: http://jsfiddle.net/Skooljester/jWRRA/1/ bekerja? Itu hanya memeriksa ketinggian konten dan membandingkannya dengan ketinggian wadah. Jika lebih besar daripada yang dapat Anda masukkan ke dalam kode untuk menambahkan tombol "Tampilkan lebih banyak".

Perbarui: Menambahkan kode untuk membuat tombol "Tampilkan Selengkapnya" di bagian atas wadah.

ayyp
sumber
3

Jika Anda menggunakan jQuery, Anda dapat mencoba trik: buat div luar dengan overflow: hiddendan div dalam dengan konten. Kemudian gunakan .height()fungsi untuk memeriksa apakah ketinggian div dalam lebih besar dari tinggi div luar. Saya tidak yakin ini akan berhasil tetapi cobalah.

TMS
sumber
1

gunakan js untuk memeriksa apakah anak offsetHeightlebih dari orang tua .. jika ya, buat orang tua meluap scroll/hidden/automana pun yang Anda inginkan dan juga display:blockpada lebih banyak div ..

Vivek Chandra
sumber
1

Anda dapat memeriksa batas relatif terhadap induk offset.

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

Jika Anda melewatkan elemen ini, elemen akan memberi tahu Anda apakah batasnya sepenuhnya di dalam wadah, dan akan default ke induk offset elemen jika tidak ada wadah eksplisit yang disediakan. Itu menggunakan

Mike Samuel
sumber
1

Masalah lain yang harus Anda pertimbangkan adalah tidak tersedianya JS. Pikirkan tentang pesona progresif atau penurunan anggun. Saya akan menyarankan:

  • menambahkan "tombol lagi" secara default
  • menambahkan aturan overflow secara default
  • menyembunyikan tombol dan jika perlu modifikasi CSS di JS setelah membandingkan element.scrollHeight ke element.clientHeight
MFix
sumber
1

Berikut adalah biola untuk menentukan apakah suatu elemen telah meluap menggunakan div pembungkus dengan luberan: tersembunyi dan tinggi JQuery () untuk mengukur perbedaan antara pembungkus dan div konten dalam.

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

Sumber: Kerangka & Ekstensi di jsfiddle.net

pengguna1295799
sumber
1

Ini adalah solusi jQuery yang bekerja untuk saya. clientWidthdll tidak bekerja.

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

Jika ini tidak berhasil, pastikan bahwa induk elemen memiliki lebar yang diinginkan (secara pribadi, saya harus menggunakan parent().parent()). positionRelatif terhadap induk. Saya juga menyertakan extra_widthkarena elemen saya ("tag") berisi gambar yang membutuhkan waktu sedikit untuk memuat, tetapi selama panggilan fungsi mereka memiliki lebar nol, merusak perhitungan. Untuk menyiasatinya, saya menggunakan kode panggilan berikut:

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

Semoga ini membantu.

Dennis Golomazov
sumber
0
setTimeout(function(){
    isOverflowed(element)           
},500)

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

Ini berhasil untuk saya. Terima kasih.

Krunal
sumber
3
Bagaimana hal ini berbeda dari jawaban micnic?
carefulnow1
0

Alternatif jquery untuk jawabannya adalah menggunakan kunci [0] untuk mengakses elemen mentah seperti ini:

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

Saya telah memperpanjang Elemen untuk alasan enkapsulasi. Dari jawaban mikro.

/*
 * isOverflowing
 * 
 * Checks to see if the element has overflowing content
 * 
 * @returns {}
 */
Element.prototype.isOverflowing = function(){
    return this.scrollHeight > this.clientHeight || this.scrollWidth > this.clientWidth;
}

Gunakan seperti ini

let elementInQuestion = document.getElementById("id_selector");

    if(elementInQuestion.isOverflowing()){
        // do something
    }
David Clews
sumber