Kiểm tra xem nội dung của một phần tử có tràn không?


153

Cách dễ nhất để phát hiện nếu một phần tử đã bị tràn?

Trường hợp sử dụng của tôi là, tôi muốn giới hạn một hộp nội dung nhất định để có chiều cao 300px. Nếu nội dung bên trong cao hơn thế, tôi sẽ cắt nó với một tràn. Nhưng nếu nó bị tràn, tôi muốn hiển thị nút 'thêm', nhưng nếu không tôi không muốn hiển thị nút đó.

Có một cách dễ dàng để phát hiện tràn, hoặc có một phương pháp tốt hơn?

Câu trả lời:


86

Nếu bạn muốn chỉ hiển thị một mã định danh cho nhiều nội dung hơn, thì bạn có thể làm điều này với CSS thuần túy. Tôi sử dụng bóng cuộn thuần túy cho việc này. Bí quyết là sử dụng background-attachment: local;. Css của bạn trông như thế này:

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

Mã và ví dụ bạn có thể tìm thấy trên http://dabblet.com/gist/2462915

Và một lời giải thích bạn có thể tìm thấy ở đây: http://lea.verou.me/2012/04/background-attachment-local/ .


1
Ý tưởng hay nhưng trong ví dụ của bạn, nền (bóng) sẽ ở phía sau văn bản!
DreamTeK

Thủ thuật tuyệt vời, tuy nhiên trong Chrome, nó chỉ hiển thị bóng tĩnh ở phía dưới, nó không bao giờ biến mất và bóng trên không bao giờ hiển thị
Jared

214

Phần tử có thể bị tràn theo chiều dọc, chiều ngang hoặc cả hai. Hàm này sẽ trả về cho bạn một giá trị boolean nếu phần tử DOM bị tràn:

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

Ví dụ ES6:

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

41
Giải pháp tuyệt vời! Đây là một biến thể của jQuery (sẽ được sử dụng với $("#element").overflown()):$.fn.overflown=function(){var e=this[0];return e.scrollHeight>e.clientHeight||e.scrollWidth>e.clientWidth;}
Sygmoral

@micnic hi, tôi đang sử dụng ionic2 và đang cố gắng làm điều tương tự ... nhưng chức năng luôn luôn đúng ... có một cách khác để làm mọi thứ trong góc 2
Yasir

@DavidBracoly, chức năng này dành cho API DOM thuần túy, tôi không có kinh nghiệm với Ionic / Angular, tôi đoán bạn nên lấy Phần tử DOM gốc và sử dụng chức năng này
micnic

3
Chỉ dành cho Firefox: element.addEventListener ("overflow", () => log( "overflow" ), false);Tham khảo: sự kiện tràn
Reza

18

So sánh element.scrollHeightđể element.clientHeightnên làm nhiệm vụ.

Dưới đây là những hình ảnh từ MDN giải thích Element.scrollHeight và Element.clientHeight.

Chiều cao cuộn

Chiều cao của khách hàng


2
Vâng, nhưng theo quirksmode, nó hoạt động tốt nhất - và đơn giản hơn nhiều so với các giải pháp được đăng khác.
Bergi

@Harry: Nó được hỗ trợ trong tất cả các trình duyệt hiện tại (ít nhất là các trình duyệt dành cho máy tính để bàn), do đó, nó không phải là vấn đề chính thức.
Marat Tanalin

1
Ở đây, các thuộc tính này luôn có cùng các giá trị.
koppor

7

Tôi đã tạo một codepen nhiều phần thể hiện các câu trả lời ở trên (ví dụ: sử dụng ẩn tràn và chiều cao) nhưng cũng là cách bạn sẽ mở rộng / thu gọn các mục bị tràn

Ví dụ 1: https://codepen.io/Kagerjay/pen/rraKLB (Ví dụ đơn giản thực sự, không có javascript, chỉ để clip các mục bị tràn)

Ví dụ 2: https://codepen.io/Kagerjay/pen/LBErJL (Trình xử lý sự kiện đơn lẻ hiển thị nhiều hơn / không hiển thị trên các mục bị tràn)

