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

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

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

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

【问题讨论】:

标签: javascript css 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;
                      }
                      

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

                      【讨论】:

                        猜你喜欢
                        • 2010-09-13
                        • 2017-09-13
                        • 2020-04-11
                        • 1970-01-01
                        • 2022-01-04
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多