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

Posted

技术标签:

【中文标题】检查元素的内容是不是溢出?【英文标题】:Check if an element's content is overflowing?检查元素的内容是否溢出? 【发布时间】:2012-03-09 03:44:01 【问题描述】:

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

我的用例是,我想将某个内容框的高度限制为 300 像素。如果内部内容高于此,我会用溢出将其切断。但如果溢出我想显示一个“更多”按钮,但如果不是我不想显示那个按钮。

有没有简单的方法检测溢出,或者有没有更好的方法?

【问题讨论】:

如果有人正在寻找自定义 React Hook 来在 React 领域执行此任务:robinwieruch.de/react-custom-hook-check-if-overflow 【参考方案1】:

这样的东西:http://jsfiddle.net/Skooljester/jWRRA/1/ 有用吗?它只是检查内容的高度并将其与容器的高度进行比较。如果它大于您可以输入的代码以附加“显示更多”按钮。

更新:添加了在容器顶部创建“显示更多”按钮的代码。

【讨论】:

【参考方案2】:

使用js检查孩子的offsetHeight是否超过父母..如果是的话,让父母溢出scroll/hidden/auto任意你想要的,还有display:block在更多的div上..

【讨论】:

【参考方案3】:

您可以检查相对于偏移父级的边界。

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

如果你传递一个元素,它会告诉你它的边界是否完全在一个容器内,如果没有提供明确的容器,它将默认为元素的偏移父级。它使用

【讨论】:

这是整个线程上唯一有效的解决方案。感谢发帖。【参考方案4】:

如果您使用 jQuery,您可能会尝试一个技巧:使用 overflow: hidden 制作外部 div 并使用内容制作内部 div。然后使用.height()函数检查内部div的高度是否大于外部div的高度。我不确定它是否会起作用,但请尝试一下。

【讨论】:

【参考方案5】:

比较 element.scrollHeightelement.clientHeight 应该可以完成任务。

以下是 MDN 中解释 Element.scrollHeight 和 Element.clientHeight 的图片。

【讨论】:

是的,但根据quirksmode 的说法,它最有效 - 并且比其他发布的解决方案简单得多。 @Harry:当前所有浏览器(至少桌面浏览器)都支持它,所以它在形式上是非标准的也没关系。 在这里,这些属性始终具有相同的值。【参考方案6】:

您应该考虑的另一个问题是 JS 不可用。想想渐进式的魔法或优雅的退化。我建议:

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

【讨论】:

【参考方案7】:

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

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

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


var els = document.getElementsByClassName('demos');
for (var i = 0; i < els.length; i++) 
  var el = els[i];
  el.style.borderColor = (isOverflown(el) ? 'red' : 'green');
  console.log("Element #" + i + " is " + (isOverflown(el) ? '' : 'not ') + "overflown.");
.demos 
  white-space: nowrap;
  overflow: hidden;
  width: 120px;
  border: 3px solid black;
<div class='demos'>This is some text inside the div which we are testing</div>
<div class='demos'>This is text.</div>

ES6 示例:

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

【讨论】:

很好的解决方案!这是一个 jQuery 变体(与 $("#element").overflown() 一起使用):$.fn.overflown=function()var e=this[0];return e.scrollHeight&gt;e.clientHeight||e.scrollWidth&gt;e.clientWidth; @micnic 嗨,我正在使用 ionic2 并尝试做同样的事情......但函数总是返回 true......在 angular 2 中是否有不同的方法来做事 @DavidBracoly,这个函数是纯DOM API,我没有Ionic/Angular的经验,我想你应该得到原始的DOM元素并使用这个函数 仅适用于 Firefox:element.addEventListener ("overflow", () =&gt; log( "overflow" ), false); 参考:overflow event 哇,这甚至可以工作,例如在 grid 中,其中边界客户端 rect 不包含溢出内容。【参考方案8】:

这里是一个小提琴,用于确定元素是否已经溢出,使用带有 overflow:hidden 和 JQuery height() 的包装器 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);
);

来源: Frameworks & Extensions on jsfiddle.net

【讨论】:

【参考方案9】:
setTimeout(function()
    isOverflowed(element)           
,500)

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

这对我有用。谢谢。

【讨论】:

这与 micnic 的回答有何不同?【参考方案10】:

这是对我有用的 jQuery 解决方案。 clientWidth 等无效。

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

如果这不起作用,请确保元素的父级具有所需的宽度(就我个人而言,我不得不使用 parent().parent())position 是相对于父级的。我还包括了 extra_width,因为我的元素("tags") 包含加载时间短的图像,但在函数调用期间它们的宽度为零,从而破坏了计算。为了解决这个问题,我使用以下调用代码:

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

希望这会有所帮助。

【讨论】:

【参考方案11】:

如果您只想为更多内容显示一个标识符,那么您可以使用纯 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/。

【讨论】:

好主意,但在您的示例中,背景(阴影)将在文本后面! 很棒的技巧,但是在 Chrome 中它只在底部显示静态阴影,它永远不会消失,上阴影永远不会显示 /* Opera 不支持这个简写 */ -> 我在 Opera 上,它似乎对我有用。【参考方案12】:

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

示例 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>

【讨论】:

【参考方案13】:

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

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

【讨论】:

【参考方案14】:

出于封装原因,我扩展了 Element。来自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
    

【讨论】:

【参考方案15】:

为条件可见性添加事件侦听器:

document.getElementById('parent').addEventListener('scroll', (e) => 
  const childEl = document.getElementById('child');

  childEl.style.visibility = e.target.scrollTop > 0 ? 'visible' : 'hidden';
);

【讨论】:

【参考方案16】:

非常非常简单。只需在页面上的所有元素上添加以下代码:

* 
  outline: 2px solid red;

现在只需找到溢出的部分,即:

【讨论】:

以上是关于检查元素的内容是不是溢出?的主要内容,如果未能解决你的问题,请参考以下文章

HTML 字段集内容在 100% 高度溢出 (Chrome)

html文本溢出

画布元素溢出其容器 div

手动将字符串转换为 int 并检查 C/C++ 中是不是发生溢出?

文本溢出显示省略号

SQL / Python尝试检查数据是不是已存在:将nvarchar转换为数据类型数字的算术溢出错误