title is an attribute to represent advisory information related to the element it belongs to, typically presented as a tooltip. Sometimes we also use the title attribute to show omitted text when it's not suitable to wrap text and it overflows the container.

And here comes the question. If we simply add the title attribute, the tooltip will show regardless of whether the text overflows, while what we want is to show the tooltip only if the text overflows.

To achieve that, we may use jQuery with jQuery UI, or jQuery only, or even with vanilla JavaScript.

  1. Firstly, if we do not want tooltip to be shown when text fits its container, we should

    • set title attribute with no value;
    • or not add the title attribute at all.

    Otherwise we cannot control its behavior as browsers natively show tooltips for elements with title attribute.

    Though we still need to mark elements which need to show tooltips when text within them overflow. For example, adding data-title attribute, using title attribute without value, or using a class name.

    <!--    title attribute with no value -->
    <div><span title>Long Text Really Long</span></div>
    <!-- or data-title attribute with no value -->
    <div><span data-title>Long Text Really Long</span></div>
    <!-- or data-title attribute with value -->
    <div><span data-title="Long Text Really Long">Long Text Really Long</span></div>
    <!-- or title attribute with value if using jQuery UI Tooltip widget -->
    <!-- jQuery UI Tooltip widget removes content in title attribute when hovered. -->
    <div><span title="Long Text Really Long">Long Text Really Long</span></div>
    
  2. Then we may store tooltip content in another attribute such as data-title or not use an attribute at all if all we want to show in a tooltip is the text content of the element.

    DOM provides different ways for accessing data stored in different places, assuming the element we are dealing with is named as el:

    • Accessing title attribute:
      via el.title, or $(el).attr('title') in jQuery;
    • Accessing data-title attribute:
      via el.getAttribute('data-title'), or $(el).data('title') in jQuery;
    • Accessing text content of the element:
      via el.textContent, or $(el).text() in jQuery;
    var title = el.title || el.getAttribute('data-title') || el.textContent;
    // or in jQuery
    var $el = $(el);
    var title = $el.attr('title') || $el.data('title') || $el.text();
    
  3. Next, we need a way to tell whether the content in a container overflows.

    To learn the sizing of an element, we have Element.getBoundingClientRect(), Element.clientWidth, Element.offsetWidth, Element.scrollWidth, and their Height, Left, Top counterparts.

    offsetWidth and offsetHeight relate to element's border-box, clientWidth and clientHeight relate to padding-box (without the size of scrollbar if any), and scrollWidth and scrollHeight relate to padding-box plus size of scrollbar and overflowed content.

    Here for comparing the width of the element itself and the width of the content of the element, we compare scrollWidth with clientWidth, if scrollWidth is larger than clientWidth, the text overflows.

    var overflowed = container.scrollWidth > container.clientWidth;
    
  4. Finally, show the tooltip only if the text overflows.

    • Using jQuery and jQuery UI
    $(document).tooltip({
        items: '[title]',  // the default
                           // or '[data-title]'
                           // depending on HTML structure
        content: function () {
            // The container should be a `display: block` element,
            // as overflow means a `display: inline` element excedes
            // the size of a `display: block` element.
            var container = this;  // or `this.parentNode`
                                   // depending on where `title` attribute is set
                                   // In any case, the element with `display: block`.
    
            var title = this.title || this.getAttribute('data-title') || this.textContent;
    
            var overflowed = container.scrollWidth > container.clientWidth;
    
            // Return an empty string as content won't show the tooltip
            return overflowed ? title : '';
        }
    });
    
    • Using jQuery only
    // filter on '[title]' or '[data-title]' depending on HTML structure
    $(document)
        .on('mouseover', '[title]', function () {
            var container = this;  // or `this.parentNode`
            var title = this.title || this.getAttribute('data-title') || this.textContent;
            var overflowed = container.scrollWidth > container.clientWidth;
    
            this.title = overflowed ? title : '';
        })
        .on('mouseout', '[title]', function() {
            this.title = '';
        });
    
    • Using vanilla JavaScript
    document.addEventListener('mouseover', function(event) {
        var target = event.target;
        // Check support for matches() at <http://caniuse.com/#feat=matchesselector>
        if (!target.matches('[title]')) return;
    
        var container = this;  // or `this.parentNode`
        var title = target.title || target.getAttribute('data-title') || target.textContent;
        var overflowed = container.scrollWidth > container.clientWidth;
    
        target.title = overflowed ? title : '';
    });
    
    document.addEventListener('mouseout', function(event) {
        var target = event.target;
        // Check support for matches() at <http://caniuse.com/#feat=matchesselector>
        if (!target.matches('[title]')) return;
        // 'mouseout' event fires even when move from parent to child element
        if (event.relatedTarget.parentNode === target) return;
    
        target.title = '';
    });
    

Some side notes here, in the examples above, to take advantage of event bubbling and delegated events, mouseover and mouseout events are used, there are also mouseenter and mouseleave events which are similar, but they do not bubble, thus not suitable for event delegation.

I thinks the ability to use event delegation is important here, as there may be many elements with tooltips on a page. What's more, they might be added and/or removed dynamically. Thus using a single event handler for dealing with all these tooltips definitely improves performance.

Besides, I also made a JSFiddle demo at https://jsfiddle.net/pallxk/ket3mpy6/.