ตรวจสอบว่าเนื้อหาขององค์ประกอบล้นหรือไม่


153

วิธีที่ง่ายที่สุดในการตรวจสอบว่าองค์ประกอบได้รับการล้น?

กรณีการใช้งานของฉันคือฉันต้องการ จำกัด กล่องเนื้อหาบางอย่างให้มีความสูง 300px หากเนื้อหาภายในสูงกว่านั้นฉันจะตัดมันด้วยการล้น แต่ถ้ามันล้นฉันต้องการแสดงปุ่ม 'มากกว่า' แต่ถ้าไม่ใช่ฉันไม่ต้องการแสดงปุ่มนั้น

มีวิธีง่าย ๆ ในการตรวจจับการล้นหรือมีวิธีการที่ดีกว่า

คำตอบ:


86

หากคุณต้องการแสดงเฉพาะตัวระบุเนื้อหาเพิ่มเติมจากนั้นคุณสามารถทำได้ด้วย CSS บริสุทธิ์ ฉันใช้เงาเลื่อนที่บริสุทธิ์สำหรับเรื่องนี้ background-attachment: local;เคล็ดลับคือการใช้งานของ CSS ของคุณมีลักษณะดังนี้:

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

รหัสและตัวอย่างที่คุณสามารถพบได้ในhttp://dabblet.com/gist/2462915

และคำอธิบายที่คุณสามารถหาได้ที่นี่: http://lea.verou.me/2012/04/background-attachment-local/


1
ความคิดที่ดี แต่ในตัวอย่างของคุณพื้นหลัง (เงา) จะอยู่ด้านหลังข้อความ!
DreamTeK

เคล็ดลับที่ยอดเยี่ยม แต่ใน Chrome จะแสดงเฉพาะเงาที่ด้านล่างเท่านั้นมันไม่เคยหายไปและเงาบนไม่เคยปรากฏ
Jared

214

องค์ประกอบอาจอยู่ในแนวตั้งแนวนอนหรือทั้งสองอย่าง ฟังก์ชั่นนี้จะคืนค่าบูลีนให้คุณหากองค์ประกอบ DOM เป็นแบบ overflown:

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

ตัวอย่าง ES6:

const isOverflown = ({ clientWidth, clientHeight, scrollWidth, scrollHeight }) => {
    return scrollHeight > clientHeight || scrollWidth > clientWidth;
}

41
สุดยอดทางออก! นี่คือตัวแปร jQuery (เพื่อใช้กับ$("#element").overflown()):$.fn.overflown=function(){var e=this[0];return e.scrollHeight>e.clientHeight||e.scrollWidth>e.clientWidth;}
Sygmoral

@micnic สวัสดีฉันใช้ ionic2 และพยายามทำสิ่งเดียวกัน ... แต่ฟังก์ชั่นกลับเป็นจริงเสมอ ... มีวิธีที่แตกต่างในการทำสิ่งต่าง ๆ ในเชิงมุม 2
Yasir

@DavidBracoly ฟังก์ชั่นนี้ใช้สำหรับ DOM บริสุทธิ์ API ฉันไม่เคยมีประสบการณ์เกี่ยวกับ Ionic / Angular ฉันคิดว่าคุณควรได้รับ DOM Element ดั้งเดิมและใช้ฟังก์ชั่นนี้
micnic

3
สำหรับ Firefox เท่านั้น: element.addEventListener ("overflow", () => log( "overflow" ), false);การอ้างอิง: เหตุการณ์ล้น
Reza

18

เมื่อเปรียบเทียบelement.scrollHeightกับelement.clientHeightควรทำภารกิจ

ด้านล่างนี้เป็นภาพจาก MDN อธิบาย Element.scrollHeight และ Element.clientHeight

เลื่อนความสูง

ความสูงของลูกค้า


2
ใช่ แต่ตามโหมด quirksmodeนั้นทำงานได้ดีที่สุด - และง่ายกว่าโซลูชันที่โพสต์อื่น ๆ
Bergi

@Harry: ได้รับการสนับสนุนในเบราว์เซอร์ปัจจุบันทั้งหมด (อย่างน้อยบนเดสก์ท็อป) ดังนั้นจึงไม่สำคัญว่าจะไม่เป็นทางการ
Marat Tanalin

1
ที่นี่คุณสมบัติเหล่านี้มีค่าเหมือนกันเสมอ
koppor

7

ฉันทำ codepen หลายส่วนแสดงให้เห็นถึงคำตอบข้างต้น (เช่นการใช้ที่ซ่อนอยู่ล้นและความสูง) แต่ยังวิธีที่คุณจะขยาย / ยุบรายการล้น

ตัวอย่างที่ 1: https://codepen.io/Kagerjay/pen/rraKLB (ตัวอย่างง่ายๆจริง ๆ ไม่มีจาวาสคริปต์เพื่อคลิปรายการที่โอเวอร์โฟลว์)

ตัวอย่างที่ 2: https://codepen.io/Kagerjay/pen/LBErJL (ตัวจัดการเหตุการณ์เดี่ยวแสดงมากขึ้น / แสดงอยู่ในรายการที่โอเวอร์โฟลว์)

