Check if an element's content is overflowing?

214,555

Solution 1

If you want to show only an identifier for more content, then you can do this with pure CSS. I use pure scrolling shadows for this. The trick is the use of background-attachment: local;. Your css looks like this:

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

The code and the example you can find on http://dabblet.com/gist/2462915

And an explanation you can find here: http://lea.verou.me/2012/04/background-attachment-local/.

Solution 2

The element may be overflown vertically, horizontally or both. This function will return you a boolean value if the DOM element is overflown:

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 example:

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

Solution 3

Comparing element.scrollHeight to element.clientHeight should do the task.

Below are the images from MDN explaining Element.scrollHeight and Element.clientHeight.

Scroll Height

Client Height

Solution 4

I made a multipart codepen demonstrating the above answers ( e.g. using overflow hidden and height) but also how you would expand / collapse overflowed items

Example 1: https://codepen.io/Kagerjay/pen/rraKLB ( Real simple example, no javascript, just to clip overflowed items)

Example 2: https://codepen.io/Kagerjay/pen/LBErJL (Single event handler show more / showless on overflowed items)

Example 3: https://codepen.io/Kagerjay/pen/MBYBoJ (Multi event handler on many show more/ show less on overflowed items)

I have attached example 3 below as well, I use Jade/Pug so it might be a tad verbose. I suggest checking out the codepens I've made its simpler to grasp.

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

Solution 5

Would something like this: http://jsfiddle.net/Skooljester/jWRRA/1/ work? It just checks the height of the content and compares it to the height of the container. If it's greater than you can put in the code to append a "Show more" button.

Update: Added the code to create a "Show More" button at the top of the container.

Share:
214,555

Related videos on Youtube

Harry
Author by

Harry

Updated on July 20, 2022

Comments

  • Harry
    Harry almost 2 years

    What's the easiest way to detect if an element has been overflowed?

    My use case is, I want to limit a certain content box to have a height of 300px. If the inner content is taller than that, I cut it off with an overflow. But if it is overflowed I want to show a 'more' button, but if not I don't want to show that button.

    Is there an easy way to detect overflow, or is there a better method?

  • Bergi
    Bergi over 12 years
    Yeah, but according to quirksmode it works for the most - and is much simpler than the other posted solutions.
  • Marat Tanalin
    Marat Tanalin over 12 years
    @Harry: It's supported in all current browsers (desktop ones at least), so it doesn't matter that it's formally nonstandard.
  • Sygmoral
    Sygmoral almost 11 years
    Great solution! Here's a jQuery variant (to be used with $("#element").overflown()): $.fn.overflown=function(){var e=this[0];return e.scrollHeight>e.clientHeight||e.scrollWidth>e.clientWidth;}
  • koppor
    koppor almost 11 years
    Here, these properties always have the same values.
  • carefulnow1
    carefulnow1 about 7 years
    How is this different from micnic's answer?
  • Yasir
    Yasir about 7 years
    @micnic hi , I am using ionic2 and trying to do the same thing... but the function returns true always... is there a different way to do things in angular 2
  • micnic
    micnic about 7 years
    @DavidBracoly, this function is for pure DOM API, I do not have experience with Ionic/Angular, I guess you should get the original DOM Element and use this function
  • DreamTeK
    DreamTeK about 6 years
    Nice idea but in your example the background (shadow) would be behind the text!
  • Jared
    Jared about 6 years
    Great trick, however in Chrome it shows only static shadow on the bottom, it never disappears and the upper shadow never shows
  • Reza
    Reza over 5 years
    Only for Firefox: element.addEventListener ("overflow", () => log( "overflow" ), false); Reference: overflow event
  • Sebastian Simon
    Sebastian Simon about 3 years
    Wow, this even works e.g. in a grid, where the bounding client rect doesn’t include overflowing content.
  • borisdiakur
    borisdiakur almost 3 years
    /* Opera doesn't support this in the shorthand */ -> I'm on Opera and it seems to work for me.
  • J_sdev
    J_sdev almost 3 years
    This is the only solution on this entire thread that worked. Thanks for posting.
  • Flow Overstack
    Flow Overstack about 2 years
    Note for all the trigger-happy down-voters: The question was: "What is the easiest way to detect if an element's been overflowed?". It didn't say something like "programmatically", or "using JavaScript only" etc. This answers it!