Ví dụ 3: https://codepen.io/Kagerjay/pen/MBYBoJ (Trình xử lý đa sự kiện trên nhiều chương trình hiển thị nhiều hơn / hiển thị ít hơn trên các mục bị tràn)

Tôi cũng đã đính kèm ví dụ 3 bên dưới , tôi sử dụng Jade / Pug để nó có thể là một đoạn dài. Tôi đề nghị kiểm tra các loại tiền mã hóa mà tôi đã làm cho nó đơn giản hơn để nắm bắt.

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

Sẽ một cái gì đó như thế này: http://jsfiddle.net/Skooljester/jWRRA/1/ làm việc? Nó chỉ kiểm tra chiều cao của nội dung và so sánh với chiều cao của container. Nếu nó lớn hơn bạn có thể nhập mã để nối thêm nút "Hiển thị thêm".

Cập nhật: Đã thêm mã để tạo nút "Hiển thị thêm" ở đầu hộp chứa.


3

Nếu bạn đang sử dụng jQuery, bạn có thể thử một mẹo: tạo div bên ngoài overflow: hiddenvà div bên trong bằng nội dung. Sau đó sử dụng .height()hàm để kiểm tra xem chiều cao của div bên trong có lớn hơn chiều cao của div bên ngoài không. Tôi không chắc nó sẽ hoạt động nhưng hãy thử xem.


1

sử dụng js để kiểm tra xem đứa trẻ offsetHeightcó hơn cha mẹ không .. nếu có, hãy làm cho cha mẹ tràn ra scroll/hidden/autobất cứ điều gì bạn muốn và cũng display:blocktrên div nhiều hơn ..


1

Bạn có thể kiểm tra giới hạn liên quan đến cha mẹ bù.

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

Nếu bạn vượt qua phần tử này, nó sẽ cho bạn biết liệu giới hạn của nó có hoàn toàn bên trong một thùng chứa hay không và sẽ mặc định là phần tử bù của phần tử nếu không có vùng chứa rõ ràng nào được cung cấp. Nó sử dụng


1

Một vấn đề khác bạn nên xem xét là không có sẵn JS. Hãy suy nghĩ về sự mê hoặc tiến bộ hoặc xuống cấp duyên dáng. Tôi muốn đề nghị:

  • thêm "nút thêm" theo mặc định
  • thêm quy tắc tràn theo mặc định
  • nút ẩn và nếu sửa đổi CSS cần thiết trong JS sau khi so sánh Element.scrollHeight với Element.clientHeight

1

Dưới đây là một mẹo để xác định xem một phần tử có bị tràn hay không bằng cách sử dụng div trình bao bọc với overflow: hidden và JQuery height () để đo sự khác biệt giữa trình bao bọc và div nội dung bên trong.

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

Nguồn: Khung & Tiện ích mở rộng trên jsfiddle.net


1

Đây là giải pháp jQuery phù hợp với tôi. clientWidthvv đã không làm việc.

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

Nếu điều này không hoạt động, hãy đảm bảo rằng cha mẹ của các thành phần có chiều rộng mong muốn (cá nhân tôi phải sử dụng parent().parent()). Có positionliên quan đến cha mẹ. Tôi cũng đã bao gồm extra_widthvì các thành phần của tôi ("thẻ") chứa hình ảnh mất ít thời gian để tải, nhưng trong khi gọi hàm chúng có độ rộng bằng 0, làm hỏng phép tính. Để giải quyết vấn đề đó, tôi sử dụng mã gọi sau:

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

Hi vọng điêu nay co ich.


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

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

Điều này đã làm việc cho tôi. Cảm ơn bạn.


3
Điều này khác với câu trả lời của micnic như thế nào?
cẩn thận1

0

Giải pháp thay thế cho câu trả lời là sử dụng phím [0] để truy cập phần tử thô như sau:

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

0

Tôi đã mở rộng Element vì lý do đóng gói. Từ câu trả lời 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;
}

Sử dụng nó như thế này

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

    if(elementInQuestion.isOverflowing()){
        // do something
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.