I made an image for this question to make it easier to understand.
Is it possible to create an ellipsis on a
EDIT: Came across Shave which is JS plugin that does multi line text truncation based on a given max-height really well. It uses binary search to find the optimum break point. Definitely worth investigating.
ORIGINAL ANSWER:
I had to come up with a vanilla JS solution for this problem. In the case that I had worked on, I had to fit a long product name into limited width and over two lines; truncated by ellipsis if needed.
I used answers from various SO posts to cook up something that fit my needs. The strategy is as follows:
Code sample:
/**
* Helper to get the average width of a character in px
* NOTE: Ensure this is used only AFTER font files are loaded (after page load)
* @param {DOM element} parentElement
* @param {string} fontSize
*/
function getAverageCharacterWidth(parentElement, fontSize) {
var textSample = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()";
parentElement = parentElement || document.body;
fontSize = fontSize || "1rem";
var div = document.createElement('div');
div.style.width = "auto";
div.style.height = "auto";
div.style.fontSize = fontSize;
div.style.whiteSpace = "nowrap";
div.style.position = "absolute";
div.innerHTML = textSample;
parentElement.appendChild(div);
var pixels = Math.ceil((div.clientWidth + 1) / textSample.length);
parentElement.removeChild(div);
return pixels;
}
/**
* Helper to truncate text to fit into a given width over a specified number of lines
* @param {string} text Text to truncate
* @param {string} oneChar Average width of one character in px
* @param {number} pxWidth Width of the container (adjusted for padding)
* @param {number} lineCount Number of lines to span over
* @param {number} pad Adjust this to ensure optimum fit in containers. Use a negative value to Increase length of truncation, positive values to decrease it.
*/
function truncateTextForDisplay(text, oneChar, pxWidth, lineCount, pad) {
var ellipsisPadding = isNaN(pad) ? 0 : pad;
var charsPerLine = Math.floor(pxWidth / oneChar);
var allowedCount = (charsPerLine * (lineCount)) - ellipsisPadding;
return text.substr(0, allowedCount) + "...";
}
//SAMPLE USAGE:
var rawContainer = document.getElementById("raw");
var clipContainer1 = document.getElementById("clip-container-1");
var clipContainer2 = document.getElementById("clip-container-2");
//Get the text to be truncated
var text=rawContainer.innerHTML;
//Find the average width of a character
//Note: Ideally, call getAverageCharacterWidth only once and reuse the value for the same font and font size as this is an expensive DOM operation
var oneChar = getAverageCharacterWidth();
//Get the container width
var pxWidth = clipContainer1.clientWidth;
//Number of lines to span over
var lineCount = 2;
//Truncate without padding
clipContainer1.innerHTML = truncateTextForDisplay(text, oneChar, pxWidth, lineCount);
//Truncate with negative padding value to adjust for particular font and font size
clipContainer2.innerHTML = truncateTextForDisplay(text, oneChar, pxWidth, lineCount,-10);
.container{
display: inline-block;
width: 200px;
overflow: hidden;
height: auto;
border: 1px dotted black;
padding: 10px;
}
Untruncated
This is super long text which needs to be clipped to the correct length with ellipsis spanning over two lines
Truncated
Truncated with Padding Tweak
PS:
PPS: Just realised this is very similar to the approach as suggested by @DanMan and @st.never. Checkout the code snippets for an implementation example.