Is it possible in HTML to create an "intelligent" overflow effect where text is truncated and replaced with an ellipsis "..." followed by a link to view the full content?

I have a <div> that has a limited size, and I am looking for a way to display multiline text in it. If the text exceeds the available space, I would like to add "..." at the end along with a link to view the full content on another page.

Is there a way to achieve this using Javascript/CSS? I tried researching but couldn't find a clear solution.

It seems like there is a CSS property text-overflow: ellipsis;, but adding a link on the ellipsis might not be possible.


The answer provided here is close, but there are instances where only a part of the ellipsis appears if the text starts to overflow.


Library requirements: I am open to using jQuery (albeit reluctantly), but I would prefer a cross-browser solution that doesn't rely on any specific framework.

Answer №1

This example showcases a simple method to iterate through elements marked with the class .smart-overflow. It introduces a clickable a element with the class ellipsis-link only when the content is truncated. The attached link triggers an event listener that reveals the hidden content which was initially concealed using overflow: hidden. Please note that this solution is tailored for single-line text. For multiple lines and broader browser compatibility, refer to the alternative below.

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 an ellipsis. This is a longer string of text which should have an ellipsis.</p>
<p class="smart-overflow">Another string of text which should have an ellipsis. Another string of text which should have an ellipsis.</p>

In the scenario above, implementing text-overflow: ellipsis necessitates the usage of white-space: nowrap for it to operate effectively, restricting its functionality to a single line of text.

If you require multi-line support, consider employing the following methodology for modern browsers. If encountering any issues, explore the jQuery-based solution below for comprehensive browser backing.

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 an ellipsis. This is a longer string of text which should have an ellipsis.</p>
<p class="smart-overflow">Another multi-line string of text which should have an ellipsis. Another multi-line string of text which should have an ellipsis.</p>

JQuery provides a multi-line approach with comprehensive browser coverage utilizing 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 an ellipsis. This is a longer string of text which should have an ellipsis.</p>
<p class="smart-overflow">Another multi-line string of text which should have an ellipsis. Another multi-line string of text which should have an ellipsis.</p>

Answer №2

Looking for some amazing jQuery plugins to enhance your website? Take a look at these:

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

I once developed a piece of code that integrates trunk8 with ellipsis, creating responsive links in the process.

(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);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Combining multiple API requests using NodeJS

I'm currently experimenting with SteamAPI to enhance my understanding of NodeJS. My aim is to retrieve game information after making an initial request to obtain the player's profile and storing the game IDs in an array. However, I am facing a ch ...

Dealing with Sideways Overflow Using slideDown() and slideUp()

Attempting to use slideUp() and slideDown() for an animated reveal of page elements, I encountered difficulty when dealing with a relatively positioned icon placed outside the element. During these animations, overflow is set to hidden, resulting in my ico ...

Refresh your webpage with new content and modified URLs without the need to reload using window.history.pushState

Hey everyone, I'm looking to incorporate window.history.pushState into my website, but I'm unsure of how to go about it... What I'm aiming for is to have a page dashboard.php and update the URL to dashboard.php?do=edit&who=me, while loa ...

Tracking mouse movement: calculating mouse coordinates in relation to parent element

I am facing an issue with a mousemove event listener that I have set up for a div. The purpose of this listener is to track the offset between the mouse and the top of the div using event.layerY. Within this main div, there is another nested div. The prob ...

javascript utilizing underscorejs to categorize and aggregate information

Here is the data I have: var dates = [ {date: "2000-01-01", total: 120}, {date: "2000-10-10", total: 100}, {date: "2010-02-08", total: 100}, {date: "2010-02-09", total: 300} ]; My goal is to group and sum the totals by year like this. ...

Iterating through an array in Javascript to create a new array filled with objects

Is there a way to iterate through an array of strings and convert them into an array of objects based on their values? For instance, if the array looks like this: [a,a,a,b,b,c,d] I aim to cycle through the array and create objects with key-value pairs t ...

