检查元素的内容是否溢出?


153

检测元素是否已溢出的最简单方法是什么?

我的用例是,我想将某个内容框的高度限制为300px。如果内部内容比那更高,我会溢出来。但是,如果溢出了,我想显示一个“更多”按钮,但如果不是,我不想显示那个按钮。

有没有检测溢出的简便方法,还是有更好的方法?

Answers:


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 '18

绝妙的技巧,但是在Chrome中,它在底部仅显示静态阴影,它永远不会消失,而在上部阴影也永远不会显示
Jared

214

该元素可能在垂直,水平或两者上溢出。如果DOM元素溢出,此函数将返回一个布尔值:

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 2013年

@micnic嗨,我正在使用ionic2并尝试做相同的事情...但是该函数始终返回true ...在角度2中有做事的另一种方法
Yasir

@DavidBracoly,此函数用于纯DOM API,我没有Ionic / Angular的经验,我想您应该获取原始的DOM元素并使用此函数
micnic '17

3
仅适用于Firefox:element.addEventListener ("overflow", () => log( "overflow" ), false);参考:溢出事件
Reza


7

我做了一个多部分的代码笔,演示了上述答案(例如,使用隐藏的隐藏和高度),以及如何扩展/折叠溢出的项目

示例1:https//codepen.io/Kagerjay/pen/rraKLB(真正简单的示例,没有javascript,仅用于剪辑溢出的项目)

示例2:https://codepen.io/Kagerjay/pen/LBErJL(单个事件处理程序对溢出的项目显示更多/不显示)

示例3:https//codepen.io/Kagerjay/pen/MBYBoJ(许多事件处理程序显示更多/溢出项目显示更少)

我在下面附加了示例3,我使用了Jade / Pug,所以可能有点冗长。我建议您检查一下我更易于掌握的代码笔。

// 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,则可以尝试以下技巧:使用 overflow: hidden div具有内容,内部div具有内容。然后使用.height()函数检查内部div的高度是否大于外部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不可用。考虑进行附魔或优雅降级。我会建议:

  • 默认添加“更多按钮”
  • 默认情况下添加溢出规则
  • 在将element.scrollHeight与element.clientHeight比较之后,在JS中隐藏按钮和必要的CSS修改

1

这是一个小技巧,用于确定是否使用带有wrover:hidden和JQuery height()的wrapper div来溢出元素,以测量包装器与内部内容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);
});

资料来源: jsfiddle.net上的Frameworks&Extensions


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
这与麦克风的答案有何不同?
now17年

0

答案的jquery替代方法是使用[0]键访问原始元素,例如:

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

0

我出于封装原因扩展了Element。来自麦克风的答案。

/*
 * 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
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.