ตัวอย่างที่ 3: https://codepen.io/Kagerjay/pen/MBYBoJ (ตัวจัดการหลายเหตุการณ์ในหลายรายการแสดงมากขึ้น / แสดงน้อยลงในรายการที่โอเวอร์โฟลว์)

ฉันได้แนบตัวอย่างที่ 3 ด้านล่างเช่นกันฉันใช้ Jade / Pug ดังนั้นมันอาจเป็น verbose แบบตาด ฉันแนะนำให้ตรวจสอบ codepens ที่ฉันทำได้ง่ายกว่าที่จะเข้าใจ

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


4

จะมีลักษณะเช่นนี้: http://jsfiddle.net/Skooljester/jWRRA/1/หรือไม่ เพียงแค่ตรวจสอบความสูงของเนื้อหาและเปรียบเทียบกับความสูงของคอนเทนเนอร์ หากมากกว่านั้นคุณสามารถใส่รหัสเพื่อผนวกปุ่ม "แสดงเพิ่มเติม"

อัปเดต:เพิ่มรหัสเพื่อสร้างปุ่ม "แสดงเพิ่มเติม" ที่ด้านบนของคอนเทนเนอร์


3

หากคุณใช้ jQuery คุณอาจลองใช้เคล็ดลับ: สร้าง div ภายนอกด้วยoverflow: hiddenและ div ภายในด้วยเนื้อหา จากนั้นใช้.height()ฟังก์ชันเพื่อตรวจสอบว่าความสูงของ div ภายในมากกว่าความสูงของ div ภายนอกหรือไม่ ฉันไม่แน่ใจว่ามันจะทำงานได้ แต่ลองดู


1

ใช้ js เพื่อตรวจสอบว่าเด็กของoffsetHeightเป็นมากกว่าพ่อแม่ .. ถ้ามันเป็นความกรุณาให้ผู้ปกครองล้นscroll/hidden/autoใดก็ตามที่คุณต้องการและยังdisplay:blockบน div มากขึ้น ..


1

คุณสามารถตรวจสอบขอบเขตที่เกี่ยวข้องกับผู้ปกครองชดเชย

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

หากคุณผ่านองค์ประกอบนี้มันจะบอกคุณว่าขอบเขตนั้นอยู่ในคอนเทนเนอร์ทั้งหมดหรือไม่และจะใช้ค่าเริ่มต้นเป็นพาเรนต์หลักขององค์ประกอบหากไม่มีคอนเทนเนอร์ที่ชัดเจน มันใช้


1

ปัญหาอื่นที่คุณควรพิจารณาคือ JS ไม่สามารถใช้งานได้ คิดเกี่ยวกับความลุ่มหลงก้าวหน้าหรือความเสื่อมสง่างาม ฉันจะแนะนำ:

  • การเพิ่ม "ปุ่มเพิ่มเติม" โดยค่าเริ่มต้น
  • การเพิ่มกฎการโอเวอร์โฟลว์ตามค่าเริ่มต้น
  • ปุ่มซ่อนและหากจำเป็นต้องแก้ไข CSS ใน JS หลังจากเปรียบเทียบ element.scrollHeight กับ element.clientHeight

1

นี่คือซอสำหรับการพิจารณาว่าองค์ประกอบถูกโอเวอร์โฟลว์โดยใช้ wrapper div กับโอเวอร์โฟลว์: hidden และ JQuery height () เพื่อวัดความแตกต่างระหว่าง wrapper และ div เนื้อหาภายใน

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

ที่มา: Frameworks & Extensions บน jsfiddle.net


1

นี่เป็นโซลูชัน jQuery ที่เหมาะกับฉัน clientWidthฯลฯ ไม่ทำงาน

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

หากยังไม่สามารถทำงานให้แน่ใจว่าผู้ปกครองว่าองค์ประกอบมีความกว้างตามต้องการ (ส่วนตัวผมต้องใช้parent().parent()). positionเป็นญาติไปยังผู้ปกครอง. ฉันยังได้รวมextra_widthเพราะองค์ประกอบของฉัน ( 'แท็ก') มีภาพซึ่งใช้เวลาขนาดเล็กที่จะ แต่ในระหว่างการเรียกฟังก์ชั่นพวกเขามีความกว้างเป็นศูนย์ทำลายการคำนวณเพื่อหลีกเลี่ยงปัญหานั้นฉันใช้รหัสการโทรต่อไปนี้:

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

หวังว่านี่จะช่วยได้


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

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

สิ่งนี้ได้ผลสำหรับฉัน ขอบคุณ.


3
สิ่งนี้แตกต่างจากคำตอบของ micnic อย่างไร
carefulnow1

0

ทางเลือก jquery ของคำตอบคือการใช้ปุ่ม [0] เพื่อเข้าถึงองค์ประกอบดิบเช่นนี้

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

0

ฉันได้ขยายองค์ประกอบให้เหตุผลการห่อหุ้ม จากคำตอบของ micnic

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

ใช้มันแบบนี้

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

    if(elementInQuestion.isOverflowing()){
        // do something
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.