Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Smart" overflow in HTML: is there any way to put ellipsis "..." with a link at the end to view entire content?

I have a <div> of constrained size, and I want to put multiline text in it, but if it's going to overflow, I'd like to put a "..." at the end with a link to view the entire content on another page.

Is this doable in Javascript/CSS? I tried searching a bit but I'm not sure what to look for.

Hmm -- looks like there's a CSS text-overflow: ellipsis; but I don't think I can put a link on the ellipsis.


this answer is really close but there are cases where if it just starts to overflow then only part of the ellipsis shows up.


library requirements: I can use jQuery (somewhat reluctantly), would prefer a no-framework-dependency cross-browser solution.

like image 739
Jason S Avatar asked Dec 29 '15 21:12

Jason S


2 Answers

Here is a basic example that iterates over elements with a class of .smart-overflow. It adds a clickable a element with a class of ellipsis-link only if the content is clipped. The link has a click event listener that will reveal the hidden content that was hidden with overflow: hidden. This example only works for a single line. See the alternative example below for an approach that works for multiple lines in supported browsers.

var elements = document.querySelectorAll('.smart-overflow');
Array.prototype.forEach.call(elements, function (el) {
  var link = document.createElement('a');
  link.href = '#'; link.className = 'ellipsis-link';
  
  if (el.offsetWidth < el.scrollWidth) {
    link.addEventListener('click', function (e) {
      e.preventDefault();
      el.classList.remove('smart-overflow');
    });
    el.appendChild(link);
  }
});
p {
  width: 200px;
  position: relative;
}
.smart-overflow {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
a.ellipsis-link {
  display: none;
}
.smart-overflow a.ellipsis-link {
  display: block;
  position: absolute;
  right: 0; bottom: 0;
  width: 1.2em;
  height: 100%;
  cursor: pointer;
}
<p class="smart-overflow">No ellipsis.</p>
<p class="smart-overflow">This is a longer string of text which should have ellipsis. This is a longer string of text which should have ellipsis.</p>
<p class="smart-overflow">Another string of text which should have ellipsis. Another string of text which should have ellipsis.</p>

In the example above, text-overflow: ellipsis requires white-space: nowrap in order to work which means that it only works for a single line.

If you want support for multiple lines, you can do something like this in supported browsers. If that doesn't work, see the jQuery solution below for full browser support.

var elements = document.querySelectorAll('.smart-overflow');
Array.prototype.forEach.call(elements, function (el) {
  var link = document.createElement('a');
  link.href = '#'; link.className = 'ellipsis-link';

  link.addEventListener('click', function (e) {
    e.preventDefault();
    el.classList.remove('smart-overflow');
  });
  el.appendChild(link);
});
p {
  width: 200px;
  position: relative;
}
.smart-overflow {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;  
  max-height: 2.2em;
  overflow: hidden;
  position: relative;
}
a.ellipsis-link {
  display: none;
}
.smart-overflow a.ellipsis-link {
  display: block;
  position: absolute;
  right: 0; bottom: 0;
  width: 4.2em;
  height: 1.2em;
  cursor: pointer;
}
<p class="smart-overflow">No ellipsis.</p>
<p class="smart-overflow">This is a longer multi-line string of text which should have ellipsis. This is a longer string of text which should have ellipsis.</p>
<p class="smart-overflow">Another multi-line string of text which should have ellipsis. Another multi-line string of text which should have ellipsis.</p>

jQuery multi-line alternative with full browser support using this library.

$('.smart-overflow').dotdotdot({
  ellipsis: '',
  wrap: 'word',
  callback: function(isTruncated, content) {
    var self = this;

    if (isTruncated) {
      $(this).append($('<a/>', {
        class: 'ellipsis-link',
        text: '...',
        href: '#',
        click: function(e) {
          e.preventDefault();
          $(this).remove();
          $(self).removeClass('smart-overflow is-truncated').trigger("destroy");
        }
      }));
    }
  }
});
p { width: 200px; }
.smart-overflow { max-height: 2.8em; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery.dotdotdot/1.7.4/jquery.dotdotdot.min.js"></script>
<p class="smart-overflow">No ellipsis.</p>
<p class="smart-overflow">This is a longer multi-line string of text which should have ellipsis. This is a longer string of text which should have ellipsis.</p>
<p class="smart-overflow">Another multi-line string of text which should have ellipsis. Another multi-line string of text which should have ellipsis.</p>
like image 99
Josh Crozier Avatar answered Sep 20 '22 23:09

Josh Crozier


Check out these jQuery plugins:

https://github.com/jjenzz/jquery.ellipsis https://github.com/rviscomi/trunk8

Here's some code I wrote awhile back, that wraps trunk8, to make the ellipsis in to links and to make them responsive as well.

(function($, window, document, undefined) {

  'use strict';

  window.seeMore = function() {
    function addSeeMoreLinks() {
      $article.find('p').trunk8(options).each(function() {
        var $this = $(this);

        if (0 === $this.find('.trunk8').length) {
          $this.append(' <a href="#" class="seeMore">see more</a>.');
        }
      });
    }

    function removeSeeMoreLinks() {
      $article.find('p').each(function() {
        $(this).find('.seeMore').remove();
      });
    }

    function setupSeeMoreLinks() {
      addSeeMoreLinks();
      $(window).resize(function() {
        removeSeeMoreLinks();
        addSeeMoreLinks();
      });
    }

    var
      $article = $('.blogArticleList article'),
      options = {
        lines: 6,
        fill: '&hellip; <a href="#" class="trunk8">see more</a>.',
        tooltip: false
      };

    setupSeeMoreLinks();
  };

  if (window.addEventListener && $().trunk8) {
    window.seeMore();
  }

})(jQuery, window, document);
like image 24
David Bradshaw Avatar answered Sep 19 '22 23:09

David Bradshaw