102

How can you detect if text has overflown? For example, the following text is longer than it's div container allows. How can I detect this in javascript?

<div style="max-width: 100px; white-space:nowrap; overflow: hidden;">
    Lorem ipsum dolor sit amet, consectetur adipisicing elit
</div>
isherwood
  • 58,414
  • 16
  • 114
  • 157
Brett
  • 2,706
  • 7
  • 33
  • 49

4 Answers4

167

If you are using jQuery, you can try comparing the div's width to its scrollWidth.

if ($('#div-id')[0].scrollWidth >  $('#div-id').innerWidth()) {
    //Text has over-flown
}
J.Ko
  • 964
  • 12
  • 26
Nathan Bell
  • 2,364
  • 2
  • 18
  • 16
  • 28
    I had to also use `innerWidth()` instead of `width()` to account for paddings. – lanan Jul 07 '12 at 17:32
  • 1
    I use the same technique, but comparing the `scrollHeight` against `innerHeight()` – Alejandro Fiore Oct 17 '13 at 03:07
  • 4
    Edited to use innerWidth() instead of width() – Nathan Bell Aug 17 '14 at 06:05
  • 3
    AND... It is always better to use "jQuery" instead of "$"... :) – TheCuBeMan Nov 03 '14 at 10:21
  • 8
    @TheCuBeMan: The actual best approach is to wrap the jQuery code in a closure taking `$` and pass it `jQuery` as an argument. This is what jQuery Core does. e.g. `(function ($) { // code })(jQuery);` – wizonesolutions Dec 08 '14 at 20:08
  • @wizonesolutions but what happens when you have other JS framework(s) on the same page/site and it already uses the $ sign?? I still say that it is best to use the jQuery object name in order to avoid collisions etc. – TheCuBeMan Dec 09 '14 at 08:23
  • 3
    @TheCuBeMan But that pattern does use jQuery. It aliases it to $ in the closure scope. Collision-free. – wizonesolutions Dec 09 '14 at 12:51
  • @wizonesolutions Let me ask you this - in this way, does it mean that the $ character will be used to refer to the jQuery object (and functionality)? because if it does, then there's the possibility of the collision. Let's say that there is another framework that is already utilizing this character for its purposes, then this code will override it and create the problem. Even if jQuery is referenced before the other framework, then the latter will be the one to utilize the $ character, therefore the code did nothing. Why not just always rely on "jQuery" as the only reference to its library?... – TheCuBeMan Dec 09 '14 at 19:25
  • 3
    @TheCuBeMan But only within the IIFE (Immediately-Invoked Function Expression, the pattern I showed above). Outside of the IIFE, if you have called `jQuery.noConflict()`, there is no problem. The closure receives `jQuery` as its argument and it takes a parameter called `$`, so `$` within the IIFE points to `jQuery`. This is compatible with your advice always to use `jQuery`; it simply aliases it. It doesn't affect the global scope. One can also pass references to other libraries to the IIFE by adding more parameters and arguments. – wizonesolutions Dec 10 '14 at 09:41
  • 1
    @TheCuBeMan There are several assumptions I've made in my solution. i.e.: 1) The jQuery object has been assigned to $ in someway, such as being passed into the scope or being set at the global scope. 2) That the selector used returns one and exactly one element. Otherwise the array index used (0) creates problems when the object doesn't exist, or when there are multiple matched elements (this snippet only considers the first element matched). I admit that, in an effort to provide a clear and concise solution to the question, solving these issues are left as an exercise for the reader. – Nathan Bell Mar 03 '15 at 21:51
  • 1
    doesn't work in ie11 – DrewB Mar 13 '15 at 16:01
  • Can you be more specific @DrewB – Nathan Bell Apr 15 '15 at 17:47
  • It worked great in chrome, firefox and iOS but not on ie11. Was a month ago so I don't recall which part of the solution wasn't working. I ended up using the top answer from http://stackoverflow.com/questions/143815/how-to-determine-using-javascript-if-html-element-has-overflowing-content/143889#143889 instead. – DrewB Apr 15 '15 at 19:54
  • If you can reproduce the problem please provide a jsfiddle and I can update my answer – Nathan Bell Apr 15 '15 at 20:26
  • 2
    Actually should use `.clientWidth`. All the rest are not accurate. `.width`, `.innerWidth`, etc.. always return a number that is lower than `.scrollWidth`. – Liran Funaro May 25 '17 at 15:31
  • I second @LiranFunaro's suggestion. In my case `innerWidth()` returned a float, which deviated `0.072` from `scrollWidth`, therefore the statement would always evaluate to true. – YTZ Jul 01 '21 at 23:26
20

You can detect whether text will fit before you display the element. So you can use this function which doesn't require the element to be on screen.

function textWidth(text, fontProp) {
    var tag = document.createElement('div')
    tag.style.position = 'absolute'
    tag.style.left = '-99in'
    tag.style.whiteSpace = 'nowrap'
    tag.style.font = fontProp
    tag.innerHTML = text

    document.body.appendChild(tag)
    var result = tag.clientWidth
    document.body.removeChild(tag)
    return result;
}

Usage:

if (textWidth('Text', 'bold 13px Verdana') > elementWidth) {
    ...
}
ashleedawg
  • 20,365
  • 9
  • 72
  • 105
artnikpro
  • 5,487
  • 4
  • 38
  • 40
  • This worked for me when scrollWidth is zero, which seems to happen sometimes (haven't figured out why...) – dlchambers Apr 07 '18 at 16:36
  • 1
    So very helpful! I basically just slapped together my own, simplified version of [Fitty.js](https://github.com/rikschennink/fitty), to loop through a page's elements and if any are larger than their container, decrease the font 1px at a time until it fits. :-) – ashleedawg Nov 27 '19 at 10:17
  • worked just fine for me – Ahmadreza_HK Jun 08 '22 at 12:11
6

jQuery plugin for checking if text has overflown, not written very well, but works as it suppose to be working. Posting this because I didn't find a working plugin for this anywhere.

jQuery.fn.hasOverflown = function () {
   var res;
   var cont = $('<div>'+this.text()+'</div>').css("display", "table")
   .css("z-index", "-1").css("position", "absolute")
   .css("font-family", this.css("font-family"))
   .css("font-size", this.css("font-size"))
   .css("font-weight", this.css("font-weight")).appendTo('body');
   res = (cont.width()>this.width());
   cont.remove();
   return res;
}
Flash
  • 466
  • 6
  • 16
  • 1
    nice plugin, but the correct past tense of 'overflow' is 'overflowed' =) – roryok Aug 16 '18 at 07:20
  • This works pretty well! Could you please explain how it works? As far as I can tell, this is better than the `isEllipsisActive` function you can find here on SO because it works even with some edge cases when the width of the overflowed text is the same as the width of the text without `overflow:hidden;` and `text-overflow: ellipsis` – tonix Jul 26 '19 at 06:38
  • This works, but only for elements that contain single line of text. For elements with a fixed width that span multiple lines, modify this function to test for height instead of width. – Mahn Apr 29 '20 at 16:58
0

For illustrative purposes let's say your div has id="d", then you could do:

var d = document.getElementById('d'),
    dWider;
d.style.maxWidth = '9999em';
d.style.overflow = 'visible';
dWider = d.offsetWidth > 100;
d.style.maxWidth = '100px';
d.style.overflow = 'hidden';

Then the var dWider will be true if the text overflows and false if it doesn't.

mVChr
  • 49,587
  • 11
  • 107
  • 104