检测元素是否溢出的最简单方法是什么?
我的用例是,我想限制某个内容框的高度为300px。如果内部内容比这高,我用溢出切断它。但如果它已满,我想显示一个'more'按钮,但如果没有,我不想显示该按钮。
是否有一种简单的方法来检测溢出,或者有更好的方法?
检测元素是否溢出的最简单方法是什么?
我的用例是,我想限制某个内容框的高度为300px。如果内部内容比这高,我用溢出切断它。但如果它已满,我想显示一个'more'按钮,但如果没有,我不想显示该按钮。
是否有一种简单的方法来检测溢出,或者有更好的方法?
像http://jsfiddle.net/Skooljester/jWRRA/1/这样的代码有用吗?它只是检查内容的高度,并将其与容器的高度进行比较。如果大于,则可以在代码中添加“显示更多”按钮。
更新:增加了在容器顶部创建“Show More”按钮的代码。
您可以检查相对于偏移父函数的边界。
// 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;
}
如果你传递给它一个元素,它会告诉你它的边界是否完全在容器中,如果没有显式提供容器,它将默认为元素的offset父元素。
如果你正在使用jQuery,你可能会尝试一个技巧:使外部div溢出:隐藏和内部div内容。然后使用.height()函数来检查内部div的高度是否大于外部div的高度。我不确定它是否会工作,但请尝试一下。
比较元素。scrollHeight到元素。clientHeight应该做这个任务。
下面是来自MDN解释Element的图片。scrollHeight和Element.clientHeight。
你应该考虑的另一个问题是JS不可用。考虑渐进增强或优雅降级。我建议:
默认添加“更多按钮” 默认添加溢出规则 隐藏按钮,并在JS中进行CSS修改后比较元素。scrollHeight到element.clientHeight
元素可以垂直、水平或同时进行溢出。如果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;
}
下面是一个使用带有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);
});
来源:jsfiddle.net上的框架和扩展
setTimeout(function(){
isOverflowed(element)
},500)
function isOverflowed(element){
return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}
这对我来说很管用。谢谢你!
这是对我有用的jQuery解决方案。clientWidth等没有工作。
function is_overflowing(element, extra_width) {
return element.position().left + element.width() + extra_width > element.parent().width();
}
如果这不起作用,请确保元素的父元素具有所需的宽度(就个人而言,我必须使用parent().parent())。位置相对于父节点。我还包含了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();
}
});
希望这能有所帮助。
如果您只想显示更多内容的标识符,那么您可以使用纯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: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>
jquery的替代答案是使用[0]键来访问原始元素,如:
if ($('#elem')[0].scrollHeight > $('#elem')[0].clientHeight){
出于封装原因,我扩展了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
}
为条件可见性添加一个事件监听器:
document.getElementById('parent').addEventListener('scroll', (e) => {
const childEl = document.getElementById('child');
childEl.style.visibility = e.target.scrollTop > 0 ? 'visible' : 'hidden';
});