Please be patient for the PayPal script to load on the nextjs page

I've encountered an issue with my code that is meant to display PayPal buttons <Head> <script src="https://www.paypal.com/sdk/js?client-id=KEY"></script> </Head> The PayPal buttons are loaded within the ...

Sending data to API using AngularJS Http Post

Upon clicking "Add new User", a modal pop-up will appear with a form containing a text field and a checkbox. However, upon clicking the create button, the data is not being posted to the API and the modal pop-up remains open without closing. I would like ...

Issue with a input element having relative positioning within a flexbox

Objective: Aim to align the middle DIV (MIDDLE) within a flexbox row in the center. Issue: The right element includes an input element with relative positioning. Consequently, the middle DIV element (MIDDLE) is no longer centered but instead shifted to th ...

What is the best way to interact with a html element using the onclick event in Selenium?

Struggling to find the xpath for a link on a webpage. The HTML code for the link is as follows: <td style="width: 50%; text-align: right; vertical-align: middle"> <img id="ctl00_ContentPlaceHolder1_RadGrid1_ctl00_ctl02_ctl00_AddRecord1" ...

Tips for changing input field type from "password" to "text" in Angular?

Is there a way to dynamically convert an input field with type="password" to type="text" in Angular? In my demo, I have two input fields labeled Mobile no and Re-enter mobile number. I want these fields to change to type="text" if the user inputs the same ...

How can I transform this statement into a higher-order function that offers a resource instead of using an object for initialization and destruction?

Starting with this code snippet: convert utilizes svgInjector to start and terminate a resource. export async function convert( serializedSvg: string, svgSourceId: string, containerId: string ): Promise<string> { const svgInjector = new SvgI ...

Tips for integrating highcharts plugins with highcharts-vue (highcharts vue wrapper)

Currently, I am utilizing the Vue wrapper for Highcharts called highcharts-vue(https://github.com/highcharts/highcharts-vue). However, I am facing an issue where I need to detect the event of a right mouse click (contextmenu) on the chart. To address this, ...

Is there a way to calculate the number of days between two selected dates using the bootstrap date range picker?

I recently implemented the bootstrap daterange picker for selecting start and end dates, and it's been working perfectly. However, I now have a requirement to display the count of days selected. Here's my current code: $('input[name="datera ...

Style HTML in VSCode just like you do in Visual Studio

Trying to figure out how to configure VSCode to format HTML (and other markup files like .vue) in a similar way to Visual Studio. In Visual Studio, if I write something like: <div id="testid" class="test" style="display: block;"> <p class="p ...

Creating a rectangular pyramid using three.js r68: a step-by-step guide

Currently working on r68, I'm in search of a modern example showcasing the creation of a rectangular pyramid that will allow me to implement THREE.MeshFaceMaterial(). Many existing examples are outdated and lead to errors with my current setup. My re ...

What is the process for retrieving data on the server side using node.js that has been sent from the frontend via the post method

After diving into learning node.js with the express framework, I encountered a roadblock. I'm experimenting with a basic query search webapp and trying to send some data (a boolean named all) from front-end plain javascript via ajax to the server sid ...

Tips for saving HTML code within a concealed field utilizing jQuery

What is the best way to store a string with HTML tags in a hidden field using jQuery? I am attempting to use this code, but it's not functioning as expected: var terms = $('#TermsAndCondition').val(); alert($('#hdnTerms').val( ...

Calculator screen filled with numbers overflowing beyond its boundaries

I'm encountering an issue with my calculator created in create-react-app where the numbers are overflowing off the screen. Specifically, when inputting very large numbers like 11111111111111111111111111111111, they exceed the output container. I am lo ...

Ways to invoke a specific component within ReactDOM.render in React

Currently, I am facing an issue where 2 components need to be rendered present in a single div using myProject-init.js, but both are getting called at the same time. In myProject-init.js file: ReactDOM.render( <div> <component1>in compone ...